public void Add(ICertificatePal cert) { if (_readOnly) { throw new CryptographicException(SR.Cryptography_X509_StoreReadOnly); } AndroidCertificatePal certPal = (AndroidCertificatePal)cert; string hashString = GetCertificateHashString(cert); bool success; if (certPal.HasPrivateKey) { Interop.AndroidCrypto.PAL_KeyAlgorithm algorithm = certPal.PrivateKeyHandle switch { // The AndroidKeyStore doesn't support adding DSA private key entries in newer versions (API 23+) // Our minimum supported version (API 21) does support it, but for simplicity, we simply block adding // certificates with DSA private keys on all versions instead of trying to support it on two versions. SafeDsaHandle _ => throw new PlatformNotSupportedException(SR.Cryptography_X509_StoreDSAPrivateKeyNotSupported), SafeEcKeyHandle _ => Interop.AndroidCrypto.PAL_KeyAlgorithm.EC, SafeRsaHandle _ => Interop.AndroidCrypto.PAL_KeyAlgorithm.RSA, _ => throw new NotSupportedException(SR.NotSupported_KeyAlgorithm) }; success = Interop.AndroidCrypto.X509StoreAddCertificateWithPrivateKey(_keyStoreHandle, certPal.SafeHandle, certPal.PrivateKeyHandle, algorithm, hashString); } else { success = Interop.AndroidCrypto.X509StoreAddCertificate(_keyStoreHandle, certPal.SafeHandle, hashString); } if (!success) { throw new CryptographicException(SR.Cryptography_X509_StoreAddFailure); } }
internal static extern int EcKeyGetCurveName(SafeEcKeyHandle ecKey);
private static partial int EcKeyCreateByKeyParameters( out SafeEcKeyHandle key, string oid, byte[]?qx, int qxLength, byte[]?qy, int qyLength, byte[]?d, int dLength);
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);
private static partial int CryptoNative_EcKeyGetSize(SafeEcKeyHandle ecKey, out int keySize);
private static partial int AndroidCryptoNative_EcKeyGetCurveName(SafeEcKeyHandle ecKey, out IntPtr curveName);
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);
private static partial int CryptoNative_EcDsaSize(SafeEcKeyHandle ecKey);
internal static extern int EcDsaSize(SafeEcKeyHandle ecKey);
internal static unsafe int EcDsaVerify(ReadOnlySpan <byte> dgst, int dgst_len, ReadOnlySpan <byte> sigbuf, int sig_len, SafeEcKeyHandle ecKey) => EcDsaVerify(ref dgst.DangerousGetPinnableReference(), dgst_len, ref sigbuf.DangerousGetPinnableReference(), sig_len, ecKey);
private static extern bool EcDsaSign(ref byte dgst, int dlen, ref byte sig, [In, Out] ref int siglen, SafeEcKeyHandle ecKey);
internal static bool EcDsaSign(ReadOnlySpan <byte> dgst, int dlen, Span <byte> sig, [In, Out] ref int siglen, SafeEcKeyHandle ecKey) => EcDsaSign(ref dgst.DangerousGetPinnableReference(), dlen, ref sig.DangerousGetPinnableReference(), ref siglen, ecKey);
internal static bool EcDsaSign(ReadOnlySpan <byte> dgst, int dlen, Span <byte> sig, [In, Out] ref int siglen, SafeEcKeyHandle ecKey) => EcDsaSign(ref MemoryMarshal.GetReference(dgst), dlen, ref MemoryMarshal.GetReference(sig), ref siglen, ecKey);
internal static int EcDsaVerify(ReadOnlySpan <byte> dgst, ReadOnlySpan <byte> sigbuf, SafeEcKeyHandle ecKey) { int ret = EcDsaVerify( ref MemoryMarshal.GetReference(dgst), dgst.Length, ref MemoryMarshal.GetReference(sigbuf), sigbuf.Length, ecKey); if (ret == 0) { // OpenSSL ECDSA signature processing requires a DER encode and decode, so // the error queue may have been contaminated. ErrClearError(); } return(ret); }
internal static int EcDsaVerify(ReadOnlySpan <byte> dgst, ReadOnlySpan <byte> sigbuf, SafeEcKeyHandle ecKey) { int ret = EcDsaVerify( ref MemoryMarshal.GetReference(dgst), dgst.Length, ref MemoryMarshal.GetReference(sigbuf), sigbuf.Length, ecKey); if (ret < 0) { ErrClearError(); } return(ret); }
private static extern int EcKeyCreateByKeyParameters( out SafeEcKeyHandle key, string oid, byte[] qx, int qxLength, byte[] qy, int qyLength, byte[] d, int dLength);
private static partial int EcDsaVerify(ref byte dgst, int dgst_len, ref byte sigbuf, int sig_len, SafeEcKeyHandle ecKey);
private static extern int CryptoNative_EcDsaSize(SafeEcKeyHandle ecKey);
internal static extern bool EvpPkeySetEcKey(SafeEvpPKeyHandle pkey, SafeEcKeyHandle key);
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);
internal static SafeEcKeyHandle?EcKeyCreateByOid(string oid) { SafeEcKeyHandle handle = AndroidCryptoNative_EcKeyCreateByOid(oid); return(handle); }
internal static extern bool EcKeyGenerateKey(SafeEcKeyHandle eckey);
internal static partial bool EcKeyGenerateKey(SafeEcKeyHandle eckey);
private static extern int CryptoNative_EcKeyGetSize(SafeEcKeyHandle ecKey, out int keySize);
private static partial int CryptoNative_EcKeyGetCurveName(SafeEcKeyHandle ecKey, out int nid);
internal static bool EcDsaSign(ReadOnlySpan <byte> dgst, Span <byte> sig, out int siglen, SafeEcKeyHandle ecKey) => EcDsaSign(ref MemoryMarshal.GetReference(dgst), dgst.Length, ref MemoryMarshal.GetReference(sig), out siglen, ecKey);
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 = default; bool refAdded = false; try { key.DangerousAddRef(ref refAdded); // Protect access to d_bn_not_owned int rc = CryptoNative_GetECKeyParameters( key, includePrivate, out qx_bn, out qx_cb, out qy_bn, out qy_cb, out d_bn_not_owned, out d_cb); using (qx_bn) using (qy_bn) { if (rc == -1) { throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); } else if (rc != 1) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } 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); }
private static partial bool EcDsaSign(ref byte dgst, int dlen, ref byte sig, out int siglen, SafeEcKeyHandle ecKey);
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(); } } }
internal static extern ECCurve.ECCurveType EcKeyGetCurveType(SafeEcKeyHandle key);