Example #1
0
        public unsafe void DeriveSecret(IHashProvider hashProvider, HashType hashType, void *salt, int saltSize, void *output, int outputSize)
        {
            SafeBCryptSecretHandle returnPtr;

            ExceptionHelper.CheckReturnCode(BCryptSecretAgreement(_key, _peerKey, out returnPtr, 0));
            var buffDescription = new BCryptBufferDesc();
            var bufferArray     = stackalloc BCryptBuffer[2];
            var algId           = System.Text.Encoding.Unicode.GetBytes(hashType.ToString().ToUpper() + "\0");

            buffDescription.pBuffers = (IntPtr)bufferArray;
            buffDescription.cBuffers = 2;
            fixed(byte *algPtr = algId)
            {
                bufferArray[0] = new BCryptBuffer()
                {
                    BufferType = NCryptBufferDescriptors.KDF_HASH_ALGORITHM, cbBuffer = algId.Length, pvBuffer = algPtr
                };
                bufferArray[1] = new BCryptBuffer()
                {
                    BufferType = NCryptBufferDescriptors.KDF_HMAC_KEY, cbBuffer = saltSize, pvBuffer = salt
                };
                int sizeOfResult;

                ExceptionHelper.CheckReturnCode(BCryptDeriveKey(returnPtr, BCRYPT_KDF_HMAC, &buffDescription, (IntPtr)output, outputSize, out sizeOfResult, 0));
                returnPtr.Dispose();
                Dispose();
            }
        }
Example #2
0
 public static extern NTStatus BCryptDeriveKey(
     SafeSecretHandle sharedSecret,
     string keyDerivationFunction,
     [In] ref BCryptBufferDesc kdfParameters,
     [Out, MarshalAs(UnmanagedType.LPArray)] byte[] derivedKey,
     int derivedKeySize,
     [Out] out int resultSize,
     BCryptDeriveKeyFlags flags);
Example #3
0
        public void DeriveKey(byte *pbLabel, uint cbLabel, byte *pbContext, uint cbContext, byte *pbDerivedKey, uint cbDerivedKey)
        {
            const int SHA512_ALG_CHAR_COUNT = 7;
            char *    pszHashAlgorithm      = stackalloc char[SHA512_ALG_CHAR_COUNT /* includes terminating null */];

            pszHashAlgorithm[0] = 'S';
            pszHashAlgorithm[1] = 'H';
            pszHashAlgorithm[2] = 'A';
            pszHashAlgorithm[3] = '5';
            pszHashAlgorithm[4] = '1';
            pszHashAlgorithm[5] = '2';
            pszHashAlgorithm[6] = (char)0;

            // First, build the buffers necessary to pass (label, context, PRF algorithm) into the KDF
            BCryptBuffer *pBuffers = stackalloc BCryptBuffer[3];

            pBuffers[0].BufferType = BCryptKeyDerivationBufferType.KDF_LABEL;
            pBuffers[0].pvBuffer   = (IntPtr)pbLabel;
            pBuffers[0].cbBuffer   = cbLabel;

            pBuffers[1].BufferType = BCryptKeyDerivationBufferType.KDF_CONTEXT;
            pBuffers[1].pvBuffer   = (IntPtr)pbContext;
            pBuffers[1].cbBuffer   = cbContext;

            pBuffers[2].BufferType = BCryptKeyDerivationBufferType.KDF_HASH_ALGORITHM;
            pBuffers[2].pvBuffer   = (IntPtr)pszHashAlgorithm;
            pBuffers[2].cbBuffer   = checked (SHA512_ALG_CHAR_COUNT * sizeof(char));

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

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

            // Finally, invoke the KDF
            uint numBytesDerived;
            var  ntstatus = UnsafeNativeMethods.BCryptKeyDerivation(
                hKey: _keyHandle,
                pParameterList: &bufferDesc,
                pbDerivedKey: pbDerivedKey,
                cbDerivedKey: cbDerivedKey,
                pcbResult: out numBytesDerived,
                dwFlags: 0);

            UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

            // Final sanity checks before returning control to caller.
            CryptoUtil.Assert(numBytesDerived == cbDerivedKey, "numBytesDerived == cbDerivedKey");
        }
        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");
            }
        }
