Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libraries/Common/src/Internal/Cryptography/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public static int GetPaddingSize(this SymmetricAlgorithm algorithm)
return algorithm.BlockSize / 8;
}

internal static bool TryCopyToDestination(ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten)
internal static bool TryCopyToDestination(this ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten)
{
if (source.TryCopyTo(destination))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ internal static partial class Interop
{
internal static partial class Crypto
{
[DllImport(Libraries.CryptoNative)]
private static extern SafeEvpPKeyHandle CryptoNative_EvpPKeyCreateRsa(IntPtr rsa);

internal static SafeEvpPKeyHandle EvpPKeyCreateRsa(IntPtr rsa)
{
Debug.Assert(rsa != IntPtr.Zero);

SafeEvpPKeyHandle pkey = CryptoNative_EvpPKeyCreateRsa(rsa);

if (pkey.IsInvalid)
{
pkey.Dispose();
throw CreateOpenSslCryptographicException();
}

return pkey;
}

[DllImport(Libraries.CryptoNative)]
private static extern SafeEvpPKeyHandle CryptoNative_RsaGenerateKey(int keySize);

Expand Down Expand Up @@ -171,16 +189,5 @@ ref MemoryMarshal.GetReference(signature),
Debug.Assert(ret == -1);
throw CreateOpenSslCryptographicException();
}

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyGetRsa")]
internal static extern SafeRsaHandle EvpPkeyGetRsa(SafeEvpPKeyHandle pkey);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeySetRsa")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool EvpPkeySetRsa(SafeEvpPKeyHandle pkey, SafeRsaHandle rsa);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeySetRsa")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool EvpPkeySetRsa(SafeEvpPKeyHandle pkey, IntPtr rsa);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;

Expand All @@ -12,6 +13,30 @@ internal static partial class Crypto
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyCreate")]
internal static extern SafeEvpPKeyHandle EvpPkeyCreate();

[DllImport(Libraries.CryptoNative)]
private static extern SafeEvpPKeyHandle CryptoNative_EvpPKeyDuplicate(
SafeEvpPKeyHandle currentKey,
EvpAlgorithmId algorithmId);

internal static SafeEvpPKeyHandle EvpPKeyDuplicate(
SafeEvpPKeyHandle currentKey,
EvpAlgorithmId algorithmId)
{
Debug.Assert(!currentKey.IsInvalid);

SafeEvpPKeyHandle pkey = CryptoNative_EvpPKeyDuplicate(
currentKey,
algorithmId);

if (pkey.IsInvalid)
{
pkey.Dispose();
throw CreateOpenSslCryptographicException();
}

return pkey;
}

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyDestroy")]
internal static extern void EvpPkeyDestroy(IntPtr pkey);

Expand All @@ -20,5 +45,173 @@ internal static partial class Crypto

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_UpRefEvpPkey")]
internal static extern int UpRefEvpPkey(SafeEvpPKeyHandle handle);

[DllImport(Libraries.CryptoNative)]
private static extern unsafe SafeEvpPKeyHandle CryptoNative_DecodeSubjectPublicKeyInfo(
byte* buf,
int len,
int algId);

[DllImport(Libraries.CryptoNative)]
private static extern unsafe SafeEvpPKeyHandle CryptoNative_DecodePkcs8PrivateKey(
byte* buf,
int len,
int algId);

internal static unsafe SafeEvpPKeyHandle DecodeSubjectPublicKeyInfo(
ReadOnlySpan<byte> source,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Since CryptoNative_DecodeSubjectPublicKeyInfo requires buf != nullptr and len > 0, may want a Debug.Assert(!source.IsEmpty); statement here.

(Same comment for related methods in this file.)

EvpAlgorithmId algorithmId)
{
SafeEvpPKeyHandle handle;

fixed (byte* sourcePtr = source)
{
handle = CryptoNative_DecodeSubjectPublicKeyInfo(
sourcePtr,
source.Length,
(int)algorithmId);
}

if (handle.IsInvalid)
{
handle.Dispose();
throw CreateOpenSslCryptographicException();
}

return handle;
}

internal static unsafe SafeEvpPKeyHandle DecodePkcs8PrivateKey(
ReadOnlySpan<byte> source,
EvpAlgorithmId algorithmId)
{
SafeEvpPKeyHandle handle;

fixed (byte* sourcePtr = source)
{
handle = CryptoNative_DecodePkcs8PrivateKey(
sourcePtr,
source.Length,
(int)algorithmId);
}

if (handle.IsInvalid)
{
handle.Dispose();
throw CreateOpenSslCryptographicException();
}

return handle;
}

[DllImport(Libraries.CryptoNative)]
private static extern int CryptoNative_GetPkcs8PrivateKeySize(IntPtr pkey);

private static int GetPkcs8PrivateKeySize(IntPtr pkey)
{
int ret = CryptoNative_GetPkcs8PrivateKeySize(pkey);

if (ret < 0)
{
throw CreateOpenSslCryptographicException();
}

return ret;
}

[DllImport(Libraries.CryptoNative)]
private static extern unsafe int CryptoNative_EncodePkcs8PrivateKey(IntPtr pkey, byte* buf);

internal static ArraySegment<byte> RentEncodePkcs8PrivateKey(SafeEvpPKeyHandle pkey)
{
bool addedRef = false;

try
{
pkey.DangerousAddRef(ref addedRef);
IntPtr handle = pkey.DangerousGetHandle();

int size = GetPkcs8PrivateKeySize(handle);
byte[] rented = CryptoPool.Rent(size);
int written;

unsafe
{
fixed (byte* buf = rented)
{
written = CryptoNative_EncodePkcs8PrivateKey(handle, buf);
}
}

Debug.Assert(written == size);
return new ArraySegment<byte>(rented, 0, written);
}
finally
{
if (addedRef)
{
pkey.DangerousRelease();
}
}
}

[DllImport(Libraries.CryptoNative)]
private static extern int CryptoNative_GetSubjectPublicKeyInfoSize(IntPtr pkey);

private static int GetSubjectPublicKeyInfoSize(IntPtr pkey)
{
int ret = CryptoNative_GetSubjectPublicKeyInfoSize(pkey);

if (ret < 0)
{
throw CreateOpenSslCryptographicException();
}

return ret;
}

[DllImport(Libraries.CryptoNative)]
private static extern unsafe int CryptoNative_EncodeSubjectPublicKeyInfo(IntPtr pkey, byte* buf);

internal static ArraySegment<byte> RentEncodeSubjectPublicKeyInfo(SafeEvpPKeyHandle pkey)
{
bool addedRef = false;

try
{
pkey.DangerousAddRef(ref addedRef);
IntPtr handle = pkey.DangerousGetHandle();

int size = GetSubjectPublicKeyInfoSize(handle);
byte[] rented = CryptoPool.Rent(size);
int written;

unsafe
{
fixed (byte* buf = rented)
{
written = CryptoNative_EncodeSubjectPublicKeyInfo(handle, buf);
}
}

Debug.Assert(written == size);
return new ArraySegment<byte>(rented, 0, written);
}
finally
{
if (addedRef)
{
pkey.DangerousRelease();
}
}
}

internal enum EvpAlgorithmId
{
Unknown = 0,
RSA = 6,
DSA = 116,
ECC = 408,
}
}
}
Loading