Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 3ffbbbb

Browse files
committed
Add an IntPtr constructor to RSAOpenSsl.
OpenSSL doesn't have the same notion of key addressing as Windows (via structures such as CspParameters), so the ability to use a hardware key is currently non-existent. With this change it improves to "if you do the P/Invokes to get the correct RSA*, pass us the pointer and the rest of the managed cryptography stack can use it". This also empowers X509Certificates Unix implementation to use the existing key handle to instantiate the RSAOpenSsl object, rather than having to run through ExportParameters/ImportParameters.
1 parent 8ca44f6 commit 3ffbbbb

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

src/Common/src/Interop/Unix/libcrypto/Interop.Rsa.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ internal static partial class libcrypto
2121
[DllImport(Libraries.LibCrypto)]
2222
internal static unsafe extern SafeRsaHandle d2i_RSAPublicKey(IntPtr zero, byte** ppin, int len);
2323

24+
[DllImport(Libraries.LibCrypto)]
25+
[return: MarshalAs(UnmanagedType.Bool)]
26+
internal static extern bool RSA_up_ref(IntPtr rsa);
27+
2428
[DllImport(Libraries.LibCrypto)]
2529
internal static extern void RSA_free(IntPtr rsa);
2630

src/Common/src/Microsoft/Win32/SafeHandles/SafeRsaHandle.Unix.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5+
using System.Diagnostics;
56
using System.Security;
67
using System.Runtime.InteropServices;
78

@@ -26,5 +27,22 @@ public override bool IsInvalid
2627
{
2728
get { return handle == IntPtr.Zero; }
2829
}
30+
31+
internal static SafeRsaHandle DuplicateHandle(IntPtr handle)
32+
{
33+
Debug.Assert(handle != IntPtr.Zero);
34+
35+
// Reliability: Allocate the SafeHandle before calling RSA_up_ref so
36+
// that we don't lose a tracked reference in low-memory situations.
37+
SafeRsaHandle safeHandle = new SafeRsaHandle();
38+
39+
if (!Interop.libcrypto.RSA_up_ref(handle))
40+
{
41+
throw Interop.libcrypto.CreateOpenSslCryptographicException();
42+
}
43+
44+
safeHandle.SetHandle(handle);
45+
return safeHandle;
46+
}
2947
}
3048
}

src/System.Security.Cryptography.OpenSsl/src/System/Security/Cryptography/RSAOpenSsl.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace System.Security.Cryptography
1212
{
1313
public sealed class RSAOpenSsl : RSA
1414
{
15+
private const int BitsPerByte = 8;
16+
1517
// 65537 (0x10001) in big-endian form
1618
private static readonly byte[] s_defaultExponent = { 0x01, 0x00, 0x01 };
1719

@@ -45,6 +47,31 @@ public RSAOpenSsl(RSAParameters parameters)
4547
ImportParameters(parameters);
4648
}
4749

50+
/// <summary>
51+
/// Create an RSAOpenSsl from an existing <see cref="IntPtr"/> whose value is an
52+
/// existing OpenSSL <c>RSA*</c>.
53+
/// </summary>
54+
/// <remarks>
55+
/// This method will increase the reference count of the <c>RSA*</c>, the caller should
56+
/// continue to manage the lifetime of their reference.
57+
/// </remarks>
58+
/// <param name="handle">A pointer to an OpenSSL <c>RSA*</c></param>
59+
/// <exception cref="ArgumentException"><paramref name="handle" /> is invalid</exception>
60+
public RSAOpenSsl(IntPtr handle)
61+
{
62+
if (handle == IntPtr.Zero)
63+
throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, "handle");
64+
65+
_legalKeySizesValue = new[] { s_legalKeySizes };
66+
67+
SafeRsaHandle rsaHandle = SafeRsaHandle.DuplicateHandle(handle);
68+
69+
// Set base.KeySize to avoid throwing an extra Lazy at the GC when
70+
// using something other than the default keysize.
71+
base.KeySize = BitsPerByte * Interop.libcrypto.RSA_size(rsaHandle);
72+
_key = new Lazy<SafeRsaHandle>(() => rsaHandle);
73+
}
74+
4875
public override int KeySize
4976
{
5077
set
@@ -224,7 +251,7 @@ public override unsafe void ImportParameters(RSAParameters parameters)
224251

225252
// Set base.KeySize directly, since we don't want to free the key
226253
// (which we would do if the keysize changed on import)
227-
base.KeySize = 8 * Interop.libcrypto.RSA_size(key);
254+
base.KeySize = BitsPerByte * Interop.libcrypto.RSA_size(key);
228255
}
229256

230257
protected override void Dispose(bool disposing)

0 commit comments

Comments
 (0)