internal BCryptHMAC(CngAlgorithm algorithm, CngProvider algorithmProvider, string hashName, int blockSize, byte[] key) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(algorithmProvider != null, "algorithmProvider != null"); Debug.Assert(!String.IsNullOrEmpty(hashName), "!String.IsNullOrEmpty(hashName)"); Debug.Assert(blockSize > 0, "blockSize > 0"); Debug.Assert(key != null, "key != null"); BlockSizeValue = blockSize; HashName = hashName; m_algorithm = BCryptNative.OpenAlgorithm(algorithm.Algorithm, algorithmProvider.Provider, BCryptNative.AlgorithmProviderOptions.HmacAlgorithm); // Resetting the key will call Initialize for us, and get us setup with a hash handle, // so we don't need to create the hash handle ourselves Key = key; HashSizeValue = BCryptNative.GetInt32Property(m_hash, BCryptNative.HashPropertyName.HashLength) * 8; }
internal BCryptHMAC(CngAlgorithm algorithm, CngProvider algorithmProvider, string hashName, int blockSize, byte[] key) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(algorithmProvider != null, "algorithmProvider != null"); Debug.Assert(!String.IsNullOrEmpty(hashName), "!String.IsNullOrEmpty(hashName)"); Debug.Assert(blockSize > 0, "blockSize > 0"); Debug.Assert(key != null, "key != null"); BlockSizeValue = blockSize; // We set the HashName up to be the CNG version of the hash, since the base type will instantiate // the algorithm, and the CNG versions have different FIPS characteristics than the standard implementations. HashName = String.Format(CultureInfo.InvariantCulture, "System.Security.Cryptography.{0}Cng, {1}", hashName, typeof(SHA256Cng).Assembly.FullName); m_implementation = algorithmProvider; m_algorithm = BCryptNative.OpenAlgorithm(algorithm.Algorithm, algorithmProvider.Provider, BCryptNative.AlgorithmProviderOptions.HmacAlgorithm); // Resetting the key will call Initialize for us, and get us setup with a hash handle, // so we don't need to create the hash handle ourselves Key = key; HashSizeValue = BCryptNative.GetInt32Property(m_hash, BCryptNative.HashPropertyName.HashLength) * 8; }
private void UpdateLegalTagSizes() { using (SafeBCryptAlgorithmHandle algorithm = SetupAlgorithm()) { UpdateLegalTagSizes(algorithm); } }
internal static extern ErrorCode BCryptCreateHash(SafeBCryptAlgorithmHandle hAlgorithm, [Out] out SafeBCryptHashHandle hHash, IntPtr pbHashObject, // byte * int cbHashObject, [In, MarshalAs(UnmanagedType.LPArray)] byte[] pbSecret, int cbSecret, int dwFlags);
internal BCryptAuthenticatedSymmetricAlgorithm(CngAlgorithm algorithm, CngProvider implementation, KeySizes[] legalBlockSizes, KeySizes[] legalKeySizes) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(implementation != null, "implementation != null"); Debug.Assert(legalBlockSizes != null, "legalBlockSizes != null"); Debug.Assert(legalKeySizes != null, "legalKeySizes != null"); m_algorithm = algorithm; m_implementation = implementation; m_chainingMode = CngChainingMode.Gcm; LegalBlockSizesValue = legalBlockSizes; LegalKeySizesValue = legalKeySizes; // Create a temporary algorithm handle so that we can query it for some properties - such as the // block and tag sizes. using (SafeBCryptAlgorithmHandle algorithmHandle = SetupAlgorithm()) { // Get block size in bits BlockSize = BCryptNative.GetInt32Property(algorithmHandle, BCryptNative.ObjectPropertyName.BlockLength) * 8; UpdateLegalTagSizes(algorithmHandle); } }
internal static extern ErrorCode BCryptImportKey(SafeBCryptAlgorithmHandle hAlgorithm, IntPtr hImportKey, [MarshalAs(UnmanagedType.LPWStr)] string pszBlobType, [Out] out SafeBCryptKeyHandle phKey, [In, Out] IntPtr pbKeyObject, // BYTE * int cbKeyObject, [In, MarshalAs(UnmanagedType.LPArray)] byte[] pbInput, int cbInput, int dwFlags);
internal BCryptAuthenticatedSymmetricCryptoTransform(SafeBCryptAlgorithmHandle algorithm, byte[] key, byte[] nonce, byte[] authenticatedData, bool chainingSupported, int tagSize) : this(algorithm, key, nonce, authenticatedData, new byte[tagSize / 8], chainingSupported) { m_encrypting = true; }
public RNGCng(CngProvider algorithmProvider) { if (algorithmProvider == null) { throw new ArgumentNullException("algorithmProvider"); } m_algorithm = BCryptNative.OpenAlgorithm(BCryptNative.AlgorithmName.Rng, algorithmProvider.Provider); }
internal static SafeBCryptHashHandle CreateHash(SafeBCryptAlgorithmHandle algorithm, byte[] secret) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(!algorithm.IsClosed && !algorithm.IsInvalid, "!algorithm.IsClosed && !algorithm.IsInvalid"); IntPtr hashObject = IntPtr.Zero; SafeBCryptHashHandle hash = null; RuntimeHelpers.PrepareConstrainedRegions(); try { // Figure out how big of a buffer is needed for the hash object and allocate it int hashObjectSize = GetInt32Property(algorithm, ObjectPropertyName.ObjectLength); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { hashObject = Marshal.AllocCoTaskMem(hashObjectSize); } // Create the hash object ErrorCode error = UnsafeNativeMethods.BCryptCreateHash(algorithm, out hash, hashObject, hashObjectSize, secret, secret != null ? secret.Length : 0, 0); if (error != ErrorCode.Success) { throw new CryptographicException((int)error); } // Transfer ownership of the buffer to the safe handle hash.DataBuffer = hashObject; return(hash); } finally { // If the safe hash handle never took ownership of the data buffer, free it now. if (hashObject != IntPtr.Zero) { if (hash == null || hash.DataBuffer == IntPtr.Zero) { Marshal.FreeCoTaskMem(hashObject); } } } }
private SafeBCryptAlgorithmHandle SetupAlgorithm() { // Open the algorithm handle SafeBCryptAlgorithmHandle algorithm = BCryptNative.OpenAlgorithm(m_algorithm.Algorithm, m_implementation.Provider); // Set the chaining mode BCryptNative.SetStringProperty(algorithm, BCryptNative.ObjectPropertyName.ChainingMode, m_chainingMode.ChainingMode); return(algorithm); }
private SafeBCryptAlgorithmHandle SetupAlgorithm() { SafeBCryptAlgorithmHandle algorithmHandle = BCryptNative.OpenAlgorithm(m_algorithm.Algorithm, m_algorithmProvider.Provider); // If we've selected a different block size than the default, set that now if (BlockSize / 8 != BCryptNative.GetInt32Property(algorithmHandle, BCryptNative.ObjectPropertyName.BlockLength)) { BCryptNative.SetInt32Property(algorithmHandle, BCryptNative.ObjectPropertyName.BlockLength, BlockSize / 8); } BCryptNative.SetStringProperty(algorithmHandle, BCryptNative.ObjectPropertyName.ChainingMode, BCryptNative.MapChainingMode(Mode)); return(algorithmHandle); }
internal static void GenerateRandomBytes(SafeBCryptAlgorithmHandle algorithm, byte[] buffer) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(!algorithm.IsClosed && !algorithm.IsInvalid, "!algorithm.IsClosed && !algorithm.IsInvalid"); Debug.Assert(buffer != null, "buffer != null"); ErrorCode error = UnsafeNativeMethods.BCryptGenRandom(algorithm, buffer, buffer.Length, 0); if (error != ErrorCode.Success) { throw new CryptographicException((int)error); } }
internal static SafeBCryptAlgorithmHandle OpenAlgorithm(string algorithm, string implementation, AlgorithmProviderOptions options) { Debug.Assert(!String.IsNullOrEmpty(algorithm), "!String.IsNullOrEmpty(algorithm)"); Debug.Assert(!String.IsNullOrEmpty(implementation), "!String.IsNullOrEmpty(implementation)"); SafeBCryptAlgorithmHandle algorithmHandle = null; ErrorCode error = UnsafeNativeMethods.BCryptOpenAlgorithmProvider(out algorithmHandle, algorithm, implementation, options); if (error != ErrorCode.Success) { throw new CryptographicException((int)error); } return(algorithmHandle); }
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 void UpdateLegalTagSizes(SafeBCryptAlgorithmHandle algorithm) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(!algorithm.IsClosed && !algorithm.IsInvalid, "!algorithm.IsClosed && !algorithm.IsInvalid"); // Get the authentication tag length structure. BCryptNative.BCRYPT_KEY_LENGTHS_STRUCT tagLengths = BCryptNative.GetValueTypeProperty <SafeBCryptAlgorithmHandle, BCryptNative.BCRYPT_KEY_LENGTHS_STRUCT>( algorithm, BCryptNative.ObjectPropertyName.AuthTagLength); // BCrypt returns the tag sizes in bytes, convert them to bits for the LegalTagSizes property LegalTagSizesValue = new KeySizes[] { new KeySizes(tagLengths.dwMinLength * 8, tagLengths.dwMaxLength * 8, tagLengths.dwIncrement * 8) }; // By default, generate the maximum authentication tag length possible for this algorithm TagSize = tagLengths.dwMaxLength * 8; }
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 ErrorCode BCryptGenRandom(SafeBCryptAlgorithmHandle hAlgorithm, [In, Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbBuffer, int cbBuffer, int dwFlags);
internal static extern ErrorCode BCryptGetAlgorithmProperty(SafeBCryptAlgorithmHandle hObject, [MarshalAs(UnmanagedType.LPWStr)] string pszProperty, [In, Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbOutput, int cbOutput, [In, Out] ref int pcbResult, int flags);
internal static extern ErrorCode BCryptOpenAlgorithmProvider([Out] out SafeBCryptAlgorithmHandle phAlgorithm, [MarshalAs(UnmanagedType.LPWStr)] string pszAlgId, [MarshalAs(UnmanagedType.LPWStr)] string pszImplementation, AlgorithmProviderOptions dwFlags);
internal static extern ErrorCode BCryptSetAlgorithmProperty(SafeBCryptAlgorithmHandle hObject, [MarshalAs(UnmanagedType.LPWStr)] string pszProperty, [In, MarshalAs(UnmanagedType.LPArray)] byte[] pbInput, int cbInput, int dwFlags);
internal static SafeBCryptKeyHandle ImportSymmetricKey(SafeBCryptAlgorithmHandle algorithm, byte[] key) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(!algorithm.IsClosed && !algorithm.IsInvalid, "!algorithm.IsClosed && !algorithm.IsInvalid"); Debug.Assert(key != null, "buffer != null"); IntPtr keyDataBuffer = IntPtr.Zero; SafeBCryptKeyHandle keyHandle = null; RuntimeHelpers.PrepareConstrainedRegions(); try { // Build up the key blob structure in memory. BCryptImportKey requries a // BCRYPT_KEY_DATA_BLOB header immediately followed by the raw key data. byte[] keyBlob = new byte[Marshal.SizeOf(typeof(BCRYPT_KEY_DATA_BLOB)) + key.Length]; unsafe { fixed(byte *pbKeyBlob = keyBlob) { BCRYPT_KEY_DATA_BLOB *pkeyDataBlob = (BCRYPT_KEY_DATA_BLOB *)pbKeyBlob; pkeyDataBlob->dwMagic = KeyBlobMagicNumber.KeyDataBlob; pkeyDataBlob->dwVersion = 1; pkeyDataBlob->cbKeyData = key.Length; } } Buffer.BlockCopy(key, 0, keyBlob, Marshal.SizeOf(typeof(BCRYPT_KEY_DATA_BLOB)), key.Length); // Figure out how big of a key data buffer we need and allocate space on the native heap for // it. We cannot use a managed array here because the address needs to stay constant for // the lifetime of the algorithm handle. Pinning for a potentially long lifetime is // undesirable, so we use a native heap allocation instead. int keyDataSize = GetInt32Property(algorithm, ObjectPropertyName.ObjectLength); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { keyDataBuffer = Marshal.AllocCoTaskMem(keyDataSize); } // Import the key ErrorCode error = UnsafeNativeMethods.BCryptImportKey(algorithm, IntPtr.Zero, KeyBlobType.KeyDataBlob, out keyHandle, keyDataBuffer, keyDataSize, keyBlob, keyBlob.Length, 0); if (error != ErrorCode.Success) { throw new CryptographicException((int)error); } // Give the key ownership of the key data buffer keyHandle.DataBuffer = keyDataBuffer; return(keyHandle); } finally { // If we allocated a key data buffer, but never transfered ownership to the key handle, then // we need to free it now otherwise it will leak. if (keyDataBuffer != IntPtr.Zero) { if (keyHandle == null || keyHandle.DataBuffer == IntPtr.Zero) { Marshal.FreeCoTaskMem(keyDataBuffer); } } } }