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)); } }
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)); } }
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)); } } }
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);
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); } }
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)); }
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)); } }
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 }
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); }
private static extern ErrorCode NCryptSecretAgreement( SafeNCryptKeyHandle hPrivKey, SafeNCryptKeyHandle hPubKey, [Out] out SafeNCryptSecretHandle phSecret, int dwFlags);
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)); } } } }
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); } } }