public override byte[] DeriveKeyFromHmac(
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            HashAlgorithmName hashAlgorithm,
            byte[]?hmacKey,
            byte[]?secretPrepend,
            byte[]?secretAppend)
        {
            ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
            ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                Interop.NCrypt.SecretAgreementFlags flags = hmacKey == null ?
                                                            Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey :
                                                            Interop.NCrypt.SecretAgreementFlags.None;

                return(Interop.NCrypt.DeriveKeyMaterialHmac(
                           secretAgreement,
                           hashAlgorithm.Name,
                           hmacKey,
                           secretPrepend,
                           secretAppend,
                           flags));
            }
        }
Example #2
0
        public override byte[] DeriveKeyFromHmac(
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            HashAlgorithmName hashAlgorithm,
            byte[] hmacKey,
            byte[] secretPrepend,
            byte[] secretAppend)
        {
            Contract.Ensures(Contract.Result <byte[]>() != null);

            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_HashAlgorithmNameNullOrEmpty), "hashAlgorithm");
            }

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                NCryptNative.SecretAgreementFlags flags = hmacKey == null ?
                                                          NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey :
                                                          NCryptNative.SecretAgreementFlags.None;

                return(NCryptNative.DeriveKeyMaterialHmac(
                           secretAgreement,
                           hashAlgorithm.Name,
                           hmacKey,
                           secretPrepend,
                           secretAppend,
                           flags));
            }
        }
Example #3
0
        public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
        {
            Contract.Ensures(Contract.Result <byte[]>() != null);

            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }
            if (prfLabel == null)
            {
                throw new ArgumentNullException("prfLabel");
            }
            if (prfSeed == null)
            {
                throw new ArgumentNullException("prfSeed");
            }

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                return(NCryptNative.DeriveKeyMaterialTls(
                           secretAgreement,
                           prfLabel,
                           prfSeed,
                           NCryptNative.SecretAgreementFlags.None));
            }
        }
        internal static unsafe byte[] DeriveKeyMaterialTls(SafeNCryptSecretHandle secretAgreement, byte[] label, byte[] seed, SecretAgreementFlags flags)
        {
            NCryptBuffer[] parameters = new NCryptBuffer[2];
            fixed(byte *numRef = label)
            {
                fixed(byte *numRef2 = seed)
                {
                    NCryptBuffer buffer = new NCryptBuffer {
                        cbBuffer   = label.Length,
                        BufferType = BufferType.KdfTlsLabel,
                        pvBuffer   = new IntPtr((void *)numRef)
                    };

                    parameters[0] = buffer;
                    NCryptBuffer buffer2 = new NCryptBuffer {
                        cbBuffer   = seed.Length,
                        BufferType = BufferType.KdfTlsSeed,
                        pvBuffer   = new IntPtr((void *)numRef2)
                    };

                    parameters[1] = buffer2;
                    return(DeriveKeyMaterial(secretAgreement, "TLS_PRF", parameters, flags));
                }
            }
        }