Example #5
0
        public unsafe void DeriveMasterSecretTls12(IHashProvider hashProvider, HashType hashType, void *seed, int seedLength, void *output, int outputLength)
        {
            uint version         = 0x0303;
            var  buffDescription = new BCryptBufferDesc();
            var  bufferArray     = stackalloc BCryptBuffer[4];
            var  algId           = Encoding.Unicode.GetBytes(hashType.ToString() + "\0");

            fixed(void *algPtr = algId)
            {
                bufferArray[0] = new BCryptBuffer()
                {
                    BufferType = NCryptBufferDescriptors.KDF_HASH_ALGORITHM, cbBuffer = algId.Length, pvBuffer = algPtr
                };
                bufferArray[1] = new BCryptBuffer()
                {
                    BufferType = NCryptBufferDescriptors.KDF_TLS_PRF_LABEL, cbBuffer = Tls13.Internal.Tls1_2Consts.MasterSecretLabelSize, pvBuffer = (void *)Tls13.Internal.Tls1_2Consts.MasterSecretLabelPointer
                };
                bufferArray[2] = new BCryptBuffer()
                {
                    BufferType = NCryptBufferDescriptors.KDF_TLS_PRF_SEED, cbBuffer = seedLength, pvBuffer = seed
                };
                bufferArray[3] = new BCryptBuffer()
                {
                    BufferType = NCryptBufferDescriptors.KDF_TLS_PRF_PROTOCOL, cbBuffer = 4, pvBuffer = &version
                };
                buffDescription.cBuffers = 4;
                buffDescription.pBuffers = (IntPtr)bufferArray;
                int sizeOfResult;
                SafeBCryptSecretHandle secretPointer;

                ExceptionHelper.CheckReturnCode(BCryptSecretAgreement(_key, _peerKey, out secretPointer, 0));
                ExceptionHelper.CheckReturnCode(
                    BCryptDeriveKey(secretPointer, BCRYPT_KDF_TLS_PRF, &buffDescription, (IntPtr)output, outputLength, out sizeOfResult, 0));
                secretPointer.Dispose();
                Dispose();
            }
        }
Example #6
0
        /// <inheritdoc />
        public byte[] DeriveKeyMaterial(IECDiffieHellmanPublicKey otherParty)
        {
            Requires.NotNull(otherParty, nameof(otherParty));

            var publicKey = (ECDiffieHellmanPublicKey)otherParty;
            using (var secret = BCryptSecretAgreement(this.PlatformKey, publicKey.Key))
            {
                IntPtr hashAlgorithmPtr = IntPtr.Zero;
                try
                {
                    string hashAlgorithmString = HashAlgorithmProviderFactory.GetHashAlgorithmName(this.HashAlgorithm);
                    try
                    {
                    }
                    finally
                    {
                        // Do this in a finally so that ThreadAbortException doesn't interrupt the
                        // assignment of a successfully allocated pointer.
                        hashAlgorithmPtr = Marshal.StringToHGlobalUni(hashAlgorithmString);
                    }

                    var parameters = new List<BCryptBuffer>();
                    parameters.Add(new BCryptBuffer
                    {
                        cbBuffer = (hashAlgorithmString.Length + 1) * sizeof(char),
                        BufferType = BufferType.KDF_HASH_ALGORITHM,
                        pvBuffer_IntPtr = hashAlgorithmPtr,
                    });

                    const string kdf = KeyDerivationFunctions.HASH;
                    unsafe
                    {
                        fixed (BCryptBuffer* pParameters = parameters.ToArray())
                        {
                            var parameterDesc = new BCryptBufferDesc
                            {
                                ulVersion = 0,
                                cBuffers = parameters.Count,
                                pBuffers = pParameters,
                            };

                            int secretLength;
                            BCryptDeriveKey(
                                secret,
                                kdf,
                                ref parameterDesc,
                                null,
                                0,
                                out secretLength,
                                BCryptDeriveKeyFlags.KDF_USE_SECRET_AS_HMAC_KEY_FLAG).ThrowOnError();

                            byte[] derivedKey = new byte[secretLength];
                            BCryptDeriveKey(
                                secret,
                                kdf,
                                ref parameterDesc,
                                derivedKey,
                                derivedKey.Length,
                                out secretLength,
                                0).ThrowOnError();
                            Assumes.True(secretLength == derivedKey.Length);
                            return derivedKey;
                        }
                    }
                }
                finally
                {
                    if (hashAlgorithmPtr != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(hashAlgorithmPtr);
                    }
                }
            }
        }
