private static unsafe byte[] ExtractBignum(SafeBignumHandle bignum, int targetSize) { if (bignum == null || bignum.IsInvalid) { return(null); } int compactSize = GetBigNumBytes(bignum); if (targetSize < compactSize) { targetSize = compactSize; } // OpenSSL BIGNUM values do not record leading zeroes. // Windows Crypt32 does. // // Since RSACryptoServiceProvider already checks that RSAParameters.DP.Length is // exactly half of RSAParameters.Modulus.Length, we need to left-pad (big-endian) // the array with zeroes. int offset = targetSize - compactSize; byte[] buf = new byte[targetSize]; fixed(byte *to = buf) { byte *start = to + offset; BigNumToBinary(bignum, start); } return(buf); }
private static extern bool GetDsaParameters( SafeDsaHandle key, out SafeBignumHandle p, out int p_cb, out SafeBignumHandle q, out int q_cb, out SafeBignumHandle g, out int g_cb, out SafeBignumHandle y, out int y_cb, out SafeBignumHandle x, out int x_cb);
private SafeRsaHandle GenerateKey() { SafeRsaHandle key = Interop.libcrypto.RSA_new(); bool generated = false; CheckInvalidNewKey(key); try { using (SafeBignumHandle exponent = Interop.libcrypto.CreateBignum(s_defaultExponent)) { // The documentation for RSA_generate_key_ex does not say that it returns only // 0 or 1, so the call marshalls it back as a full Int32 and checks for a value // of 1 explicitly. int response = Interop.libcrypto.RSA_generate_key_ex( key, KeySize, exponent, IntPtr.Zero); CheckBoolReturn(response); generated = true; } } finally { if (!generated) { key.Dispose(); } } return(key); }
internal static ECParameters GetECKeyParameters( SafeEcKeyHandle key, bool includePrivate) { SafeBignumHandle qx_bn, qy_bn, d_bn; IntPtr d_bn_not_owned; int qx_cb, qy_cb, d_cb; ECParameters parameters = new ECParameters(); bool refAdded = false; try { key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned if (!CryptoNative_GetECKeyParameters( key, includePrivate, out qx_bn, out qx_cb, out qy_bn, out qy_cb, out d_bn_not_owned, out d_cb)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } using (qx_bn) using (qy_bn) using (d_bn = new SafeBignumHandle(d_bn_not_owned, false)) { // Match Windows semantics where qx, qy, and d have same length int keySizeBits = EcKeyGetSize(key); int expectedSize = (keySizeBits + 7) / 8; int cbKey = GetMax(qx_cb, qy_cb, d_cb); Debug.Assert( cbKey <= expectedSize, $"Expected output size was {expectedSize}, which a parameter exceeded. qx={qx_cb}, qy={qy_cb}, d={d_cb}"); cbKey = GetMax(cbKey, expectedSize); parameters.Q = new ECPoint { X = Crypto.ExtractBignum(qx_bn, cbKey), Y = Crypto.ExtractBignum(qy_bn, cbKey) }; parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbKey); } } finally { if (refAdded) { key.DangerousRelease(); } } return(parameters); }
internal static byte[] ExtractBignum(IntPtr bignum, int targetSize) { // Given that the only reference held to bignum is an IntPtr, create an unowned SafeHandle // to ensure that we don't destroy the key after extraction. using (SafeBignumHandle handle = new SafeBignumHandle(bignum, ownsHandle: false)) { return(ExtractBignum(handle, targetSize)); } }
private static extern bool GetRsaParameters( SafeRsaHandle key, out SafeBignumHandle n, out SafeBignumHandle e, out SafeBignumHandle d, out SafeBignumHandle p, out SafeBignumHandle dmp1, out SafeBignumHandle q, out SafeBignumHandle dmq1, out SafeBignumHandle iqmp);
internal static SafeBignumHandle CreateBignum(ReadOnlySpan <byte> bigEndianValue) { SafeBignumHandle ret = BigNumFromBinary(bigEndianValue, bigEndianValue.Length); if (ret.IsInvalid) { Exception e = CreateOpenSslCryptographicException(); ret.Dispose(); throw e; } return(ret); }
internal static ECParameters GetECKeyParameters( SafeEcKeyHandle key, bool includePrivate) { SafeBignumHandle qx_bn, qy_bn, d_bn; IntPtr d_bn_not_owned; int qx_cb, qy_cb, d_cb; ECParameters parameters = new ECParameters(); bool refAdded = false; try { key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned if (!CryptoNative_GetECKeyParameters( key, includePrivate, out qx_bn, out qx_cb, out qy_bn, out qy_cb, out d_bn_not_owned, out d_cb)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } using (qx_bn) using (qy_bn) using (d_bn = new SafeBignumHandle(d_bn_not_owned, false)) { // Match Windows semantics where qx, qy, and d have same length int cbKey = GetMax(new[] { qx_cb, qy_cb, d_cb }); parameters.Q = new ECPoint { X = Crypto.ExtractBignum(qx_bn, cbKey), Y = Crypto.ExtractBignum(qy_bn, cbKey) }; parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_bn, cbKey); } } finally { if (refAdded) { key.DangerousRelease(); } } return(parameters); }
private static extern int AndroidCryptoNative_GetECCurveParameters( SafeEcKeyHandle key, bool includePrivate, out ECCurve.ECCurveType curveType, out SafeBignumHandle qx, out int x_cb, out SafeBignumHandle qy, out int y_cb, out IntPtr d_bn_not_owned, out int d_cb, out SafeBignumHandle p, out int P_cb, out SafeBignumHandle a, out int A_cb, out SafeBignumHandle b, out int B_cb, out SafeBignumHandle gx, out int Gx_cb, out SafeBignumHandle gy, out int Gy_cb, out SafeBignumHandle order, out int order_cb, out SafeBignumHandle cofactor, out int cofactor_cb, out SafeBignumHandle seed, out int seed_cb);
private static partial int CryptoNative_GetECCurveParameters( SafeEcKeyHandle key, [MarshalAs(UnmanagedType.Bool)] bool includePrivate, out ECCurve.ECCurveType curveType, out SafeBignumHandle qx, out int x_cb, out SafeBignumHandle qy, out int y_cb, out IntPtr d_bn_not_owned, out int d_cb, out SafeBignumHandle p, out int P_cb, out SafeBignumHandle a, out int A_cb, out SafeBignumHandle b, out int B_cb, out SafeBignumHandle gx, out int Gx_cb, out SafeBignumHandle gy, out int Gy_cb, out SafeBignumHandle order, out int order_cb, out SafeBignumHandle cofactor, out int cofactor_cb, out SafeBignumHandle seed, out int seed_cb);
internal static SafeBignumHandle CreateBignum(ReadOnlySpan <byte> bigEndianValue) { unsafe { fixed(byte *pBigEndianValue = bigEndianValue) { SafeBignumHandle ret = BigNumFromBinary(pBigEndianValue, bigEndianValue.Length); if (ret.IsInvalid) { ret.Dispose(); throw new CryptographicException(); } return(ret); } } }
private static extern int BN_num_bits(SafeBignumHandle a);
internal static ECParameters GetECCurveParameters( SafeEcKeyHandle key, bool includePrivate) { ECCurve.ECCurveType curveType; SafeBignumHandle qx_bn, qy_bn, p_bn, a_bn, b_bn, gx_bn, gy_bn, order_bn, cofactor_bn, seed_bn; IntPtr d_bn_not_owned; int qx_cb, qy_cb, p_cb, a_cb, b_cb, gx_cb, gy_cb, order_cb, cofactor_cb, seed_cb, d_cb; bool refAdded = false; try { key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned int rc = CryptoNative_GetECCurveParameters( key, includePrivate, out curveType, out qx_bn, out qx_cb, out qy_bn, out qy_cb, out d_bn_not_owned, out d_cb, out p_bn, out p_cb, out a_bn, out a_cb, out b_bn, out b_cb, out gx_bn, out gx_cb, out gy_bn, out gy_cb, out order_bn, out order_cb, out cofactor_bn, out cofactor_cb, out seed_bn, out seed_cb); using (qx_bn) using (qy_bn) using (p_bn) using (a_bn) using (b_bn) using (gx_bn) using (gy_bn) using (order_bn) using (cofactor_bn) using (seed_bn) { if (rc == -1) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } else if (rc != 1) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } using (var d_h = new SafeBignumHandle(d_bn_not_owned, false)) { int cbFieldLength; int pFieldLength; if (curveType == ECCurve.ECCurveType.Characteristic2) { // Match Windows semantics where a,b,gx,gy,qx,qy have same length // Treat length of m separately as it is not tied to other fields for Char2 (Char2 not supported by Windows) cbFieldLength = GetMax(new[] { a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb }); pFieldLength = p_cb; } else { // Match Windows semantics where p,a,b,gx,gy,qx,qy have same length cbFieldLength = GetMax(new[] { p_cb, a_cb, b_cb, gx_cb, gy_cb, qx_cb, qy_cb }); pFieldLength = cbFieldLength; } // Match Windows semantics where order and d have same length int cbSubgroupOrder = GetMax(order_cb, d_cb); // Copy values to ECParameters ECParameters parameters = default; parameters.Q = new ECPoint { X = Crypto.ExtractBignum(qx_bn, cbFieldLength), Y = Crypto.ExtractBignum(qy_bn, cbFieldLength) }; parameters.D = d_cb == 0 ? null : Crypto.ExtractBignum(d_h, cbSubgroupOrder); var curve = parameters.Curve; curve.CurveType = curveType; curve.A = Crypto.ExtractBignum(a_bn, cbFieldLength) !; curve.B = Crypto.ExtractBignum(b_bn, cbFieldLength) !; curve.G = new ECPoint { X = Crypto.ExtractBignum(gx_bn, cbFieldLength), Y = Crypto.ExtractBignum(gy_bn, cbFieldLength) }; curve.Order = Crypto.ExtractBignum(order_bn, cbSubgroupOrder) !; if (curveType == ECCurve.ECCurveType.Characteristic2) { curve.Polynomial = Crypto.ExtractBignum(p_bn, pFieldLength) !; } else { curve.Prime = Crypto.ExtractBignum(p_bn, pFieldLength) !; } // Optional parameters curve.Cofactor = cofactor_cb == 0 ? null : Crypto.ExtractBignum(cofactor_bn, cofactor_cb); curve.Seed = seed_cb == 0 ? null : Crypto.ExtractBignum(seed_bn, seed_cb); parameters.Curve = curve; return(parameters); } } } finally { if (refAdded) { key.DangerousRelease(); } } }
private static extern int GetBigNumBytes(SafeBignumHandle a);
private static partial int CryptoNative_GetECKeyParameters( SafeEcKeyHandle key, [MarshalAs(UnmanagedType.Bool)] bool includePrivate, out SafeBignumHandle qx_bn, out int x_cb, out SafeBignumHandle qy_bn, out int y_cb, out IntPtr d_bn_not_owned, out int d_cb);
/// <summary> /// Returns the number of bytes needed to export a BIGNUM. /// </summary> /// <remarks>This is a macro in bn.h, expanded here.</remarks> private static int BN_num_bytes(SafeBignumHandle a) { return((BN_num_bits(a) + 7) / 8); }
private static extern unsafe int BigNumToBinary(SafeBignumHandle a, byte *to);
private static unsafe partial int BigNumToBinary(SafeBignumHandle a, byte *to);
private static extern int AndroidCryptoNative_GetECKeyParameters( SafeEcKeyHandle key, bool includePrivate, out SafeBignumHandle qx_bn, out int x_cb, out SafeBignumHandle qy_bn, out int y_cb, out IntPtr d_bn_not_owned, out int d_cb);
internal static extern int RsaGenerateKeyEx(SafeRsaHandle rsa, int bits, SafeBignumHandle e);
private static partial int AndroidCryptoNative_GetECKeyParameters( SafeEcKeyHandle key, bool includePrivate, out SafeBignumHandle qx_bn, out int x_cb, out SafeBignumHandle qy_bn, out int y_cb, out SafeBignumHandle d_bn, out int d_cb);
private static partial int GetBigNumBytes(SafeBignumHandle a);
private static extern unsafe int BN_bn2bin(SafeBignumHandle a, byte *to);
internal static extern int RSA_generate_key_ex(SafeRsaHandle rsa, int bits, SafeBignumHandle e, IntPtr zero);