Example #5
0
 public static extern uint NCryptDeriveKey(SafeNCryptSecretHandle hSharedSecret,
                                           string kdf,
                                           NCryptBufferDesc parameterList,
                                           byte[] derivedKey,
                                           uint derivedKeyByteSize,
                                           out uint result,
                                           uint flags);
        private static unsafe byte[] DeriveKeyMaterial(SafeNCryptSecretHandle secretAgreement, string kdf, NCryptBuffer[] parameters, SecretAgreementFlags flags)
        {
            fixed(NCryptBuffer *bufferRef = parameters)
            {
                NCryptBufferDesc pParameterList = new NCryptBufferDesc {
                    ulVersion = 0,
                    cBuffers  = parameters.Length,
                    pBuffers  = new IntPtr((void *)bufferRef)
                };
                int       pcbResult = 0;
                ErrorCode code      = UnsafeNativeMethods.NCryptDeriveKey(secretAgreement, kdf, ref pParameterList, null, 0, out pcbResult, flags);

                if ((code != ErrorCode.Success) && (code != ErrorCode.BufferTooSmall))
                {
                    throw new CryptographicException((int)code);
                }
                byte[] pbDerivedKey = new byte[pcbResult];
                code = UnsafeNativeMethods.NCryptDeriveKey(secretAgreement, kdf, ref pParameterList, pbDerivedKey, pbDerivedKey.Length, out pcbResult, flags);
                if (code != ErrorCode.Success)
                {
                    throw new CryptographicException((int)code);
                }
                return(pbDerivedKey);
            }
        }
        internal static byte[] DeriveKeyMaterialTls(
            SafeNCryptSecretHandle secretAgreement,
            byte[] label,
            byte[] seed,
            SecretAgreementFlags flags)
        {
            Span <NCryptBuffer> buffers = stackalloc NCryptBuffer[2];

            unsafe
            {
                fixed(byte *pLabel = label, pSeed = seed)
                {
                    NCryptBuffer labelBuffer = default;

                    labelBuffer.cbBuffer   = label.Length;
                    labelBuffer.BufferType = BufferType.KdfTlsLabel;
                    labelBuffer.pvBuffer   = new IntPtr(pLabel);
                    buffers[0]             = labelBuffer;

                    NCryptBuffer seedBuffer = default;

                    seedBuffer.cbBuffer   = seed.Length;
                    seedBuffer.BufferType = BufferType.KdfTlsSeed;
                    seedBuffer.pvBuffer   = new IntPtr(pSeed);
                    buffers[1]            = seedBuffer;

                    return(DeriveKeyMaterial(
                               secretAgreement,
                               BCryptNative.KeyDerivationFunction.Tls,
                               buffers,
                               flags));
                }
            }
        }
        public override byte[] DeriveKeyFromHash(
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            HashAlgorithmName hashAlgorithm,
            byte[]?secretPrepend,
            byte[]?secretAppend)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException(nameof(otherPartyPublicKey));
            }
            if (string.IsNullOrEmpty(hashAlgorithm.Name))
            {
                throw new ArgumentException(SR.Cryptography_HashAlgorithmNameNullOrEmpty, nameof(hashAlgorithm));
            }

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                return(Interop.NCrypt.DeriveKeyMaterialHash(
                           secretAgreement,
                           hashAlgorithm.Name,
                           secretPrepend,
                           secretAppend,
                           Interop.NCrypt.SecretAgreementFlags.None));
            }
        }
        public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey)
        {
            ArgumentNullException.ThrowIfNull(otherPartyPublicKey);

            if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman)
            {
                throw new ArgumentException(SR.Cryptography_ArgECDHRequiresECDHKey, nameof(otherPartyPublicKey));
            }
            if (otherPartyPublicKey.KeySize != KeySize)
            {
                throw new ArgumentException(SR.Cryptography_ArgECDHKeySizeMismatch, nameof(otherPartyPublicKey));
            }

            // Setting the flag to UseSecretAsHmacKey even when the KDF isn't HMAC, because that's what .NET Framework does.
            Interop.NCrypt.SecretAgreementFlags flags =
                UseSecretAgreementAsHmacKey
                    ? Interop.NCrypt.SecretAgreementFlags.UseSecretAsHmacKey
                    : Interop.NCrypt.SecretAgreementFlags.None;

            using (SafeNCryptSecretHandle handle = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                switch (KeyDerivationFunction)
                {
                case ECDiffieHellmanKeyDerivationFunction.Hash:
                    return(Interop.NCrypt.DeriveKeyMaterialHash(
                               handle,
                               HashAlgorithm.Algorithm,
                               _secretPrepend,
                               _secretAppend,
                               flags));

                case ECDiffieHellmanKeyDerivationFunction.Hmac:
                    return(Interop.NCrypt.DeriveKeyMaterialHmac(
                               handle,
                               HashAlgorithm.Algorithm,
                               _hmacKey,
                               _secretPrepend,
                               _secretAppend,
                               flags));

                case ECDiffieHellmanKeyDerivationFunction.Tls:
                    if (_label == null || _seed == null)
                    {
                        throw new InvalidOperationException(SR.Cryptography_TlsRequiresLabelAndSeed);
                    }

                    return(Interop.NCrypt.DeriveKeyMaterialTls(
                               handle,
                               _label,
                               _seed,
                               flags));

                default:
                    Debug.Fail($"Unknown KDF ({KeyDerivationFunction})");
                    // Match .NET Framework behavior
                    goto case ECDiffieHellmanKeyDerivationFunction.Tls;
                }
            }
        }
 private static extern ErrorCode NCryptDeriveKey(
     SafeNCryptSecretHandle hSharedSecret,
     string pwszKDF,
     [In] ref NCryptBufferDesc pParameterList,
     [Out, MarshalAs(UnmanagedType.LPArray)] byte[]?pbDerivedKey,
     int cbDerivedKey,
     [Out] out int pcbResult,
     SecretAgreementFlags dwFlags);