Example #7
0
        /// <inheritdoc />
        public byte[] DeriveKeyMaterial(IECDiffieHellmanPublicKey otherParty)
        {
            Requires.NotNull(otherParty, nameof(otherParty));

            var publicKey = (ECDiffieHellmanPublicKey)otherParty;

            using (var secret = BCryptSecretAgreement(this.PlatformKey, publicKey.Key))
            {
                IntPtr hashAlgorithmPtr = IntPtr.Zero;
                try
                {
                    string hashAlgorithmString = HashAlgorithmProviderFactory.GetHashAlgorithmName(this.HashAlgorithm);
                    try
                    {
                    }
                    finally
                    {
                        // Do this in a finally so that ThreadAbortException doesn't interrupt the
                        // assignment of a successfully allocated pointer.
                        hashAlgorithmPtr = Marshal.StringToHGlobalUni(hashAlgorithmString);
                    }

                    var parameters = new List <BCryptBuffer>();
                    parameters.Add(new BCryptBuffer
                    {
                        cbBuffer        = (hashAlgorithmString.Length + 1) * sizeof(char),
                        BufferType      = BufferType.KDF_HASH_ALGORITHM,
                        pvBuffer_IntPtr = hashAlgorithmPtr,
                    });

                    const string kdf = KeyDerivationFunctions.BCRYPT_KDF_HASH;
                    unsafe
                    {
                        fixed(BCryptBuffer *pParameters = parameters.ToArray())
                        {
                            var parameterDesc = new BCryptBufferDesc
                            {
                                ulVersion = 0,
                                cBuffers  = parameters.Count,
                                pBuffers  = pParameters,
                            };

                            int secretLength;

                            BCryptDeriveKey(
                                secret,
                                kdf,
                                ref parameterDesc,
                                null,
                                0,
                                out secretLength,
                                BCryptDeriveKeyFlags.KDF_USE_SECRET_AS_HMAC_KEY_FLAG).ThrowOnError();

                            byte[] derivedKey = new byte[secretLength];
                            BCryptDeriveKey(
                                secret,
                                kdf,
                                ref parameterDesc,
                                derivedKey,
                                derivedKey.Length,
                                out secretLength,
                                0).ThrowOnError();
                            Assumes.True(secretLength == derivedKey.Length);
                            return(derivedKey);
                        }
                    }
                }
                finally
                {
                    if (hashAlgorithmPtr != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(hashAlgorithmPtr);
                    }
                }
            }
        }
Example #8
0
 public static void Initialize(ref BCryptBufferDesc bufferDesc)
 {
     bufferDesc.ulVersion = BCRYPTBUFFER_VERSION;
 }
Example #9
0
        public unsafe static void Main(string[] args)
        {
            var thumb   = "48026c976caaf7f3a72d38c17d16ce69d04a6053".ToUpper();
            var cert    = LoadCertificateFromStore(thumb, false, StoreLocation.CurrentUser, StoreName.My);
            var privKey = cert.GetECDsaPrivateKey();
            var curve   = privKey.ExportParameters(true);



            List <byte> currentSection = null;
            var         lines          = ecdsaKeyPEM.Split('\n');

            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i].StartsWith("-----BEGIN"))
                {
                    //Starting a block
                    string blockName = lines[i].Substring("-----BEGIN ".Length, lines[i].LastIndexOf("-----") - "-----BEGIN ".Length);
                    currentSection = new List <byte>();
                    _sections.Add(blockName, currentSection);
                    continue;
                }
                else if (lines[i].StartsWith("-----END"))
                {
                    //ending block
                    currentSection = null;
                }
                currentSection?.AddRange(Convert.FromBase64String(lines[i].Trim()));
            }

            IntPtr prov, key;
            var    res = NCryptOpenStorageProvider(out prov, "Microsoft Software Key Storage Provider", 0);

            //ECDSA_P521

            var size       = sizeof(BCRYPT_ECCKEY_BLOB);
            var blobHeader = new BCRYPT_ECCKEY_BLOB()
            {
                Magic = KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC,
                cbKey = _sections["EC PRIVATE KEY"].Count
            };

            var desc = new BCryptBufferDesc()
            {
                cBuffers = 1
            };
            var buff = new BCryptBuffer()
            {
                BufferType = NCryptBufferDescriptors.NCRYPTBUFFER_ECC_CURVE_NAME,
                cbBuffer   = "ECDSA_P521\0".Length * 2,
                pvBuffer   = Marshal.StringToHGlobalUni("ECDSA_P521\0")
            };
            var buffPtr = Marshal.AllocHGlobal(sizeof(BCryptBuffer));

            Marshal.StructureToPtr(buff, buffPtr, true);
            desc.pBuffers = buffPtr;
            var descPtr = Marshal.AllocHGlobal(sizeof(BCryptBufferDesc));

            Marshal.StructureToPtr(desc, descPtr, true);

            var bytes = new byte[size + blobHeader.cbKey];

            _sections["EC PRIVATE KEY"].ToArray().CopyTo(bytes, size);
            fixed(void *blobPtr = bytes)
            {
                Unsafe.Copy(blobPtr, ref blobHeader);

                res = NCryptImportKey(prov, IntPtr.Zero, "ECCPRIVATEBLOB", descPtr, out key, (IntPtr)blobPtr, (uint)bytes.Length, 0);
            }
        }