コード例 #1
0
        // 'pbIV' must be a pointer to a buffer equal in length to the symmetric algorithm block size.
        private void DoCbcEncrypt(BCryptKeyHandle symmetricKeyHandle, byte *pbIV, byte *pbInput, uint cbInput, byte *pbOutput, uint cbOutput)
        {
            // BCryptEncrypt mutates the provided IV; we need to clone it to prevent mutation of the original value
            byte *pbClonedIV = stackalloc byte[checked ((int)_symmetricAlgorithmBlockSizeInBytes)];

            UnsafeBufferUtil.BlockCopy(from: pbIV, to: pbClonedIV, byteCount: _symmetricAlgorithmBlockSizeInBytes);

            uint dwEncryptedBytes;
            var  ntstatus = UnsafeNativeMethods.BCryptEncrypt(
                hKey: symmetricKeyHandle,
                pbInput: pbInput,
                cbInput: cbInput,
                pPaddingInfo: null,
                pbIV: pbClonedIV,
                cbIV: _symmetricAlgorithmBlockSizeInBytes,
                pbOutput: pbOutput,
                cbOutput: cbOutput,
                pcbResult: out dwEncryptedBytes,
                dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING);

            UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

            // Need to make sure we didn't underrun the buffer - means caller passed a bad value
            CryptoUtil.Assert(dwEncryptedBytes == cbOutput, "dwEncryptedBytes == cbOutput");
        }
コード例 #2
0
 // http://msdn.microsoft.com/en-us/library/windows/desktop/hh448506(v=vs.85).aspx
 internal static extern int BCryptKeyDerivation(
     [In] BCryptKeyHandle hKey,
     [In] BCryptBufferDesc *pParameterList,
     [In] byte *pbDerivedKey,
     [In] uint cbDerivedKey,
     [Out] out uint pcbResult,
     [In] uint dwFlags);
コード例 #3
0
        public byte[] DeriveKey(string password, byte[] salt, KeyDerivationPrf prf, int iterationCount, int numBytesRequested)
        {
            Debug.Assert(password != null);
            Debug.Assert(salt != null);
            Debug.Assert(iterationCount > 0);
            Debug.Assert(numBytesRequested > 0);

            string algorithmName = PrfToCngAlgorithmId(prf);

            fixed(byte *pbHeapAllocatedSalt = salt)
            {
                byte  dummy; // CLR doesn't like pinning zero-length buffers, so this provides a valid memory address when working with zero-length buffers
                byte *pbSalt = (pbHeapAllocatedSalt != null) ? pbHeapAllocatedSalt : &dummy;

                byte[] retVal = new byte[numBytesRequested];
                using (BCryptKeyHandle keyHandle = PasswordToPbkdfKeyHandle(password, CachedAlgorithmHandles.PBKDF2, prf))
                {
                    fixed(byte *pbRetVal = retVal)
                    {
                        Pbkdf2Win8ImplStep2(keyHandle, algorithmName, pbSalt, (uint)salt.Length, (ulong)iterationCount, pbRetVal, (uint)retVal.Length);
                    }

                    return(retVal);
                }
            }
        }
コード例 #4
0
 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375453(v=vs.85).aspx
 internal static extern int BCryptGenerateSymmetricKey(
     [In] BCryptAlgorithmHandle hAlgorithm,
     [Out] out BCryptKeyHandle phKey,
     [In] IntPtr pbKeyObject,
     [In] uint cbKeyObject,
     [In] byte *pbSecret,
     [In] uint cbSecret,
     [In] uint dwFlags);
コード例 #5
0
    internal static extern int BCryptKeyDerivation(
#endif
        BCryptKeyHandle hKey,
        BCryptBufferDesc *pParameterList,
        byte *pbDerivedKey,
        uint cbDerivedKey,
        out uint pcbResult,
        uint dwFlags);