Example #11
0
 public static extern ErrorCode NCryptDeriveKey(
     SafeNCryptSecretHandle hSharedSecret,
     [In] string pwszKDF,
     [In] ref NCryptBufferDesc pParameterList,
     [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbDerivedKey,
     int cbDerivedKey,
     [Out] out int pcbResult,
     int dwFlags);
        private static unsafe byte[] DeriveKeyMaterial(
            SafeNCryptSecretHandle secretAgreement,
            string kdf,
            ReadOnlySpan <NCryptBuffer> parameters,
            SecretAgreementFlags flags)
        {
            fixed(NCryptBuffer *pParameters = &MemoryMarshal.GetReference(parameters))
            {
                NCryptBufferDesc parameterDesc = default;

                parameterDesc.ulVersion = 0;
                parameterDesc.cBuffers  = parameters.Length;
                parameterDesc.pBuffers  = new IntPtr(pParameters);

                // Figure out how big the key material is
                ErrorCode error = NCryptDeriveKey(
                    secretAgreement,
                    kdf,
                    ref parameterDesc,
                    null,
                    0,
                    out int keySize,
                    flags);

                if (error != ErrorCode.ERROR_SUCCESS && error != ErrorCode.NTE_BUFFER_TOO_SMALL)
                {
                    throw error.ToCryptographicException();
                }

                // Allocate memory for the key material and generate it
                byte[] keyMaterial = new byte[keySize];

                error = NCryptDeriveKey(
                    secretAgreement,
                    kdf,
                    ref parameterDesc,
                    keyMaterial,
                    keyMaterial.Length,
                    out keySize,
                    flags);

                if (error != ErrorCode.ERROR_SUCCESS)
                {
                    throw error.ToCryptographicException();
                }

                // Just in case it shrank the answer once it had a buffer.
                Array.Resize(ref keyMaterial, Math.Min(keySize, keyMaterial.Length));
                return(keyMaterial);
            }
        }
Example #13
0
        public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
        {
            ArgumentNullException.ThrowIfNull(otherPartyPublicKey);
            ArgumentNullException.ThrowIfNull(prfLabel);
            ArgumentNullException.ThrowIfNull(prfSeed);

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                return(Interop.NCrypt.DeriveKeyMaterialTls(
                           secretAgreement,
                           prfLabel,
                           prfSeed,
                           Interop.NCrypt.SecretAgreementFlags.None));
            }
        }
 internal static byte[] DeriveKeyMaterialHash(
     SafeNCryptSecretHandle secretAgreement,
     string hashAlgorithm,
     byte[]?secretPrepend,
     byte[]?secretAppend,
     SecretAgreementFlags flags)
 {
     return(DeriveKeyMaterial(
                secretAgreement,
                BCryptNative.KeyDerivationFunction.Hash,
                hashAlgorithm,
                null,
                secretPrepend,
                secretAppend,
                flags));
 }
