Example #1
0
        internal static SafeBCryptKeyHandle ImportKey(SafeBCryptAlgorithmHandle algorithm, byte[] key)
        {
            const int BCRYPT_KEY_DATA_BLOB_MAGIC = 0x4d42444b;

            // Concatenate the BCRYPT_KEY_DATA_BLOB header and the raw key.
            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   = BCRYPT_KEY_DATA_BLOB_MAGIC;
                    pkeyDataBlob->dwVersion = 1;
                    pkeyDataBlob->cbKeyData = key.Length;
                }
            }
            Buffer.BlockCopy(key, 0, keyBlob, Marshal.SizeOf(typeof(BCRYPT_KEY_DATA_BLOB)), key.Length);

            int cbKeyData = BitConverter.ToInt32(GetProperty(algorithm, "ObjectLength"), 0);
            var pbKeyData = Marshal.AllocCoTaskMem(cbKeyData);

            ErrorCode error = UnsafeNativeMethods.BCryptImportKey(algorithm, IntPtr.Zero, "KeyDataBlob", out var keyHandle, pbKeyData, cbKeyData, keyBlob, keyBlob.Length, 0);

            if (error == ErrorCode.Success)
            {
                keyHandle.DataBuffer = pbKeyData;
                return(keyHandle);
            }
            else
            {
                Marshal.FreeCoTaskMem(pbKeyData);
                throw new CryptographicException("Failed to import key: error " + error);
            }
        }
Example #2
0
        public unsafe void SetKey(Span <byte> key)
        {
            var keyBlob = stackalloc byte[sizeof(BCRYPT_KEY_DATA_BLOB) + _keyLength];
            BCRYPT_KEY_DATA_BLOB *pkeyDataBlob = (BCRYPT_KEY_DATA_BLOB *)keyBlob;

            pkeyDataBlob->dwMagic   = BCRYPT_KEY_DATA_BLOB_MAGIC;
            pkeyDataBlob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
            pkeyDataBlob->cbKeyData = _keyLength;
            var keyBlobSpan = new Span <byte>(keyBlob + sizeof(BCRYPT_KEY_DATA_BLOB), _keyLength);

            key.CopyTo(keyBlobSpan);
            Interop.Windows.ExceptionHelper.CheckReturnCode(
                BCryptImportKey(_algo, IntPtr.Zero, "KeyDataBlob", out _key, IntPtr.Zero, 0, (IntPtr)keyBlob, sizeof(BCRYPT_KEY_DATA_BLOB) + _keyLength, 0));
            BCryptPropertiesHelper.SetBlockChainingMode(_key, _chainingMode);
            _blockLength  = BCryptPropertiesHelper.GetBlockLength(_key);
            _maxTagLength = _blockLength;
        }
Example #3
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);
                    }
                }
            }
        }