public unsafe void SetPeerKey(ReadableBuffer peerKey) { if (peerKey.Length != _keyExchangeSize) { Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, $"The client key didn't match the expected length"); } int cbKey; peerKey = peerKey.Slice(1); cbKey = peerKey.Length / 2; GenerateKeys(); int keyLength = peerKey.Length; //Now we have the point and can load the key var keyBuffer = stackalloc byte[keyLength + 8]; var blobHeader = new BCRYPT_ECCKEY_BLOB(); blobHeader.Magic = KeyBlobMagicNumber.BCRYPT_ECDH_PUBLIC_GENERIC_MAGIC; blobHeader.cbKey = cbKey; Marshal.StructureToPtr(blobHeader, (IntPtr)keyBuffer, false); peerKey.CopyTo(new Span <byte>(keyBuffer + 8, keyLength)); SafeBCryptKeyHandle keyHandle; ExceptionHelper.CheckReturnCode(BCryptImportKeyPair(_algo, IntPtr.Zero, KeyBlobType.BCRYPT_ECCPUBLIC_BLOB, out keyHandle, (IntPtr)keyBuffer, keyLength + 8, 0)); _peerKey = keyHandle; _hasPeerKey = true; }
internal static unsafe partial NTSTATUS BCryptKeyDerivation( SafeBCryptKeyHandle hKey, BCryptBufferDesc *pParameterList, byte *pbDerivedKey, int cbDerivedKey, out uint pcbResult, int dwFlags);
/// <summary> /// Method take BCrypt handle as input and returns the CNGKey /// </summary> /// <param name="bcryptKeyHandle">Accepts BCrypt Handle</param> /// <returns>Returns CNG key with NCrypt Handle</returns> private static CngKey LegacyBCryptHandleToNCryptHandle(SafeBCryptKeyHandle bcryptKeyHandle) { byte[] keyBlob = BCryptNative.ExportBCryptKey(bcryptKeyHandle, BCryptNative.BCRYPT_ECCPUBLIC_BLOB); //Now Import the key blob as NCRYPT_KEY_HANDLE CngKey Key = CngKey.Import(keyBlob, CngKeyBlobFormat.EccPublicBlob); return(Key); }
internal static extern int BCryptExportKey( [In] SafeBCryptKeyHandle hKey, [In] IntPtr hExportKey, [In, MarshalAs(UnmanagedType.LPWStr)] string pszBlobType, [Out] byte[] pbOutput, [In] uint cbOutput, [Out] out uint pcbResult, [In] uint dwFlags);
internal static unsafe partial NTSTATUS BCryptGenerateSymmetricKey( nuint hAlgorithm, out SafeBCryptKeyHandle phKey, IntPtr pbKeyObject, int cbKeyObject, byte *pbSecret, int cbSecret, uint dwFlags);
private static bool HasProperty(SafeBCryptKeyHandle cryptHandle, string propertyName) { Debug.Assert(!cryptHandle.IsInvalid); unsafe { int numBytesNeeded; BCryptNative.ErrorCode errorCode = BCryptNative.UnsafeNativeMethods.BCryptGetProperty(cryptHandle, propertyName, null, 0, out numBytesNeeded, 0); return(errorCode == BCryptNative.ErrorCode.Success && numBytesNeeded > 0); } }
public static ECDsa GetECDsaPublicKey(this X509Certificate2 certificate) { if (LocalAppContextSwitches.UseLegacyPublicKeyBehavior) { return(LegacyGetECDsaPublicKey(certificate)); } if (certificate == null) { throw new ArgumentNullException("certificate"); } if (!IsECDsa(certificate)) { return(null); } using (SafeCertContextHandle safeCertContext = X509Native.GetCertificateContext(certificate)) using (SafeBCryptKeyHandle bcryptKeyHandle = ImportPublicKeyInfo(safeCertContext)) { if (bcryptKeyHandle.IsInvalid) { throw new CryptographicException("SR.GetString(SR.Cryptography_OpenInvalidHandle)"); } string curveName = GetCurveName(bcryptKeyHandle); if (curveName == null) { CngKeyBlobFormat blobFormat = HasExplicitParameters(bcryptKeyHandle) ? CngKeyBlobFormat.EccFullPublicBlob : CngKeyBlobFormat.EccPublicBlob; byte[] keyBlob = BCryptNative.ExportBCryptKey(bcryptKeyHandle, blobFormat.Format); using (CngKey key = CngKey.Import(keyBlob, blobFormat)) { return(new ECDsaCng(key)); } } else { CngKeyBlobFormat blobFormat = CngKeyBlobFormat.EccPublicBlob; byte[] keyBlob = BCryptNative.ExportBCryptKey(bcryptKeyHandle, blobFormat.Format); ECParameters ecparams = new ECParameters(); ExportNamedCurveParameters(ref ecparams, keyBlob, false); ecparams.Curve = ECCurve.CreateFromFriendlyName(curveName); ECDsaCng ecdsa = new ECDsaCng(); ecdsa.ImportParameters(ecparams); return(ecdsa); } } }
public BasicSymmetricCipherBCrypt(SafeBCryptAlgorithmHandle algorithm, CipherMode cipherMode, int blockSizeInBytes, byte[] key, byte[] iv, bool encrypting) : base(cipherMode.GetCipherIv(iv), blockSizeInBytes) { Debug.Assert(algorithm != null); _encrypting = encrypting; if (IV != null) { _currentIv = new byte[IV.Length]; } _hKey = BCryptNative.BCryptImportKey(algorithm, key); Reset(); }
private static string GetPropertyAsString(SafeBCryptKeyHandle cryptHandle, string propertyName) { Debug.Assert(!cryptHandle.IsInvalid); byte[] value = GetProperty(cryptHandle, propertyName); if (value == null || value.Length == 0) { return(null); } unsafe { fixed(byte *pValue = &value[0]) { string valueAsString = Marshal.PtrToStringUni((IntPtr)pValue); return(valueAsString); } } }
internal BCryptSymmetricCryptoTransform(SafeBCryptAlgorithmHandle algorithm, byte[] key, byte[] iv, PaddingMode paddingMode, bool encrypting) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(!algorithm.IsClosed && !algorithm.IsInvalid, "!algorithm.IsClosed && !algorithm.IsInvalid"); Debug.Assert(key != null, "key != null"); m_algorithm = algorithm; m_encrypting = encrypting; m_paddingMode = BlockPaddingMethod.Create(paddingMode, BCryptNative.GetInt32Property(algorithm, BCryptNative.ObjectPropertyName.BlockLength)); m_iv = ProcessIV(iv, BCryptNative.GetInt32Property(algorithm, BCryptNative.ObjectPropertyName.BlockLength), BCryptNative.MapChainingMode(BCryptNative.GetStringProperty(algorithm, BCryptNative.ObjectPropertyName.ChainingMode))); m_key = BCryptNative.ImportSymmetricKey(algorithm, key); }
private static SafeBCryptKeyHandle ImportPublicKeyInfo(SafeCertContextHandle certContext) { IntPtr certHandle = certContext.DangerousGetHandle(); //Read the public key blob from the certificate X509Native.CERT_CONTEXT pCertContext = (X509Native.CERT_CONTEXT)Marshal.PtrToStructure(certHandle, typeof(X509Native.CERT_CONTEXT)); IntPtr pSubjectPublicKeyInfo = new IntPtr((long)pCertContext.pCertInfo + (long)Marshal.OffsetOf(typeof(X509Native.CERT_INFO), "SubjectPublicKeyInfo")); X509Native.CERT_PUBLIC_KEY_INFO certPublicKeyInfo = (X509Native.CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(pSubjectPublicKeyInfo, typeof(X509Native.CERT_PUBLIC_KEY_INFO)); SafeBCryptKeyHandle publicKeyInfo = BCryptNative.ImportAsymmetricPublicKey(certPublicKeyInfo, 0); // certContext needs to be valid through the call to BCryptNative.ImportAsymmetricPublicKey // because certPublicKeyInfo structure contains pointers. GC.KeepAlive(certContext); return(publicKeyInfo); }
protected override void Dispose(bool disposing) { if (disposing) { SafeBCryptKeyHandle hKey = _hKey; _hKey = null; if (hKey != null) { hKey.Dispose(); } byte[] currentIv = _currentIv; _currentIv = null; if (currentIv != null) { Array.Clear(currentIv, 0, currentIv.Length); } } base.Dispose(disposing); }
private static byte[] GetProperty(SafeBCryptKeyHandle cryptHandle, string propertyName) { Debug.Assert(!cryptHandle.IsInvalid); unsafe { int numBytesNeeded; BCryptNative.ErrorCode errorCode = BCryptNative.UnsafeNativeMethods.BCryptGetProperty(cryptHandle, propertyName, null, 0, out numBytesNeeded, 0); if (errorCode != BCryptNative.ErrorCode.Success) { return(null); } byte[] propertyValue = new byte[numBytesNeeded]; errorCode = BCryptNative.UnsafeNativeMethods.BCryptGetProperty(cryptHandle, propertyName, propertyValue, propertyValue.Length, out numBytesNeeded, 0); if (errorCode != BCryptNative.ErrorCode.Success) { return(null); } Array.Resize(ref propertyValue, numBytesNeeded); return(propertyValue); } }
private static ECDsa LegacyGetECDsaPublicKey(X509Certificate2 certificate) { if (certificate == null) { throw new ArgumentNullException("certificate"); } if (!IsECDsa(certificate)) { return(null); } SafeCertContextHandle safeCertContext = X509Native.GetCertificateContext(certificate); IntPtr certHandle = safeCertContext.DangerousGetHandle(); //Read the public key blob from the certificate X509Native.CERT_CONTEXT pCertContext = (X509Native.CERT_CONTEXT)Marshal.PtrToStructure(certHandle, typeof(X509Native.CERT_CONTEXT)); IntPtr pSubjectPublicKeyInfo = new IntPtr((long)pCertContext.pCertInfo + (long)Marshal.OffsetOf(typeof(X509Native.CERT_INFO), "SubjectPublicKeyInfo")); X509Native.CERT_PUBLIC_KEY_INFO certPublicKeyInfo = (X509Native.CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(pSubjectPublicKeyInfo, typeof(X509Native.CERT_PUBLIC_KEY_INFO)); CngKey key; //Import the public key blob to BCRYPT_KEY_HANDLE using (SafeBCryptKeyHandle bcryptKeyHandle = BCryptNative.ImportAsymmetricPublicKey(certPublicKeyInfo, 0)) { if (bcryptKeyHandle.IsInvalid) { throw new CryptographicException("SR.GetString(SR.Cryptography_OpenInvalidHandle)"); } key = LegacyBCryptHandleToNCryptHandle(bcryptKeyHandle); } GC.KeepAlive(safeCertContext); return(new ECDsaCng(key)); }
internal static extern NTSTATUS BCryptExportKey(SafeBCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, [Out] byte[] pbOutput, int cbOutput, out int pcbResult, int dwFlags);
internal static unsafe extern NTSTATUS BCryptSecretAgreement(SafeBCryptKeyHandle hPrivKey, SafeBCryptKeyHandle hPubKey, out SafeBCryptSecretHandle phSecret, int dwFlags);
internal static unsafe partial bool CryptImportPublicKeyInfoEx2( CertEncodingType dwCertEncodingType, CERT_PUBLIC_KEY_INFO *pInfo, CryptImportPublicKeyInfoFlags dwFlags, void *pvAuxInfo, out SafeBCryptKeyHandle phKey);
public static extern NTStatus BCryptGenerateSymmetricKey(SafeBCryptAlgorithmHandle hAlgorithm, out SafeBCryptKeyHandle phKey, [Optional] IntPtr pbKeyObject, [Optional] int cbKeyObject, IntPtr pbSecret, int cbSecret, int dwFlags = 0);
public static extern NTStatus BCryptDecrypt(SafeBCryptKeyHandle hKey, IntPtr pbInput, int cbInput, IntPtr pPaddingInfo, IntPtr pbIV, int cbIV, [Optional] IntPtr pbOutput, [Optional] int cbOutput, out int pcbResult, int dwFlags);
public static extern unsafe bool CryptImportPublicKeyInfoEx2(CertEncodingType dwCertEncodingType, CERT_PUBLIC_KEY_INFO *pInfo, int dwFlags, void *pvAuxInfo, out SafeBCryptKeyHandle phKey);
internal static unsafe extern NTSTATUS BCryptFinalizeKeyPair(SafeBCryptKeyHandle hKey, int dwFlags);
internal static unsafe extern NTSTATUS BCryptEncrypt(SafeBCryptKeyHandle hKey, void *pbInput, int cbInput, void *pPaddingInfo, void *pbIV, int cbIV, void *pbOutput, int cbOutput, out int pcbResult, int dwFlags);
internal static extern bool CryptImportPublicKeyInfoEx2( [In] uint dwCertEncodingType, [In] SafeLocalAllocHandle pInfo, [In] uint dwFlags, [In] IntPtr pvAuxInfo, [Out] out SafeBCryptKeyHandle phKey);
internal BCryptAuthenticatedSymmetricCryptoTransform(SafeBCryptAlgorithmHandle algorithm, byte[] key, byte[] nonce, byte[] authenticatedData, byte[] tag, bool chainingSupported) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(!algorithm.IsClosed && !algorithm.IsInvalid, "!algorithm.IsClosed && !algorithm.IsInvalid"); if (key == null) { throw new ArgumentNullException("key"); } if (tag == null) { throw new ArgumentNullException("tag"); } bool initializationComplete = false; RuntimeHelpers.PrepareConstrainedRegions(); try { m_algorithm = algorithm; m_key = BCryptNative.ImportSymmetricKey(algorithm, key); // Initialize the padding info structure. m_authInfo = new BCryptNative.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO(); BCryptNative.InitializeAuthnenticatedCipherModeInfo(ref m_authInfo); if (nonce != null) { m_authInfo.cbNonce = nonce.Length; m_authInfo.pbNonce = Marshal.AllocCoTaskMem(m_authInfo.cbNonce); Marshal.Copy(nonce, 0, m_authInfo.pbNonce, m_authInfo.cbNonce); } if (authenticatedData != null) { m_authInfo.cbAuthData = authenticatedData.Length; m_authInfo.pbAuthData = Marshal.AllocCoTaskMem(m_authInfo.cbAuthData); Marshal.Copy(authenticatedData, 0, m_authInfo.pbAuthData, m_authInfo.cbAuthData); } if (chainingSupported) { m_chainingSupported = chainingSupported; m_authInfo.cbMacContext = tag.Length; m_authInfo.pbMacContext = Marshal.AllocCoTaskMem(m_authInfo.cbMacContext); BCryptNative.BCRYPT_KEY_LENGTHS_STRUCT tagLengths = BCryptNative.GetValueTypeProperty <SafeBCryptAlgorithmHandle, BCryptNative.BCRYPT_KEY_LENGTHS_STRUCT>( algorithm, BCryptNative.ObjectPropertyName.AuthTagLength); m_chainData = new byte[tagLengths.dwMaxLength]; } else { m_inputBuffer = new MemoryStream(); } m_authInfo.cbTag = tag.Length; m_authInfo.pbTag = Marshal.AllocCoTaskMem(m_authInfo.cbTag); Marshal.Copy(tag, 0, m_authInfo.pbTag, m_authInfo.cbTag); // Set chaining mode if supported. if (CanChainBlocks) { m_authInfo.dwFlags |= BCryptNative.AuthenticatedCipherModeInfoFlags.ChainCalls; } initializationComplete = true; } finally { // If we failed to complete initialization we may have already allocated some native // resources. Clean those up before leaving the constructor. if (!initializationComplete) { Dispose(); } } }
internal static extern NTSTATUS BCryptImportKey(SafeBCryptAlgorithmHandle hAlgorithm, IntPtr hImportKey, string pszBlobType, out SafeBCryptKeyHandle phKey, IntPtr pbKeyObject, int cbKeyObject, IntPtr pbInput, int cbInput, int dwFlags);
internal static extern NTSTATUS BCryptExportKey(SafeBCryptKeyHandle hKey, IntPtr encyrptKey, string blobType, IntPtr pbOutput, int cbOutput, out int pcbResult, int dwFlags);
internal static unsafe extern NTSTATUS BCryptGenerateKeyPair(SafeBCryptAlgorithmHandle hAlgorithm, out SafeBCryptKeyHandle phKey, int dwLength, int dwFlags);
private static bool HasExplicitParameters(SafeBCryptKeyHandle bcryptHandle) { const string BCRYPT_ECC_PARAMETERS_PROPERTY = "ECCParameters"; return(HasProperty(bcryptHandle, BCRYPT_ECC_PARAMETERS_PROPERTY)); }
private static string GetCurveName(SafeBCryptKeyHandle bcryptHandle) { const string BCRYPT_ECC_CURVE_NAME_PROPERTY = "ECCCurveName"; return(GetPropertyAsString(bcryptHandle, BCRYPT_ECC_CURVE_NAME_PROPERTY)); }