Example #15
0
        public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }
            if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman)
            {
                throw new ArgumentException(System.SR.GetString("Cryptography_ArgECDHRequiresECDHKey"), "otherPartyPublicKey");
            }
            if (otherPartyPublicKey.KeySize != this.KeySize)
            {
                throw new ArgumentException(System.SR.GetString("Cryptography_ArgECDHKeySizeMismatch"), "otherPartyPublicKey");
            }
            NCryptNative.SecretAgreementFlags flags = this.UseSecretAgreementAsHmacKey ? NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey : NCryptNative.SecretAgreementFlags.None;
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
            SafeNCryptKeyHandle privateKey = this.Key.Handle;
            SafeNCryptKeyHandle handle     = otherPartyPublicKey.Handle;

            CodeAccessPermission.RevertAssert();
            using (SafeNCryptSecretHandle handle3 = NCryptNative.DeriveSecretAgreement(privateKey, handle))
            {
                if (this.KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Hash)
                {
                    byte[] secretAppend  = (this.SecretAppend == null) ? null : (this.SecretAppend.Clone() as byte[]);
                    byte[] secretPrepend = (this.SecretPrepend == null) ? null : (this.SecretPrepend.Clone() as byte[]);
                    return(NCryptNative.DeriveKeyMaterialHash(handle3, this.HashAlgorithm.Algorithm, secretPrepend, secretAppend, flags));
                }
                if (this.KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Hmac)
                {
                    byte[] hmacKey = (this.HmacKey == null) ? null : (this.HmacKey.Clone() as byte[]);
                    byte[] buffer4 = (this.SecretAppend == null) ? null : (this.SecretAppend.Clone() as byte[]);
                    byte[] buffer5 = (this.SecretPrepend == null) ? null : (this.SecretPrepend.Clone() as byte[]);
                    return(NCryptNative.DeriveKeyMaterialHmac(handle3, this.HashAlgorithm.Algorithm, hmacKey, buffer5, buffer4, flags));
                }
                byte[] label = (this.Label == null) ? null : (this.Label.Clone() as byte[]);
                byte[] seed  = (this.Seed == null) ? null : (this.Seed.Clone() as byte[]);
                if ((label == null) || (seed == null))
                {
                    throw new InvalidOperationException(System.SR.GetString("Cryptography_TlsRequiresLabelAndSeed"));
                }
                return(NCryptNative.DeriveKeyMaterialTls(handle3, label, seed, flags));
            }
        }
Example #16
0
        public static byte[] DeriveKey(CngKey externalPubKey, CngKey privateKey, int keyBitLength, byte[] algorithmId, byte[] partyVInfo, byte[] partyUInfo, byte[] suppPubInfo)
        {
#if NET40 || NET461
            using (var cng = new ECDiffieHellmanCng(privateKey))
            {
                using (SafeNCryptSecretHandle hSecretAgreement = cng.DeriveSecretAgreementHandle(externalPubKey))
                {
                    using (var algIdBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_ALGORITHMID, algorithmId))
                        using (var pviBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_PARTYVINFO, partyVInfo))
                            using (var pvuBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_PARTYUINFO, partyUInfo))
                                using (var spiBuffer = new NCrypt.NCryptBuffer(NCrypt.KDF_SUPPPUBINFO, suppPubInfo))
                                {
                                    using (var parameters = new NCrypt.NCryptBufferDesc(algIdBuffer, pviBuffer, pvuBuffer, spiBuffer))
                                    {
                                        uint derivedSecretByteSize;
                                        uint status = NCrypt.NCryptDeriveKey(hSecretAgreement, "SP800_56A_CONCAT", parameters, null, 0, out derivedSecretByteSize, 0);

                                        if (status != BCrypt.ERROR_SUCCESS)
                                        {
                                            throw new CryptographicException(string.Format("NCrypt.NCryptDeriveKey() failed with status code:{0}", status));
                                        }

                                        var secretKey = new byte[derivedSecretByteSize];

                                        status = NCrypt.NCryptDeriveKey(hSecretAgreement, "SP800_56A_CONCAT", parameters, secretKey, derivedSecretByteSize, out derivedSecretByteSize, 0);

                                        if (status != BCrypt.ERROR_SUCCESS)
                                        {
                                            throw new CryptographicException(string.Format("NCrypt.NCryptDeriveKey() failed with status code:{0}", status));
                                        }

                                        return(Arrays.LeftmostBits(secretKey, keyBitLength));
                                    }
                                }
                }
            }
        #elif NETSTANDARD1_4
            throw new NotImplementedException("not yet");
        #endif
        }
