예제 #1
0
        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;
        }
예제 #2
0
        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);
     }
 }
예제 #4
0
 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);
            }
        }
예제 #6
0
 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;
 }
예제 #8
0
        public RNGCng(CngProvider algorithmProvider)
        {
            if (algorithmProvider == null)
            {
                throw new ArgumentNullException("algorithmProvider");
            }

            m_algorithm = BCryptNative.OpenAlgorithm(BCryptNative.AlgorithmName.Rng,
                                                     algorithmProvider.Provider);
        }
예제 #9
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        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);
            }
        }
예제 #13
0
        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();
                }
            }
        }
예제 #17
0
 internal static extern ErrorCode BCryptGenRandom(SafeBCryptAlgorithmHandle hAlgorithm,
                                                  [In, Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbBuffer,
                                                  int cbBuffer,
                                                  int dwFlags);
예제 #18
0
 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);
예제 #19
0
 internal static extern ErrorCode BCryptOpenAlgorithmProvider([Out] out SafeBCryptAlgorithmHandle phAlgorithm,
                                                              [MarshalAs(UnmanagedType.LPWStr)] string pszAlgId,
                                                              [MarshalAs(UnmanagedType.LPWStr)] string pszImplementation,
                                                              AlgorithmProviderOptions dwFlags);
예제 #20
0
 internal static extern ErrorCode BCryptSetAlgorithmProperty(SafeBCryptAlgorithmHandle hObject,
                                                             [MarshalAs(UnmanagedType.LPWStr)] string pszProperty,
                                                             [In, MarshalAs(UnmanagedType.LPArray)] byte[] pbInput,
                                                             int cbInput,
                                                             int dwFlags);
예제 #21
0
        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);
                    }
                }
            }
        }