Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Security / Cryptography / ECDiffieHellmanCng.cs / 1305376 / ECDiffieHellmanCng.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Diagnostics.Contracts; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography { ////// Key derivation functions used to transform the raw secret agreement into key material /// public enum ECDiffieHellmanKeyDerivationFunction { Hash, Hmac, Tls } ////// Wrapper for CNG's implementation of elliptic curve Diffie-Hellman key exchange /// [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public sealed class ECDiffieHellmanCng : ECDiffieHellman { private static KeySizes[] s_legalKeySizes = new KeySizes[] { new KeySizes(256, 384, 128), new KeySizes(521, 521, 0) }; private CngAlgorithm m_hashAlgorithm = CngAlgorithm.Sha256; private byte[] m_hmacKey; private CngKey m_key; private ECDiffieHellmanKeyDerivationFunction m_kdf = ECDiffieHellmanKeyDerivationFunction.Hash; private byte[] m_label; private byte[] m_secretAppend; private byte[] m_secretPrepend; private byte[] m_seed; // // Constructors // public ECDiffieHellmanCng() : this(521) { Contract.Ensures(LegalKeySizesValue != null); } //// [System.Security.SecurityCritical] public ECDiffieHellmanCng(int keySize) { Contract.Ensures(LegalKeySizesValue != null); if (!NCryptNative.NCryptSupported) { throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); } LegalKeySizesValue = s_legalKeySizes; KeySize = keySize; } //// // [System.Security.SecurityCritical] public ECDiffieHellmanCng(CngKey key) { Contract.Ensures(LegalKeySizesValue != null); Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDiffieHellman); if (key == null) { throw new ArgumentNullException("key"); } if (key.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHRequiresECDHKey), "key"); } if (!NCryptNative.NCryptSupported) { throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported)); } LegalKeySizesValue = s_legalKeySizes; // Make a copy of the key so that we continue to work if it gets disposed before this algorithm // // This requires an assert for UnmanagedCode since we'll need to access the raw handles of the key // and the handle constructor of CngKey. The assert is safe since ECDiffieHellmanCng will never // expose the key handles to calling code (without first demanding UnmanagedCode via the Handle // property of CngKey). new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); Key = CngKey.Open(key.Handle, key.IsEphemeral ? CngKeyHandleOpenOptions.EphemeralKey : CngKeyHandleOpenOptions.None); CodeAccessPermission.RevertAssert(); KeySize = m_key.KeySize; } ///// // /// Hash algorithm used with the Hash and HMAC KDFs /// public CngAlgorithm HashAlgorithm { get { Contract.Ensures(Contract.Result() != null); return m_hashAlgorithm; } set { Contract.Ensures(m_hashAlgorithm != null); if (m_hashAlgorithm == null) { throw new ArgumentNullException("value"); } m_hashAlgorithm = value; } } /// /// Key used with the HMAC KDF /// [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Reviewed API design exception since these are really setters for explicit byte arrays rather than properties that will be iterated by users")] public byte[] HmacKey { get { return m_hmacKey; } set { m_hmacKey = value; } } ////// KDF used to transform the secret agreement into key material /// public ECDiffieHellmanKeyDerivationFunction KeyDerivationFunction { get { Contract.Ensures(Contract.Result() >= ECDiffieHellmanKeyDerivationFunction.Hash && Contract.Result () <= ECDiffieHellmanKeyDerivationFunction.Tls); return m_kdf; } set { Contract.Ensures(m_kdf >= ECDiffieHellmanKeyDerivationFunction.Hash && m_kdf <= ECDiffieHellmanKeyDerivationFunction.Tls); if (value < ECDiffieHellmanKeyDerivationFunction.Hash || value > ECDiffieHellmanKeyDerivationFunction.Tls) { throw new ArgumentOutOfRangeException("value"); } m_kdf = value; } } /// /// Label bytes used for the TLS KDF /// [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Reviewed API design exception since these are really setters for explicit byte arrays rather than properties that will be iterated by users")] public byte[] Label { get { return m_label; } set { m_label = value; } } ////// Bytes to append to the raw secret agreement before processing by the KDF /// [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Reviewed API design exception since these are really setters for explicit byte arrays rather than properties that will be iterated by users")] public byte[] SecretAppend { get { return m_secretAppend; } set { m_secretAppend = value; } } ////// Bytes to prepend to the raw secret agreement before processing by the KDF /// [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Reviewed API design exception since these are really setters for explicit byte arrays rather than properties that will be iterated by users")] public byte[] SecretPrepend { get { return m_secretPrepend; } set { m_secretPrepend = value; } } ////// Seed bytes used for the TLS KDF /// [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Reviewed API design exception since these are really setters for explicit byte arrays rather than properties that will be iterated by users")] public byte[] Seed { get { return m_seed; } set { m_seed = value; } } ////// Full key pair being used for key generation /// public CngKey Key { get { Contract.Ensures(Contract.Result() != null); Contract.Ensures(Contract.Result ().AlgorithmGroup == CngAlgorithmGroup.ECDiffieHellman); Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDiffieHellman); // If the size of the key no longer matches our stored value, then we need to replace it with // a new key of the correct size. if (m_key != null && m_key.KeySize != KeySize) { m_key.Dispose(); m_key = null; } if (m_key == null) { // Map the current key size to a CNG algorithm name CngAlgorithm algorithm = null; switch (KeySize) { case 256: algorithm = CngAlgorithm.ECDiffieHellmanP256; break; case 384: algorithm = CngAlgorithm.ECDiffieHellmanP384; break; case 521: algorithm = CngAlgorithm.ECDiffieHellmanP521; break; default: Debug.Assert(false, "Illegal key size set"); break; } m_key = CngKey.Create(algorithm); } return m_key; } private set { Contract.Requires(value != null); Contract.Ensures(m_key != null && m_key.AlgorithmGroup == CngAlgorithmGroup.ECDiffieHellman); if (value.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHRequiresECDHKey)); } if (m_key != null) { m_key.Dispose(); } // // We do not duplicate the handle because the only time the user has access to the key itself // to dispose underneath us is when they construct via the CngKey constructor, which does a // duplication. Otherwise all key lifetimes are controlled directly by the ECDiffieHellmanCng // class. // m_key = value; KeySize = m_key.KeySize; } } /// /// Public key used to generate key material with the second party /// public override ECDiffieHellmanPublicKey PublicKey { //// [System.Security.SecurityCritical] get { Contract.Ensures(Contract.Result// () != null); return new ECDiffieHellmanCngPublicKey(Key); } } /// /// Use the secret agreement as the HMAC key rather than supplying a seperate one /// public bool UseSecretAgreementAsHmacKey { get { return HmacKey == null; } } ////// Given a second party's public key, derive shared key material /// public override byte[] DeriveKeyMaterial(ECDiffieHellmanPublicKey otherPartyPublicKey) { Contract.Ensures(Contract.Result() != null); Contract.Assert(m_kdf >= ECDiffieHellmanKeyDerivationFunction.Hash && m_kdf <= ECDiffieHellmanKeyDerivationFunction.Tls); if (otherPartyPublicKey == null) { throw new ArgumentNullException("otherPartyPublicKey"); } // We can only work with ECDiffieHellmanCngPublicKeys ECDiffieHellmanCngPublicKey otherKey = otherPartyPublicKey as ECDiffieHellmanCngPublicKey; if (otherPartyPublicKey == null) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgExpectedECDiffieHellmanCngPublicKey)); } using (CngKey import = otherKey.Import()) { return DeriveKeyMaterial(import); } } /// /// Given a second party's public key, derive shared key material /// //// [System.Security.SecurityCritical] public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey) { Contract.Ensures(Contract.Result// // // // // () != 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(); SafeNCryptKeyHandle localKey = Key.Handle; 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); } } } /// /// Get a handle to the secret agreement generated between two parties /// public SafeNCryptSecretHandle DeriveSecretAgreementHandle(ECDiffieHellmanPublicKey otherPartyPublicKey) { if (otherPartyPublicKey == null) { throw new ArgumentNullException("otherPartyPublicKey"); } // We can only work with ECDiffieHellmanCngPublicKeys ECDiffieHellmanCngPublicKey otherKey = otherPartyPublicKey as ECDiffieHellmanCngPublicKey; if (otherPartyPublicKey == null) { throw new ArgumentException(SR.GetString(SR.Cryptography_ArgExpectedECDiffieHellmanCngPublicKey)); } using (CngKey importedKey = otherKey.Import()) { return DeriveSecretAgreementHandle(importedKey); } } ////// Get a handle to the secret agreement between two parties /// //// [System.Security.SecurityCritical] [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] public SafeNCryptSecretHandle DeriveSecretAgreementHandle(CngKey otherPartyPublicKey) { 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"); } return NCryptNative.DeriveSecretAgreement(Key.Handle, otherPartyPublicKey.Handle); } ///// /// Clean up the algorithm /// protected override void Dispose(bool disposing) { try { if (disposing) { if (m_key != null) { m_key.Dispose(); } } } finally { base.Dispose(disposing); } } // // XML Import // // See code:System.Security.Cryptography.ECDsaCng#ECCXMLFormat and // code:System.Security.Cryptography.Rfc4050KeyFormatter#RFC4050ECKeyFormat for information about // elliptic curve XML formats. // public override void FromXmlString(string xmlString) { throw new NotImplementedException(SR.GetString(SR.Cryptography_ECXmlSerializationFormatRequired)); } public void FromXmlString(string xml, ECKeyXmlFormat format) { if (xml == null) { throw new ArgumentNullException("xml"); } if (format != ECKeyXmlFormat.Rfc4050) { throw new ArgumentOutOfRangeException("format"); } Key = Rfc4050KeyFormatter.FromXml(xml); } // // XML Export // // See code:System.Security.Cryptography.ECDsaCng#ECCXMLFormat and // code:System.Security.Cryptography.Rfc4050KeyFormatter#RFC4050ECKeyFormat for information about // elliptic curve XML formats. // public override string ToXmlString(bool includePrivateParameters) { throw new NotImplementedException(SR.GetString(SR.Cryptography_ECXmlSerializationFormatRequired)); } public string ToXmlString(ECKeyXmlFormat format) { Contract.Ensures(Contract.Result() != null); if (format != ECKeyXmlFormat.Rfc4050) { throw new ArgumentOutOfRangeException("format"); } return Rfc4050KeyFormatter.ToXml(Key); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HttpDictionary.cs
- TdsParserSessionPool.cs
- BaseComponentEditor.cs
- RemotingServices.cs
- ACL.cs
- BrushConverter.cs
- TabControlEvent.cs
- Int64AnimationUsingKeyFrames.cs
- FloaterParagraph.cs
- StandardToolWindows.cs
- ValidationErrorEventArgs.cs
- SoundPlayer.cs
- InternalCache.cs
- PropertyChangedEventArgs.cs
- TableLayoutPanelCellPosition.cs
- XmlSchemaException.cs
- AuthenticationManager.cs
- HandlerBase.cs
- DesignerActionMethodItem.cs
- StylesEditorDialog.cs
- StylusShape.cs
- ExceptionValidationRule.cs
- Control.cs
- SemanticResultValue.cs
- PolygonHotSpot.cs
- FixedElement.cs
- SizeValueSerializer.cs
- HtmlTextBoxAdapter.cs
- ProxyHelper.cs
- ProviderCommandInfoUtils.cs
- XXXInfos.cs
- DataRecordInternal.cs
- FramingFormat.cs
- TemplatePropertyEntry.cs
- _SslSessionsCache.cs
- ReturnEventArgs.cs
- WorkflowServiceHost.cs
- Debug.cs
- FontConverter.cs
- XmlSignatureManifest.cs
- TemplateBaseAction.cs
- ConfigurationLocation.cs
- SettingsPropertyIsReadOnlyException.cs
- WebPartVerbCollection.cs
- LineServicesCallbacks.cs
- EditableRegion.cs
- PointLight.cs
- OleDbError.cs
- PropertyInfoSet.cs
- WebHttpSecurityElement.cs
- IIS7UserPrincipal.cs
- ControlIdConverter.cs
- SortedList.cs
- DBSchemaRow.cs
- DesignerContextDescriptor.cs
- SqlBulkCopyColumnMapping.cs
- ObjectToIdCache.cs
- figurelengthconverter.cs
- EncoderFallback.cs
- ComponentResourceManager.cs
- AdapterDictionary.cs
- CircleHotSpot.cs
- DataColumnPropertyDescriptor.cs
- XmlNodeChangedEventArgs.cs
- LinqDataSourceContextEventArgs.cs
- DesignerValidationSummaryAdapter.cs
- DbProviderFactoriesConfigurationHandler.cs
- StdRegProviderWrapper.cs
- CapabilitiesAssignment.cs
- StylusDevice.cs
- PropertyAccessVisitor.cs
- ConnectorEditor.cs
- XamlFigureLengthSerializer.cs
- Decoder.cs
- DataGridViewColumnConverter.cs
- EntityDataSourceValidationException.cs
- StringDictionaryEditor.cs
- PopupRoot.cs
- DeviceContext.cs
- DecimalStorage.cs
- XPathItem.cs
- CaseCqlBlock.cs
- NTAccount.cs
- DateTime.cs
- XmlWrappingReader.cs
- precedingquery.cs
- VariantWrapper.cs
- precedingquery.cs
- IdleTimeoutMonitor.cs
- SynchronizationLockException.cs
- ListViewVirtualItemsSelectionRangeChangedEvent.cs
- BindingElementExtensionElement.cs
- ProcessHostFactoryHelper.cs
- SoapExtensionReflector.cs
- NameValueCache.cs
- DataRecordInfo.cs
- DataGridColumnCollection.cs
- Nullable.cs
- Constants.cs
- Visual.cs