Example #17
0
        public static byte[] DeriveKey(CngKey externalPubKey, CngKey privateKey, int keyBitLength, byte[] algorithmId, byte[] partyVInfo, byte[] partyUInfo, byte[] suppPubInfo)
        {
            uint num;

            byte[] numArray;
            using (ECDiffieHellmanCng eCDiffieHellmanCng = new ECDiffieHellmanCng(privateKey))
            {
                using (SafeNCryptSecretHandle safeNCryptSecretHandle = eCDiffieHellmanCng.DeriveSecretAgreementHandle(externalPubKey))
                {
                    using (NCrypt.NCryptBuffer nCryptBuffer = new NCrypt.NCryptBuffer(8, algorithmId))
                    {
                        using (NCrypt.NCryptBuffer nCryptBuffer1 = new NCrypt.NCryptBuffer(10, partyVInfo))
                        {
                            using (NCrypt.NCryptBuffer nCryptBuffer2 = new NCrypt.NCryptBuffer(9, partyUInfo))
                            {
                                using (NCrypt.NCryptBuffer nCryptBuffer3 = new NCrypt.NCryptBuffer(11, suppPubInfo))
                                {
                                    using (NCrypt.NCryptBufferDesc nCryptBufferDesc = new NCrypt.NCryptBufferDesc(new NCrypt.NCryptBuffer[] { nCryptBuffer, nCryptBuffer1, nCryptBuffer2, nCryptBuffer3 }))
                                    {
                                        uint num1 = NCrypt.NCryptDeriveKey(safeNCryptSecretHandle, "SP800_56A_CONCAT", nCryptBufferDesc, null, 0, out num, 0);
                                        if (num1 != 0)
                                        {
                                            throw new CryptographicException(string.Format("NCrypt.NCryptDeriveKey() failed with status code:{0}", num1));
                                        }
                                        byte[] numArray1 = new byte[num];
                                        num1 = NCrypt.NCryptDeriveKey(safeNCryptSecretHandle, "SP800_56A_CONCAT", nCryptBufferDesc, numArray1, num, out num, 0);
                                        if (num1 != 0)
                                        {
                                            throw new CryptographicException(string.Format("NCrypt.NCryptDeriveKey() failed with status code:{0}", num1));
                                        }
                                        numArray = Arrays.LeftmostBits(numArray1, keyBitLength);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(numArray);
        }
        public override byte[] DeriveKeyTls(ECDiffieHellmanPublicKey otherPartyPublicKey, byte[] prfLabel, byte[] prfSeed)
        {
            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException(nameof(otherPartyPublicKey));
            }
            if (prfLabel == null)
            {
                throw new ArgumentNullException(nameof(prfLabel));
            }
            if (prfSeed == null)
            {
                throw new ArgumentNullException(nameof(prfSeed));
            }

            using (SafeNCryptSecretHandle secretAgreement = DeriveSecretAgreementHandle(otherPartyPublicKey))
            {
                return(Interop.NCrypt.DeriveKeyMaterialTls(
                           secretAgreement,
                           prfLabel,
                           prfSeed,
                           Interop.NCrypt.SecretAgreementFlags.None));
            }
        }
 private static partial ErrorCode NCryptSecretAgreement(
     SafeNCryptKeyHandle hPrivKey,
     SafeNCryptKeyHandle hPubKey,
     out SafeNCryptSecretHandle phSecret,
     int dwFlags);
        private static byte[] DeriveKeyMaterial(
            SafeNCryptSecretHandle secretAgreement,
            string kdf,
            string hashAlgorithm,
            byte[]?hmacKey,
            byte[]?secretPrepend,
            byte[]?secretAppend,
            SecretAgreementFlags flags)
        {
            // First marshal the hash algoritm
            IntPtr hashAlgorithmString = IntPtr.Zero;

            try
            {
                hashAlgorithmString = Marshal.StringToCoTaskMemUni(hashAlgorithm);

                Span <NCryptBuffer> parameters = stackalloc NCryptBuffer[4];
                int parameterCount             = 0;
                // We always need to marshal the hashing function
                NCryptBuffer hashAlgorithmBuffer = default;
                hashAlgorithmBuffer.cbBuffer   = (hashAlgorithm.Length + 1) * sizeof(char);
                hashAlgorithmBuffer.BufferType = BufferType.KdfHashAlgorithm;
                hashAlgorithmBuffer.pvBuffer   = hashAlgorithmString;

                parameters[parameterCount] = hashAlgorithmBuffer;
                parameterCount++;

                unsafe
                {
                    fixed(byte *pHmacKey = hmacKey, pSecretPrepend = secretPrepend, pSecretAppend = secretAppend)
                    {
                        //
                        // Now marshal the other parameters
                        //

                        if (pHmacKey != null)
                        {
                            NCryptBuffer hmacKeyBuffer = default;
                            hmacKeyBuffer.cbBuffer   = hmacKey !.Length;
                            hmacKeyBuffer.BufferType = BufferType.KdfHmacKey;
                            hmacKeyBuffer.pvBuffer   = new IntPtr(pHmacKey);

                            parameters[parameterCount] = hmacKeyBuffer;
                            parameterCount++;
                        }

                        if (pSecretPrepend != null)
                        {
                            NCryptBuffer secretPrependBuffer = default;
                            secretPrependBuffer.cbBuffer   = secretPrepend !.Length;
                            secretPrependBuffer.BufferType = BufferType.KdfSecretPrepend;
                            secretPrependBuffer.pvBuffer   = new IntPtr(pSecretPrepend);

                            parameters[parameterCount] = secretPrependBuffer;
                            parameterCount++;
                        }

                        if (pSecretAppend != null)
                        {
                            NCryptBuffer secretAppendBuffer = default;
                            secretAppendBuffer.cbBuffer   = secretAppend !.Length;
                            secretAppendBuffer.BufferType = BufferType.KdfSecretAppend;
                            secretAppendBuffer.pvBuffer   = new IntPtr(pSecretAppend);

                            parameters[parameterCount] = secretAppendBuffer;
                            parameterCount++;
                        }

                        return(DeriveKeyMaterial(
                                   secretAgreement,
                                   kdf,
                                   parameters.Slice(0, parameterCount),
                                   flags));
                    }
                }
            }
            finally
            {
                if (hashAlgorithmString != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(hashAlgorithmString);
                }
            }
        }
 internal static byte[] DeriveKeyMaterialHash(SafeNCryptSecretHandle secretAgreement, string hashAlgorithm, byte[] secretPrepend, byte[] secretAppend, SecretAgreementFlags flags)
 {
     return(DeriveKeyMaterial(secretAgreement, "HASH", hashAlgorithm, null, secretPrepend, secretAppend, flags));
 }
 internal static byte[] DeriveKeyMaterialHmac(SafeNCryptSecretHandle secretAgreement, string hashAlgorithm, byte[] hmacKey, byte[] secretPrepend, byte[] secretAppend, SecretAgreementFlags flags)
 {
     return(DeriveKeyMaterial(secretAgreement, "HMAC", hashAlgorithm, hmacKey, secretPrepend, secretAppend, flags));
 }
 internal static extern NCryptNative.ErrorCode NCryptSecretAgreement(SafeNCryptKeyHandle hPrivKey, SafeNCryptKeyHandle hPubKey, out SafeNCryptSecretHandle phSecret, int dwFlags);
        private static unsafe byte[] DeriveKeyMaterial(SafeNCryptSecretHandle secretAgreement, string kdf, string hashAlgorithm, byte[] hmacKey, byte[] secretPrepend, byte[] secretAppend, SecretAgreementFlags flags)
        {
            byte[] buffer5;
            List <NCryptBuffer> list = new List <NCryptBuffer>();
            IntPtr zero = IntPtr.Zero;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                }
                finally
                {
                    zero = Marshal.StringToCoTaskMemUni(hashAlgorithm);
                }
                NCryptBuffer item = new NCryptBuffer {
                    cbBuffer   = (hashAlgorithm.Length + 1) * 2,
                    BufferType = BufferType.KdfHashAlgorithm,
                    pvBuffer   = zero
                };
                list.Add(item);
                try
                {
                    fixed(byte *numRef = hmacKey)
                    {
                        fixed(byte *numRef2 = secretPrepend)
                        {
                            fixed(byte *numRef3 = secretAppend)
                            {
                                if (numRef != IntPtr.Zero)
                                {
                                    NCryptBuffer buffer2 = new NCryptBuffer {
                                        cbBuffer   = hmacKey.Length,
                                        BufferType = BufferType.KdfHmacKey,
                                        pvBuffer   = new IntPtr((void *)numRef)
                                    };
                                    list.Add(buffer2);
                                }
                                if (numRef2 != IntPtr.Zero)
                                {
                                    NCryptBuffer buffer3 = new NCryptBuffer {
                                        cbBuffer   = secretPrepend.Length,
                                        BufferType = BufferType.KdfSecretPrepend,
                                        pvBuffer   = new IntPtr((void *)numRef2)
                                    };
                                    list.Add(buffer3);
                                }
                                if (numRef3 != IntPtr.Zero)
                                {
                                    NCryptBuffer buffer4 = new NCryptBuffer {
                                        cbBuffer   = secretAppend.Length,
                                        BufferType = BufferType.KdfSecretAppend,
                                        pvBuffer   = new IntPtr((void *)numRef3)
                                    };
                                    list.Add(buffer4);
                                }
                                return(DeriveKeyMaterial(secretAgreement, kdf, list.ToArray(), flags));
                            }
                        }
                    }
                }
                finally
                {
                    numRef  = null;
                    numRef2 = null;
                    numRef3 = null;
                }
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(zero);
                }
            }
            return(buffer5);
        }
Example #25
0
 private static extern ErrorCode NCryptSecretAgreement(
     SafeNCryptKeyHandle hPrivKey,
     SafeNCryptKeyHandle hPubKey,
     [Out] out SafeNCryptSecretHandle phSecret,
     int dwFlags);
Example #26
0
        public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey)
        {
            Contract.Ensures(Contract.Result <byte[]>() != null);
            Contract.Assert(m_kdf >= ECDiffieHellmanKeyDerivationFunction.Hash &&
                            m_kdf <= ECDiffieHellmanKeyDerivationFunction.Tls);

            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }
            if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHRequiresECDHKey), "otherPartyPublicKey");
            }
            if (otherPartyPublicKey.KeySize != KeySize)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHKeySizeMismatch), "otherPartyPublicKey");
            }

            NCryptNative.SecretAgreementFlags flags =
                UseSecretAgreementAsHmacKey ? NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey : NCryptNative.SecretAgreementFlags.None;

            // We require access to the handles for generating key material. This is safe since we will never
            // expose these handles to user code
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();

            // This looks horribly wrong - but accessing the handle property actually returns a duplicate handle, which
            // we need to dispose of - otherwise, we're stuck keepign the resource alive until the GC runs.  This explicitly
            // is not disposing of the handle underlying the key dispite what the syntax looks like.
            using (SafeNCryptKeyHandle localKey = Key.Handle)
                using (SafeNCryptKeyHandle otherKey = otherPartyPublicKey.Handle) {
                    CodeAccessPermission.RevertAssert();

                    //
                    // Generating key material is a two phase process.
                    //   1. Generate the secret agreement
                    //   2. Pass the secret agreement through a KDF to get key material
                    //

                    using (SafeNCryptSecretHandle secretAgreement = NCryptNative.DeriveSecretAgreement(localKey, otherKey)) {
                        if (KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Hash)
                        {
                            byte[] secretAppend  = SecretAppend == null ? null : SecretAppend.Clone() as byte[];
                            byte[] secretPrepend = SecretPrepend == null ? null : SecretPrepend.Clone() as byte[];

                            return(NCryptNative.DeriveKeyMaterialHash(secretAgreement,
                                                                      HashAlgorithm.Algorithm,
                                                                      secretPrepend,
                                                                      secretAppend,
                                                                      flags));
                        }
                        else if (KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Hmac)
                        {
                            byte[] hmacKey       = HmacKey == null ? null : HmacKey.Clone() as byte[];
                            byte[] secretAppend  = SecretAppend == null ? null : SecretAppend.Clone() as byte[];
                            byte[] secretPrepend = SecretPrepend == null ? null : SecretPrepend.Clone() as byte[];

                            return(NCryptNative.DeriveKeyMaterialHmac(secretAgreement,
                                                                      HashAlgorithm.Algorithm,
                                                                      hmacKey,
                                                                      secretPrepend,
                                                                      secretAppend,
                                                                      flags));
                        }
                        else
                        {
                            Debug.Assert(KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Tls, "Unknown KDF");

                            byte[] label = Label == null ? null : Label.Clone() as byte[];
                            byte[] seed  = Seed == null ? null : Seed.Clone() as byte[];

                            if (label == null || seed == null)
                            {
                                throw new InvalidOperationException(SR.GetString(SR.Cryptography_TlsRequiresLabelAndSeed));
                            }

                            return(NCryptNative.DeriveKeyMaterialTls(secretAgreement, label, seed, flags));
                        }
                    }
                }
        }