コード例 #6
0
    internal static extern int BCryptGenerateSymmetricKey(
#endif
        BCryptAlgorithmHandle hAlgorithm,
        out BCryptKeyHandle phKey,
        IntPtr pbKeyObject,
        uint cbKeyObject,
        byte *pbSecret,
        uint cbSecret,
        uint dwFlags);
コード例 #7
0
 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375391(v=vs.85).aspx
 internal static extern int BCryptDecrypt(
     [In] BCryptKeyHandle hKey,
     [In] byte *pbInput,
     [In] uint cbInput,
     [In] void *pPaddingInfo,
     [In] byte *pbIV,
     [In] uint cbIV,
     [In] byte *pbOutput,
     [In] uint cbOutput,
     [Out] out uint pcbResult,
     [In] BCryptEncryptFlags dwFlags);
コード例 #8
0
    internal static extern int BCryptDecrypt(
#endif
        BCryptKeyHandle hKey,
        byte *pbInput,
        uint cbInput,
        void *pPaddingInfo,
        byte *pbIV,
        uint cbIV,
        byte *pbOutput,
        uint cbOutput,
        out uint pcbResult,
        BCryptEncryptFlags dwFlags);
コード例 #9
0
        private static void Pbkdf2Win8ImplStep2(BCryptKeyHandle pbkdf2KeyHandle, string hashAlgorithm, byte *pbSalt, uint cbSalt, ulong iterCount, byte *pbDerivedBytes, uint cbDerivedBytes)
        {
            // First, build the buffers necessary to pass (hash alg, salt, iter count) into the KDF
            BCryptBuffer *pBuffers = stackalloc BCryptBuffer[3];

            pBuffers[0].BufferType = BCryptKeyDerivationBufferType.KDF_ITERATION_COUNT;
            pBuffers[0].pvBuffer   = (IntPtr)(&iterCount);
            pBuffers[0].cbBuffer   = sizeof(ulong);

            pBuffers[1].BufferType = BCryptKeyDerivationBufferType.KDF_SALT;
            pBuffers[1].pvBuffer   = (IntPtr)pbSalt;
            pBuffers[1].cbBuffer   = cbSalt;

            fixed(char *pszHashAlgorithm = hashAlgorithm)
            {
                pBuffers[2].BufferType = BCryptKeyDerivationBufferType.KDF_HASH_ALGORITHM;
                pBuffers[2].pvBuffer   = (IntPtr)pszHashAlgorithm;
                pBuffers[2].cbBuffer   = hashAlgorithm.GetTotalByteLengthIncludingNullTerminator();

                // Add the header which points to the buffers
                BCryptBufferDesc bufferDesc = default(BCryptBufferDesc);

                BCryptBufferDesc.Initialize(ref bufferDesc);
                bufferDesc.cBuffers = 3;
                bufferDesc.pBuffers = pBuffers;

                // Finally, import the KDK into the KDF algorithm, then invoke the KDF
                uint numBytesDerived;
                int  ntstatus = UnsafeNativeMethods.BCryptKeyDerivation(
                    hKey: pbkdf2KeyHandle,
                    pParameterList: &bufferDesc,
                    pbDerivedKey: pbDerivedBytes,
                    cbDerivedKey: cbDerivedBytes,
                    pcbResult: out numBytesDerived,
                    dwFlags: 0);

                UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

                // Final sanity checks before returning control to caller.
                CryptoUtil.Assert(numBytesDerived == cbDerivedBytes, "numBytesDerived == cbDerivedBytes");
            }
        }
