Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,52 @@ internal static ArraySegment<byte> RentEncodeSubjectPublicKeyInfo(SafeEvpPKeyHan
}
}

[LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
private static partial SafeEvpPKeyHandle CryptoNative_LoadPrivateKeyFromEngine(
string engineName,
string keyName);

internal static SafeEvpPKeyHandle LoadPrivateKeyFromEngine(
string engineName,
string keyName)
{
Debug.Assert(engineName is not null);
Debug.Assert(keyName is not null);

SafeEvpPKeyHandle pkey = CryptoNative_LoadPrivateKeyFromEngine(engineName, keyName);

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

return pkey;
}

[LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
private static partial SafeEvpPKeyHandle CryptoNative_LoadPublicKeyFromEngine(
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: I've never been able to store/load a public key in an engine before. Usually, with both TPM and PKCS#11 (via SoftHSM) the public keys were embedded in the X.509 certificate. That said, this could be allowed by some engines.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fair point but as @bartonjs has already responded:#55356 (comment) "it's a low enough incremental cost that it doesn't hurt." which I fully agree

string engineName,
string keyName);

internal static SafeEvpPKeyHandle LoadPublicKeyFromEngine(
string engineName,
string keyName)
{
Debug.Assert(engineName is not null);
Debug.Assert(keyName is not null);

SafeEvpPKeyHandle pkey = CryptoNative_LoadPublicKeyFromEngine(engineName, keyName);

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

return pkey;
}

internal enum EvpAlgorithmId
{
Unknown = 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public static bool OpenSslPresentOnSystem
{
get
{
if (IsAndroid || UsesMobileAppleCrypto || IsBrowser)
if (IsWindows || IsAndroid || UsesMobileAppleCrypto || IsBrowser)
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ public static bool IsMetadataTokenSupported
public static bool IsNotDomainJoinedMachine => !IsDomainJoinedMachine;

public static bool IsOpenSslSupported => IsLinux || IsFreeBSD || Isillumos || IsSolaris;
public static bool OpenSslNotPresentOnSystem => !OpenSslPresentOnSystem;

public static bool UsesAppleCrypto => IsOSX || IsMacCatalyst || IsiOS || IstvOS;
public static bool UsesMobileAppleCrypto => IsMacCatalyst || IsiOS || IstvOS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2245,6 +2245,18 @@ public sealed partial class SafeEvpPKeyHandle : System.Runtime.InteropServices.S
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
public static long OpenSslVersion { get { throw null; } }
public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateHandle() { throw null; }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
public static System.Security.Cryptography.SafeEvpPKeyHandle OpenPrivateKeyFromEngine(string engineName, string keyId) { throw null; }
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("android")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")]
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("windows")]
public static System.Security.Cryptography.SafeEvpPKeyHandle OpenPublicKeyFromEngine(string engineName, string keyId) { throw null; }
protected override bool ReleaseHandle() { throw null; }
}
public abstract partial class SHA1 : System.Security.Cryptography.HashAlgorithm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,22 @@ public SafeEvpPKeyHandle(IntPtr handle, bool ownsHandle) : base(handle, ownsHand
public static long OpenSslVersion =>
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL);

[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]
[UnsupportedOSPlatform("tvos")]
[UnsupportedOSPlatform("windows")]
public static SafeEvpPKeyHandle OpenPrivateKeyFromEngine(string engineName, string keyId) =>
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL);

[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]
[UnsupportedOSPlatform("tvos")]
[UnsupportedOSPlatform("windows")]
public static SafeEvpPKeyHandle OpenPublicKeyFromEngine(string engineName, string keyId) =>
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL);

public SafeEvpPKeyHandle DuplicateHandle() => null!;
public override bool IsInvalid => true;
protected override bool ReleaseHandle() => false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,110 @@ public SafeEvpPKeyHandle DuplicateHandle()
[UnsupportedOSPlatform("tvos")]
[UnsupportedOSPlatform("windows")]
public static long OpenSslVersion { get; } = Interop.OpenSsl.OpenSslVersionNumber();

/// <summary>
/// Open a named private key using a named OpenSSL <code>ENGINE</code>.
/// </summary>
/// <param name="engineName">
/// The name of the <code>ENGINE</code> to process the private key open request.
/// </param>
/// <param name="keyId">
/// The name of the key to open.
/// </param>
/// <returns>
/// The opened key.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="engineName"/> or <paramref name="keyId"/> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="engineName"/> or <paramref name="keyId"/> is the empty string.
/// </exception>
/// <exception cref="CryptographicException">
/// the key could not be opened via the specified ENGINE.
/// </exception>
/// <remarks>
/// <para>
/// This operation will fail if OpenSSL cannot successfully load the named <code>ENGINE</code>,
/// or if the named <code>ENGINE</code> cannot load the named key.
/// </para>
/// <para>
/// Not all <code>ENGINE</code>s support loading private keys.
/// </para>
/// <para>
/// The syntax for <paramref name="keyId"/> is determined by each individual
/// <code>ENGINE</code>.
/// </para>
/// </remarks>
[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]
[UnsupportedOSPlatform("tvos")]
[UnsupportedOSPlatform("windows")]
public static SafeEvpPKeyHandle OpenPrivateKeyFromEngine(string engineName, string keyId)
{
ArgumentException.ThrowIfNullOrEmpty(engineName);
ArgumentException.ThrowIfNullOrEmpty(keyId);

if (!Interop.OpenSslNoInit.OpenSslIsAvailable)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL);
}

return Interop.Crypto.LoadPrivateKeyFromEngine(engineName, keyId);
}

/// <summary>
/// Open a named public key using a named OpenSSL <code>ENGINE</code>.
/// </summary>
/// <param name="engineName">
/// The name of the <code>ENGINE</code> to process the public key open request.
/// </param>
/// <param name="keyId">
/// The name of the key to open.
/// </param>
/// <returns>
/// The opened key.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="engineName"/> or <paramref name="keyId"/> is <see langword="null" />.
/// </exception>
/// <exception cref="ArgumentException">
/// <paramref name="engineName"/> or <paramref name="keyId"/> is the empty string.
/// </exception>
/// <exception cref="CryptographicException">
/// the key could not be opened via the specified ENGINE.
/// </exception>
/// <remarks>
/// <para>
/// This operation will fail if OpenSSL cannot successfully load the named <code>ENGINE</code>,
/// or if the named <code>ENGINE</code> cannot load the named key.
/// </para>
/// <para>
/// Not all <code>ENGINE</code>s support loading public keys, even ones that support
/// loading private keys.
/// </para>
/// <para>
/// The syntax for <paramref name="keyId"/> is determined by each individual
/// <code>ENGINE</code>.
/// </para>
/// </remarks>
[UnsupportedOSPlatform("android")]
[UnsupportedOSPlatform("browser")]
[UnsupportedOSPlatform("ios")]
[UnsupportedOSPlatform("tvos")]
[UnsupportedOSPlatform("windows")]
public static SafeEvpPKeyHandle OpenPublicKeyFromEngine(string engineName, string keyId)
{
ArgumentException.ThrowIfNullOrEmpty(engineName);
ArgumentException.ThrowIfNullOrEmpty(keyId);

if (!Interop.OpenSslNoInit.OpenSslIsAvailable)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyOpenSSL);
}

return Interop.Crypto.LoadPublicKeyFromEngine(engineName, keyId);
}
}
}
Loading