Example #27
0
 public static extern uint NCryptSecretAgreement(SafeNCryptKeyHandle hPrivKey, SafeNCryptKeyHandle hPublicKey, out SafeNCryptSecretHandle phSecret, uint flags);
        public static byte[] DeriveKeyMaterial(
            this ECDiffieHellmanCng provider,
            ECDiffieHellmanPublicKey otherPartyPublicKey,
            byte[] algorithmId,
            byte[] partyUInfo,
            byte[] partyVInfo)
        {
            Collection <IntPtr> ResourcesToFree = new Collection <IntPtr>();

            try
            {
                using SafeNCryptSecretHandle Agreement = provider.DeriveSecretAgreementHandle(otherPartyPublicKey);

                IntPtr AlgorithmIdPtr = Marshal.AllocHGlobal(algorithmId.Length);
                ResourcesToFree.Add(AlgorithmIdPtr);
                Marshal.Copy(algorithmId, 0, AlgorithmIdPtr, algorithmId.Length);

                IntPtr PartyUPtr = Marshal.AllocHGlobal(partyUInfo.Length);
                ResourcesToFree.Add(PartyUPtr);
                Marshal.Copy(partyUInfo, 0, PartyUPtr, partyUInfo.Length);

                IntPtr PartyVPtr = Marshal.AllocHGlobal(partyVInfo.Length);
                ResourcesToFree.Add(PartyVPtr);
                Marshal.Copy(partyVInfo, 0, PartyVPtr, partyVInfo.Length);

                NativeMethods.NCryptBuffer[] Buffers = new NativeMethods.NCryptBuffer[]
                {
                    new NativeMethods.NCryptBuffer
                    {
                        cbBuffer   = (uint)algorithmId.Length,
                        BufferType = NativeMethods.BufferType.KDF_ALGORITHMID,
                        pvBuffer   = AlgorithmIdPtr
                    },
                    new NativeMethods.NCryptBuffer
                    {
                        cbBuffer   = (uint)partyUInfo.Length,
                        BufferType = NativeMethods.BufferType.KDF_PARTYUINFO,
                        pvBuffer   = PartyUPtr
                    },
                    new NativeMethods.NCryptBuffer
                    {
                        cbBuffer   = (uint)partyVInfo.Length,
                        BufferType = NativeMethods.BufferType.KDF_PARTYVINFO,
                        pvBuffer   = PartyVPtr
                    }
                };

                IntPtr BufferPtr = Marshal.AllocHGlobal(Buffers.Length * Marshal.SizeOf(typeof(NativeMethods.NCryptBuffer)));

                ResourcesToFree.Add(BufferPtr);

                IntPtr Location = BufferPtr;
                for (int i = 0; i < Buffers.Length; i++)
                {
                    Marshal.StructureToPtr(Buffers[i], Location, false);
                    Location = new IntPtr(Location.ToInt64() + Marshal.SizeOf(typeof(NativeMethods.NCryptBuffer)));
                }

                NativeMethods.NCryptBufferDesc ParameterList = new NativeMethods.NCryptBufferDesc
                {
                    cBuffers = Buffers.Length,
                    pBuffers = BufferPtr
                };

                byte[] DerivedKey = new byte[32];

                NativeMethods.ErrorCode ErrorCode = NativeMethods.NCryptDeriveKey(
                    Agreement,
                    "SP800_56A_CONCAT",
                    ref ParameterList,
                    DerivedKey,
                    DerivedKey.Length,
                    out int NumberOfBytesDerived,
                    0);

                if (ErrorCode != NativeMethods.ErrorCode.Success)
                {
                    throw new InvalidOperationException($"KeyMaterial could not be derived. ErrorCode [{ErrorCode}], Win32Error [{Marshal.GetLastWin32Error()}] returned.");
                }

                if (NumberOfBytesDerived != 32)
                {
                    throw new InvalidOperationException("KeyMaterial size was invalid.");
                }

                return(DerivedKey);
            }
            finally
            {
                foreach (IntPtr Resource in ResourcesToFree)
                {
                    Marshal.FreeHGlobal(Resource);
                }
            }
        }