コード例 #10
0
        private uint GetCbcEncryptedOutputSizeWithPadding(BCryptKeyHandle symmetricKeyHandle, byte *pbInput, uint cbInput)
        {
            // ok for this memory to remain uninitialized since nobody depends on it
            byte *pbIV = stackalloc byte[checked ((int)_symmetricAlgorithmBlockSizeInBytes)];

            // Calling BCryptEncrypt with a null output pointer will cause it to return the total number
            // of bytes required for the output buffer.
            uint dwResult;
            var  ntstatus = UnsafeNativeMethods.BCryptEncrypt(
                hKey: symmetricKeyHandle,
                pbInput: pbInput,
                cbInput: cbInput,
                pPaddingInfo: null,
                pbIV: pbIV,
                cbIV: _symmetricAlgorithmBlockSizeInBytes,
                pbOutput: null,
                cbOutput: 0,
                pcbResult: out dwResult,
                dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING);

            UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

            return(dwResult);
        }
コード例 #11
0
        // 'pbIV' must be a pointer to a buffer equal in length to the symmetric algorithm block size.
        private byte[] DoCbcDecrypt(BCryptKeyHandle symmetricKeyHandle, byte *pbIV, byte *pbInput, uint cbInput)
        {
            // BCryptDecrypt mutates the provided IV; we need to clone it to prevent mutation of the original value
            byte *pbClonedIV = stackalloc byte[checked ((int)_symmetricAlgorithmBlockSizeInBytes)];

            UnsafeBufferUtil.BlockCopy(from: pbIV, to: pbClonedIV, byteCount: _symmetricAlgorithmBlockSizeInBytes);

            // First, figure out how large an output buffer we require.
            // Ideally we'd be able to transform the last block ourselves and strip
            // off the padding before creating the return value array, but we don't
            // know the actual padding scheme being used under the covers (we can't
            // assume PKCS#7). So unfortunately we're stuck with the temporary buffer.
            // (Querying the output size won't mutate the IV.)
            uint dwEstimatedDecryptedByteCount;
            var  ntstatus = UnsafeNativeMethods.BCryptDecrypt(
                hKey: symmetricKeyHandle,
                pbInput: pbInput,
                cbInput: cbInput,
                pPaddingInfo: null,
                pbIV: pbClonedIV,
                cbIV: _symmetricAlgorithmBlockSizeInBytes,
                pbOutput: null,
                cbOutput: 0,
                pcbResult: out dwEstimatedDecryptedByteCount,
                dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING);

            UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

            var  decryptedPayload = new byte[dwEstimatedDecryptedByteCount];
            uint dwActualDecryptedByteCount;

            fixed(byte *pbDecryptedPayload = decryptedPayload)
            {
                byte dummy;

                // Perform the actual decryption.
                ntstatus = UnsafeNativeMethods.BCryptDecrypt(
                    hKey: symmetricKeyHandle,
                    pbInput: pbInput,
                    cbInput: cbInput,
                    pPaddingInfo: null,
                    pbIV: pbClonedIV,
                    cbIV: _symmetricAlgorithmBlockSizeInBytes,
                    pbOutput: (pbDecryptedPayload != null) ? pbDecryptedPayload : &dummy, // CLR won't pin zero-length arrays
                    cbOutput: dwEstimatedDecryptedByteCount,
                    pcbResult: out dwActualDecryptedByteCount,
                    dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING);
                UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);
            }

            // Decryption finished!
            CryptoUtil.Assert(dwActualDecryptedByteCount <= dwEstimatedDecryptedByteCount, "dwActualDecryptedByteCount <= dwEstimatedDecryptedByteCount");
            if (dwActualDecryptedByteCount == dwEstimatedDecryptedByteCount)
            {
                // payload takes up the entire buffer
                return(decryptedPayload);
            }
            else
            {
                // payload takes up only a partial buffer
                var resizedDecryptedPayload = new byte[dwActualDecryptedByteCount];
                Buffer.BlockCopy(decryptedPayload, 0, resizedDecryptedPayload, 0, resizedDecryptedPayload.Length);
                return(resizedDecryptedPayload);
            }
        }
コード例 #12
0
 public Win8SP800_108_CTR_HMACSHA512Provider(byte *pbKdk, uint cbKdk)
 {
     _keyHandle = ImportKey(pbKdk, cbKdk);
 }