diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorExtensions.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorExtensions.cs index 3bcd320cb8..6a2808e70d 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorExtensions.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptorExtensions.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption public static byte[] Encrypt(this IAuthenticatedEncryptor encryptor, ArraySegment plaintext, ArraySegment additionalAuthenticatedData, uint preBufferSize, uint postBufferSize) { // Can we call the optimized version? - IAuthenticatedEncryptor2 optimizedEncryptor = encryptor as IAuthenticatedEncryptor2; + IOptimizedAuthenticatedEncryptor optimizedEncryptor = encryptor as IOptimizedAuthenticatedEncryptor; if (optimizedEncryptor != null) { return optimizedEncryptor.Encrypt(plaintext, additionalAuthenticatedData, preBufferSize, postBufferSize); diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationFactory.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationFactory.cs index 22b254fe85..711330a151 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationFactory.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationFactory.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption { // generate a 512-bit secret randomly const int KDK_SIZE_IN_BYTES = 512 / 8; - var secret = ProtectedMemoryBlob.Random(KDK_SIZE_IN_BYTES); + var secret = Secret.Random(KDK_SIZE_IN_BYTES); return new CngCbcAuthenticatedEncryptorConfiguration(_options, secret); } } diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationOptions.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationOptions.cs index c9f6b4f8d0..9db38c5070 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationOptions.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationOptions.cs @@ -96,7 +96,7 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption // and we're good to go! return new CbcAuthenticatedEncryptor( - keyDerivationKey: new ProtectedMemoryBlob(secret), + keyDerivationKey: new Secret(secret), symmetricAlgorithmHandle: encryptionAlgorithmHandle, symmetricAlgorithmKeySizeInBytes: encryptionAlgorithmKeySizeInBits / 8, hmacAlgorithmHandle: hashAlgorithmHandle); diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationXmlReader.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationXmlReader.cs index d37f854c42..e47a6cd4f1 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationXmlReader.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptorConfigurationXmlReader.cs @@ -58,8 +58,8 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption byte[] decryptedSecretBytes = Convert.FromBase64String((string)decryptedSecretElement); try { - var protectedMemoryBlob = new ProtectedMemoryBlob(decryptedSecretBytes); - return new CngCbcAuthenticatedEncryptorConfiguration(options, protectedMemoryBlob); + var secret = new Secret(decryptedSecretBytes); + return new CngCbcAuthenticatedEncryptorConfiguration(options, secret); } finally { diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationFactory.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationFactory.cs index b184da69ab..996da69abc 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationFactory.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationFactory.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption { // generate a 512-bit secret randomly const int KDK_SIZE_IN_BYTES = 512 / 8; - var secret = ProtectedMemoryBlob.Random(KDK_SIZE_IN_BYTES); + var secret = Secret.Random(KDK_SIZE_IN_BYTES); return new CngGcmAuthenticatedEncryptorConfiguration(_options, secret); } } diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationOptions.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationOptions.cs index 271a43eefe..d8cd278490 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationOptions.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationOptions.cs @@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption // and we're good to go! return new GcmAuthenticatedEncryptor( - keyDerivationKey: new ProtectedMemoryBlob(secret), + keyDerivationKey: new Secret(secret), symmetricAlgorithmHandle: encryptionAlgorithmHandle, symmetricAlgorithmKeySizeInBytes: encryptionAlgorithmKeySizeInBits / 8); } diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationXmlReader.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationXmlReader.cs index e3fc4bad31..d826c54b3e 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationXmlReader.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptorConfigurationXmlReader.cs @@ -52,8 +52,8 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption byte[] decryptedSecretBytes = Convert.FromBase64String((string)decryptedSecretElement); try { - var protectedMemoryBlob = new ProtectedMemoryBlob(decryptedSecretBytes); - return new CngGcmAuthenticatedEncryptorConfiguration(options, protectedMemoryBlob); + var secret = new Secret(decryptedSecretBytes); + return new CngGcmAuthenticatedEncryptorConfiguration(options, secret); } finally { diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptor2.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptor2.cs deleted file mode 100644 index 2e36143dc3..0000000000 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/IAuthenticatedEncryptor2.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; - -namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption -{ - internal interface IAuthenticatedEncryptor2 : IAuthenticatedEncryptor - { - byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData, uint preBufferSize, uint postBufferSize); - } -} diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/IOptimizedAuthenticatedEncryptor.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/IOptimizedAuthenticatedEncryptor.cs new file mode 100644 index 0000000000..aa8d7c72fb --- /dev/null +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/IOptimizedAuthenticatedEncryptor.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption +{ + /// + /// An optimized encryptor that can avoid buffer allocations in common code paths. + /// + internal interface IOptimizedAuthenticatedEncryptor : IAuthenticatedEncryptor + { + /// + /// Encrypts and tamper-proofs a piece of data. + /// + /// The plaintext to encrypt. This input may be zero bytes in length. + /// A piece of data which will not be included in + /// the returned ciphertext but which will still be covered by the authentication tag. + /// This input may be zero bytes in length. The same AAD must be specified in the corresponding + /// call to Decrypt. + /// The number of bytes to include before the ciphertext in the return value. + /// The number of bytes to include after the ciphertext in the return value. + /// + /// A buffer containing the ciphertext and authentication tag. + /// If a non-zero pre-buffer or post-buffer size is specified, the returned buffer will contain appropriate padding + /// on either side of the ciphertext and authentication tag. For instance, if a pre-buffer size of 4 and a post-buffer + /// size of 7 are specified, and if the ciphertext and tag are a combined 48 bytes, then the returned buffer will + /// be a total 59 bytes in length. The first four bytes will be undefined, the next 48 bytes will contain the + /// ciphertext and tag, and the last seven bytes will be undefined. The intent is that the caller can overwrite the + /// pre-buffer or post-buffer with a header or footer without needing to allocate an additional buffer object. + /// + /// All cryptography-related exceptions should be homogenized to CryptographicException. + byte[] Encrypt(ArraySegment plaintext, ArraySegment additionalAuthenticatedData, uint preBufferSize, uint postBufferSize); + } +} diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationFactory.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationFactory.cs index 50fee4ab58..e64ddf6c07 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationFactory.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationFactory.cs @@ -21,10 +21,10 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption // generate a 512-bit secret randomly const int KDK_SIZE_IN_BYTES = 512 / 8; byte[] kdk = ManagedGenRandomImpl.Instance.GenRandom(KDK_SIZE_IN_BYTES); - ProtectedMemoryBlob secret; + Secret secret; try { - secret = new ProtectedMemoryBlob(kdk); + secret = new Secret(kdk); } finally { diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationOptions.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationOptions.cs index 9ebed10e96..673f0e2646 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationOptions.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationOptions.cs @@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption // We're good to go! return new ManagedAuthenticatedEncryptor( - keyDerivationKey: new ProtectedMemoryBlob(secret), + keyDerivationKey: new Secret(secret), symmetricAlgorithmFactory: encryptorFactory, symmetricAlgorithmKeySizeInBytes: keySizeInBytes, validationAlgorithmFactory: validatorFactory); diff --git a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationXmlReader.cs b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationXmlReader.cs index cfa38ed3ea..bdfbdccdc2 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationXmlReader.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptorConfigurationXmlReader.cs @@ -56,8 +56,8 @@ namespace Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption byte[] decryptedSecretBytes = Convert.FromBase64String((string)decryptedSecretElement); try { - var protectedMemoryBlob = new ProtectedMemoryBlob(decryptedSecretBytes); - return new ManagedAuthenticatedEncryptorConfiguration(options, protectedMemoryBlob); + var secret = new Secret(decryptedSecretBytes); + return new ManagedAuthenticatedEncryptorConfiguration(options, secret); } finally { diff --git a/src/Microsoft.AspNet.Security.DataProtection/BitHelpers.cs b/src/Microsoft.AspNet.Security.DataProtection/BitHelpers.cs index 379b5cdf5d..3e60ca7ca1 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/BitHelpers.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/BitHelpers.cs @@ -21,6 +21,20 @@ namespace Microsoft.AspNet.Security.DataProtection bytePtr[3] = (byte)(value); } + /// + /// Writes an unsigned 32-bit value to a memory address, big-endian. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteTo(ref byte* ptr, uint value) + { + byte* pTemp = ptr; + pTemp[0] = (byte)(value >> 24); + pTemp[1] = (byte)(value >> 16); + pTemp[2] = (byte)(value >> 8); + pTemp[3] = (byte)(value); + ptr = &pTemp[4]; + } + /// /// Writes a signed 32-bit value to a memory address, big-endian. /// diff --git a/src/Microsoft.AspNet.Security.DataProtection/Cng/CbcAuthenticatedEncryptor.cs b/src/Microsoft.AspNet.Security.DataProtection/Cng/CbcAuthenticatedEncryptor.cs index 819facee9f..9c7567a4da 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Cng/CbcAuthenticatedEncryptor.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Cng/CbcAuthenticatedEncryptor.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Security.Cryptography; using Microsoft.AspNet.Security.DataProtection.SafeHandles; using Microsoft.AspNet.Security.DataProtection.SP800_108; @@ -41,7 +40,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng private readonly uint _symmetricAlgorithmBlockSizeInBytes; private readonly uint _symmetricAlgorithmSubkeyLengthInBytes; - public CbcAuthenticatedEncryptor(ProtectedMemoryBlob keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, BCryptAlgorithmHandle hmacAlgorithmHandle, IBCryptGenRandom genRandom = null) + public CbcAuthenticatedEncryptor(Secret keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, BCryptAlgorithmHandle hmacAlgorithmHandle, IBCryptGenRandom genRandom = null) { CryptoUtil.Assert(KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES, "KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES"); @@ -88,16 +87,12 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng *(ptr++) = 0; // 0x00 = CBC encryption + HMAC authentication // Next is information about the symmetric algorithm (key size followed by block size) - BitHelpers.WriteTo(ptr, _symmetricAlgorithmSubkeyLengthInBytes); - ptr += sizeof(uint); - BitHelpers.WriteTo(ptr, _symmetricAlgorithmBlockSizeInBytes); - ptr += sizeof(uint); + BitHelpers.WriteTo(ref ptr, _symmetricAlgorithmSubkeyLengthInBytes); + BitHelpers.WriteTo(ref ptr, _symmetricAlgorithmBlockSizeInBytes); // Next is information about the HMAC algorithm (key size followed by digest size) - BitHelpers.WriteTo(ptr, _hmacAlgorithmSubkeyLengthInBytes); - ptr += sizeof(uint); - BitHelpers.WriteTo(ptr, _hmacAlgorithmDigestLengthInBytes); - ptr += sizeof(uint); + BitHelpers.WriteTo(ref ptr, _hmacAlgorithmSubkeyLengthInBytes); + BitHelpers.WriteTo(ref ptr, _hmacAlgorithmDigestLengthInBytes); // See the design document for an explanation of the following code. byte[] tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes]; @@ -348,7 +343,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng using (var symmetricKeyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbSymmetricEncryptionSubkey, _symmetricAlgorithmSubkeyLengthInBytes)) { - // We can't assume PKCS#7 padding (maybe the underlying provided is using CTS), + // We can't assume PKCS#7 padding (maybe the underlying provider is really using CTS), // so we need to query the padded output size before we can allocate the return value array. uint cbOutputCiphertext = GetCbcEncryptedOutputSizeWithPadding(symmetricKeyHandle, pbPlaintext, cbPlaintext); diff --git a/src/Microsoft.AspNet.Security.DataProtection/Cng/CngAuthenticatedEncryptorBase.cs b/src/Microsoft.AspNet.Security.DataProtection/Cng/CngAuthenticatedEncryptorBase.cs index 37450636a3..48f76f0937 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Cng/CngAuthenticatedEncryptorBase.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Cng/CngAuthenticatedEncryptorBase.cs @@ -2,12 +2,14 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Security.Cryptography; using Microsoft.AspNet.Security.DataProtection.AuthenticatedEncryption; namespace Microsoft.AspNet.Security.DataProtection.Cng { - internal unsafe abstract class CngAuthenticatedEncryptorBase : IAuthenticatedEncryptor, IDisposable + /// + /// Base class used for all CNG-related authentication encryption operations. + /// + internal unsafe abstract class CngAuthenticatedEncryptorBase : IOptimizedAuthenticatedEncryptor, IDisposable { public byte[] Decrypt(ArraySegment ciphertext, ArraySegment additionalAuthenticatedData) { @@ -30,7 +32,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng pbAdditionalAuthenticatedData: (pbAdditionalAuthenticatedDataArray != null) ? &pbAdditionalAuthenticatedDataArray[additionalAuthenticatedData.Offset] : &dummy, cbAdditionalAuthenticatedData: (uint)additionalAuthenticatedData.Count); } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize to CryptographicException. throw Error.CryptCommon_GenericError(ex); @@ -71,7 +73,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng cbPreBuffer: preBufferSize, cbPostBuffer: postBufferSize); } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize to CryptographicException. throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/Cng/DpapiSecretSerializerHelper.cs b/src/Microsoft.AspNet.Security.DataProtection/Cng/DpapiSecretSerializerHelper.cs index 9f1dbb2a6e..e5762f1190 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Cng/DpapiSecretSerializerHelper.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Cng/DpapiSecretSerializerHelper.cs @@ -172,7 +172,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng } } - public static ProtectedMemoryBlob UnprotectWithDpapi(byte[] protectedSecret) + public static Secret UnprotectWithDpapi(byte[] protectedSecret) { Debug.Assert(protectedSecret != null); @@ -185,7 +185,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng } } - internal static ProtectedMemoryBlob UnprotectWithDpapiImpl(byte* pbProtectedData, uint cbProtectedData, byte* pbOptionalEntropy, uint cbOptionalEntropy) + internal static Secret UnprotectWithDpapiImpl(byte* pbProtectedData, uint cbProtectedData, byte* pbOptionalEntropy, uint cbOptionalEntropy) { byte dummy; // provides a valid memory address if the secret or entropy has zero length @@ -220,7 +220,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng throw new CryptographicException(errorCode); } - return new ProtectedMemoryBlob(dataOut.pbData, checked((int)dataOut.cbData)); + return new Secret(dataOut.pbData, checked((int)dataOut.cbData)); } finally { @@ -234,7 +234,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng } } - public static ProtectedMemoryBlob UnprotectWithDpapiNG(byte[] protectedData) + public static Secret UnprotectWithDpapiNG(byte[] protectedData) { Debug.Assert(protectedData != null); @@ -247,7 +247,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng } } - private static ProtectedMemoryBlob UnprotectWithDpapiNGImpl(byte* pbData, uint cbData) + private static Secret UnprotectWithDpapiNGImpl(byte* pbData, uint cbData) { Debug.Assert(pbData != null); @@ -280,7 +280,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng try { unencryptedPayloadHandle.DangerousAddRef(ref handleAcquired); - return new ProtectedMemoryBlob((byte*)unencryptedPayloadHandle.DangerousGetHandle(), checked((int)cbUnencryptedPayload)); + return new Secret((byte*)unencryptedPayloadHandle.DangerousGetHandle(), checked((int)cbUnencryptedPayload)); } finally { diff --git a/src/Microsoft.AspNet.Security.DataProtection/Cng/GcmAuthenticatedEncryptor.cs b/src/Microsoft.AspNet.Security.DataProtection/Cng/GcmAuthenticatedEncryptor.cs index e5e67cd31b..d6b99f69c0 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Cng/GcmAuthenticatedEncryptor.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Cng/GcmAuthenticatedEncryptor.cs @@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng private readonly BCryptAlgorithmHandle _symmetricAlgorithmHandle; private readonly uint _symmetricAlgorithmSubkeyLengthInBytes; - public GcmAuthenticatedEncryptor(ProtectedMemoryBlob keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, IBCryptGenRandom genRandom = null) + public GcmAuthenticatedEncryptor(Secret keyDerivationKey, BCryptAlgorithmHandle symmetricAlgorithmHandle, uint symmetricAlgorithmKeySizeInBytes, IBCryptGenRandom genRandom = null) { CryptoUtil.Assert(KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES, "KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES"); @@ -67,14 +67,10 @@ namespace Microsoft.AspNet.Security.DataProtection.Cng *(ptr++) = 1; // 0x01 = GCM encryption + authentication // Next is information about the symmetric algorithm (key size, nonce size, block size, tag size) - BitHelpers.WriteTo(ptr, _symmetricAlgorithmSubkeyLengthInBytes); - ptr += sizeof(uint); - BitHelpers.WriteTo(ptr, NONCE_SIZE_IN_BYTES); - ptr += sizeof(uint); - BitHelpers.WriteTo(ptr, TAG_SIZE_IN_BYTES); // block size - ptr += sizeof(uint); - BitHelpers.WriteTo(ptr, TAG_SIZE_IN_BYTES); - ptr += sizeof(uint); + BitHelpers.WriteTo(ref ptr, _symmetricAlgorithmSubkeyLengthInBytes); + BitHelpers.WriteTo(ref ptr, NONCE_SIZE_IN_BYTES); + BitHelpers.WriteTo(ref ptr, TAG_SIZE_IN_BYTES); // block size = tag size + BitHelpers.WriteTo(ref ptr, TAG_SIZE_IN_BYTES); // See the design document for an explanation of the following code. byte[] tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes]; diff --git a/src/Microsoft.AspNet.Security.DataProtection/CryptoUtil.cs b/src/Microsoft.AspNet.Security.DataProtection/CryptoUtil.cs index 823e7aa213..e71807fdee 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/CryptoUtil.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/CryptoUtil.cs @@ -48,6 +48,8 @@ namespace Microsoft.AspNet.Security.DataProtection throw new CryptographicException("Assertion failed: " + message); } + // Allows callers to write "var x = Method() ?? Fail(message);" as a convenience to guard + // against a method returning null unexpectedly. [MethodImpl(MethodImplOptions.NoInlining)] public static T Fail(string message) where T : class { diff --git a/src/Microsoft.AspNet.Security.DataProtection/DataProtectionExtensions.cs b/src/Microsoft.AspNet.Security.DataProtection/DataProtectionExtensions.cs index dbfd3a1918..14f22b52b1 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/DataProtectionExtensions.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/DataProtectionExtensions.cs @@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Security.DataProtection byte[] protectedDataAsBytes = protector.Protect(unprotectedDataAsBytes); return WebEncoders.Base64UrlEncode(protectedDataAsBytes); } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize exceptions to CryptographicException throw Error.CryptCommon_GenericError(ex); @@ -60,7 +60,7 @@ namespace Microsoft.AspNet.Security.DataProtection byte[] unprotectedDataAsBytes = protector.Unprotect(protectedDataAsBytes); return CryptoUtil.SecureUtf8Encoding.GetString(unprotectedDataAsBytes); } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize exceptions to CryptographicException throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/Dpapi/DpapiDataProtector.cs b/src/Microsoft.AspNet.Security.DataProtection/Dpapi/DpapiDataProtector.cs index cf734290cc..a4b400e5e0 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Dpapi/DpapiDataProtector.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Dpapi/DpapiDataProtector.cs @@ -43,7 +43,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Dpapi return _shim.Protect(unprotectedData, _combinedPurposes, _scope) ?? CryptoUtil.Fail("Null return value."); } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize to CryptographicException throw Error.CryptCommon_GenericError(ex); @@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Dpapi return _shim.Unprotect(protectedData, _combinedPurposes, _scope) ?? CryptoUtil.Fail("Null return value."); } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize to CryptographicException throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/Dpapi/ProtectedDataImpl.cs b/src/Microsoft.AspNet.Security.DataProtection/Dpapi/ProtectedDataImpl.cs index ab6d8ac06f..cd5e579f66 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Dpapi/ProtectedDataImpl.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Dpapi/ProtectedDataImpl.cs @@ -32,7 +32,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Dpapi public byte[] Unprotect(byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope) { #if ASPNETCORE50 - ProtectedMemoryBlob blob; + Secret blob; fixed (byte* pbEncryptedData = encryptedData) { fixed (byte* pbOptionalEntropy = optionalEntropy) diff --git a/src/Microsoft.AspNet.Security.DataProtection/EphemeralDataProtectionProvider.cs b/src/Microsoft.AspNet.Security.DataProtection/EphemeralDataProtectionProvider.cs index 99bfe47d7a..8b87083b2c 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/EphemeralDataProtectionProvider.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/EphemeralDataProtectionProvider.cs @@ -50,7 +50,7 @@ namespace Microsoft.AspNet.Security.DataProtection // Currently hardcoded to a 512-bit KDK. private const int NUM_BYTES_IN_KDK = 512 / 8; - public IAuthenticatedEncryptor DefaultAuthenticatedEncryptor { get; } = new T().CreateAuthenticatedEncryptor(ProtectedMemoryBlob.Random(NUM_BYTES_IN_KDK)); + public IAuthenticatedEncryptor DefaultAuthenticatedEncryptor { get; } = new T().CreateAuthenticatedEncryptor(Secret.Random(NUM_BYTES_IN_KDK)); public Guid DefaultKeyId { get; } = default(Guid); diff --git a/src/Microsoft.AspNet.Security.DataProtection/ExceptionExtensions.cs b/src/Microsoft.AspNet.Security.DataProtection/ExceptionExtensions.cs new file mode 100644 index 0000000000..9335f3fc01 --- /dev/null +++ b/src/Microsoft.AspNet.Security.DataProtection/ExceptionExtensions.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Security.Cryptography; + +namespace Microsoft.AspNet.Security.DataProtection +{ + internal static class ExceptionExtensions + { + /// + /// Determines whether an exception must be homogenized by being wrapped inside a + /// CryptographicException before being rethrown. + /// + public static bool RequiresHomogenization(this Exception ex) + { + return !(ex is CryptographicException); + } + } +} diff --git a/src/Microsoft.AspNet.Security.DataProtection/ISecret.cs b/src/Microsoft.AspNet.Security.DataProtection/ISecret.cs index 8e73cc8cdd..0d787f9381 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/ISecret.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/ISecret.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNet.Security.DataProtection public interface ISecret : IDisposable { /// - /// The length (in bytes) of the value. + /// The length (in bytes) of the secret value. /// int Length { get; } diff --git a/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs b/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs index e5891f2d02..ecb87dad75 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/KeyRingBasedDataProtector.cs @@ -131,7 +131,7 @@ namespace Microsoft.AspNet.Security.DataProtection.KeyManagement postBufferSize: 0); CryptoUtil.Assert(retVal != null && retVal.Length >= sizeof(uint) + sizeof(Guid), "retVal != null && retVal.Length >= sizeof(uint) + sizeof(Guid)"); } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // homogenize all errors to CryptographicException throw Error.Common_EncryptionFailed(ex); @@ -247,7 +247,7 @@ namespace Microsoft.AspNet.Security.DataProtection.KeyManagement CryptoUtil.Assert(retVal != null, "retVal != null"); return retVal; } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // homogenize all failures to CryptographicException throw Error.DecryptionFailed(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/XmlKeyManager.cs b/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/XmlKeyManager.cs index d472869b48..27dff11346 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/XmlKeyManager.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/KeyManagement/XmlKeyManager.cs @@ -111,7 +111,7 @@ namespace Microsoft.AspNet.Security.DataProtection.KeyManagement var thisKey = ParseKeyElement(element); if (idToKeyMap.ContainsKey(thisKey.KeyId)) { - CryptoUtil.Fail("TODO: Duplicate key."); + throw CryptoUtil.Fail("TODO: Duplicate key."); } idToKeyMap.Add(thisKey.KeyId, thisKey); } @@ -140,7 +140,7 @@ namespace Microsoft.AspNet.Security.DataProtection.KeyManagement } else { - CryptoUtil.Fail("TODO: Unknown element."); + throw CryptoUtil.Fail("TODO: Unknown element."); } } diff --git a/src/Microsoft.AspNet.Security.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs b/src/Microsoft.AspNet.Security.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs index d384a5ff4a..f10003ece2 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Managed/ManagedAuthenticatedEncryptor.cs @@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Managed private readonly byte[] _contextHeader; private readonly IManagedGenRandom _genRandom; - private readonly ProtectedMemoryBlob _keyDerivationKey; + private readonly Secret _keyDerivationKey; private readonly Func _symmetricAlgorithmFactory; private readonly int _symmetricAlgorithmBlockSizeInBytes; private readonly int _symmetricAlgorithmSubkeyLengthInBytes; @@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Managed private readonly int _validationAlgorithmSubkeyLengthInBytes; private readonly Func _validationAlgorithmFactory; - public ManagedAuthenticatedEncryptor(ProtectedMemoryBlob keyDerivationKey, Func symmetricAlgorithmFactory, int symmetricAlgorithmKeySizeInBytes, Func validationAlgorithmFactory, IManagedGenRandom genRandom = null) + public ManagedAuthenticatedEncryptor(Secret keyDerivationKey, Func symmetricAlgorithmFactory, int symmetricAlgorithmKeySizeInBytes, Func validationAlgorithmFactory, IManagedGenRandom genRandom = null) { CryptoUtil.Assert(KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES, "KEY_MODIFIER_SIZE_IN_BYTES <= symmetricAlgorithmKeySizeInBytes && symmetricAlgorithmKeySizeInBytes <= Constants.MAX_STACKALLOC_BYTES"); @@ -278,7 +278,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Managed } } } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize all exceptions to CryptographicException. throw Error.CryptCommon_GenericError(ex); @@ -382,7 +382,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Managed } } } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize all exceptions to CryptographicException. throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Util.cs b/src/Microsoft.AspNet.Security.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Util.cs index 7eb8d4070d..7778e03013 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Util.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/SP800_108/SP800_108_CTR_HMACSHA512Util.cs @@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Security.DataProtection.SP800_108 } // Creates a provider from the given secret. - public static ISP800_108_CTR_HMACSHA512Provider CreateProvider(ProtectedMemoryBlob kdk) + public static ISP800_108_CTR_HMACSHA512Provider CreateProvider(Secret kdk) { uint secretLengthInBytes = checked((uint)kdk.Length); if (secretLengthInBytes == 0) diff --git a/src/Microsoft.AspNet.Security.DataProtection/ProtectedMemoryBlob.cs b/src/Microsoft.AspNet.Security.DataProtection/Secret.cs similarity index 76% rename from src/Microsoft.AspNet.Security.DataProtection/ProtectedMemoryBlob.cs rename to src/Microsoft.AspNet.Security.DataProtection/Secret.cs index f89af3bfdd..ddb8acdab1 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/ProtectedMemoryBlob.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/Secret.cs @@ -8,7 +8,10 @@ using Microsoft.AspNet.Security.DataProtection.SafeHandles; namespace Microsoft.AspNet.Security.DataProtection { - public unsafe sealed class ProtectedMemoryBlob : IDisposable, ISecret + /// + /// Represents a secret value stored in memory. + /// + public unsafe sealed class Secret : IDisposable, ISecret { // from wincrypt.h private const uint CRYPTPROTECTMEMORY_BLOCK_SIZE = 16; @@ -16,42 +19,57 @@ namespace Microsoft.AspNet.Security.DataProtection private readonly SecureLocalAllocHandle _localAllocHandle; private readonly uint _plaintextLength; - public ProtectedMemoryBlob(ArraySegment plaintext) + /// + /// Creates a new Secret from the provided input value, where the input value + /// is specified as an array segment. + /// + public Secret(ArraySegment value) { - plaintext.Validate(); + value.Validate(); - _localAllocHandle = Protect(plaintext); - _plaintextLength = (uint)plaintext.Count; + _localAllocHandle = Protect(value); + _plaintextLength = (uint)value.Count; } - public ProtectedMemoryBlob(byte[] plaintext) - : this(new ArraySegment(plaintext)) + /// + /// Creates a new Secret from the provided input value, where the input value + /// is specified as an array. + /// + public Secret(byte[] value) + : this(new ArraySegment(value)) { } - public ProtectedMemoryBlob(byte* plaintext, int plaintextLength) + /// + /// Creates a new Secret from the provided input value, where the input value + /// is specified as a pointer to unmanaged memory. + /// + public Secret(byte* secret, int secretLength) { - if (plaintext == null) + if (secret == null) { - throw new ArgumentNullException("plaintext"); + throw new ArgumentNullException("secret"); } - if (plaintextLength < 0) + if (secretLength < 0) { - throw new ArgumentOutOfRangeException("plaintextLength"); + throw new ArgumentOutOfRangeException("secretLength"); } - _localAllocHandle = Protect(plaintext, (uint)plaintextLength); - _plaintextLength = (uint)plaintextLength; + _localAllocHandle = Protect(secret, (uint)secretLength); + _plaintextLength = (uint)secretLength; } - public ProtectedMemoryBlob(ISecret secret) + /// + /// Creates a new Secret from another secret object. + /// + public Secret(ISecret secret) { if (secret == null) { throw new ArgumentNullException("secret"); } - ProtectedMemoryBlob other = secret as ProtectedMemoryBlob; + Secret other = secret as Secret; if (other != null) { // Fast-track: simple deep copy scenario. @@ -79,6 +97,9 @@ namespace Microsoft.AspNet.Security.DataProtection } } + /// + /// The length (in bytes) of the secret value. + /// public int Length { get @@ -87,6 +108,9 @@ namespace Microsoft.AspNet.Security.DataProtection } } + /// + /// Wipes the secret from memory. + /// public void Dispose() { _localAllocHandle.Dispose(); @@ -134,21 +158,25 @@ namespace Microsoft.AspNet.Security.DataProtection return encryptedMemoryHandle; } - public static ProtectedMemoryBlob Random(int numBytes) + /// + /// Returns a Secret comprised entirely of random bytes retrieved from + /// a cryptographically secure RNG. + /// + public static Secret Random(int numBytes) { CryptoUtil.Assert(numBytes >= 0, "numBytes >= 0"); if (numBytes == 0) { byte dummy; - return new ProtectedMemoryBlob(&dummy, 0); + return new Secret(&dummy, 0); } else { // Don't use CNG if we're not on Windows. if (!OSVersionUtil.IsBCryptOnWin7OrLaterAvailable()) { - return new ProtectedMemoryBlob(ManagedGenRandomImpl.Instance.GenRandom(numBytes)); + return new Secret(ManagedGenRandomImpl.Instance.GenRandom(numBytes)); } byte[] bytes = new byte[numBytes]; @@ -157,7 +185,7 @@ namespace Microsoft.AspNet.Security.DataProtection try { BCryptUtil.GenRandom(pbBytes, (uint)numBytes); - return new ProtectedMemoryBlob(pbBytes, numBytes); + return new Secret(pbBytes, numBytes); } finally { @@ -196,6 +224,12 @@ namespace Microsoft.AspNet.Security.DataProtection } } + /// + /// Writes the secret value to the specified buffer. + /// + /// + /// The buffer size must exactly match the length of the secret value. + /// public void WriteSecretIntoBuffer(ArraySegment buffer) { // Parameter checking @@ -215,6 +249,12 @@ namespace Microsoft.AspNet.Security.DataProtection } } + /// + /// Writes the secret value to the specified buffer. + /// + /// + /// The 'bufferLength' parameter must exactly match the length of the secret value. + /// public void WriteSecretIntoBuffer(byte* buffer, int bufferLength) { if (buffer == null) diff --git a/src/Microsoft.AspNet.Security.DataProtection/TimeLimitedDataProtector.cs b/src/Microsoft.AspNet.Security.DataProtection/TimeLimitedDataProtector.cs index 09bab47aa8..bf42b34c45 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/TimeLimitedDataProtector.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/TimeLimitedDataProtector.cs @@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Security.DataProtection expiration = new DateTimeOffset((long)utcTicksExpiration, TimeSpan.Zero); return retVal; } - catch (Exception ex) when (!(ex is CryptographicException)) + catch (Exception ex) when (ex.RequiresHomogenization()) { // Homogenize all failures to CryptographicException throw Error.CryptCommon_GenericError(ex); diff --git a/src/Microsoft.AspNet.Security.DataProtection/XmlEncryption/DpapiNGXmlEncryptor.cs b/src/Microsoft.AspNet.Security.DataProtection/XmlEncryption/DpapiNGXmlEncryptor.cs index b6930aa488..25526f61dd 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/XmlEncryption/DpapiNGXmlEncryptor.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/XmlEncryption/DpapiNGXmlEncryptor.cs @@ -46,20 +46,19 @@ namespace Microsoft.AspNet.Security.DataProtection.XmlEncryption public XElement Encrypt([NotNull] XElement plaintextElement) { // First, convert the XML element to a byte[] so that it can be encrypted. - ProtectedMemoryBlob secret; + Secret secret; using (var memoryStream = new MemoryStream()) { plaintextElement.Save(memoryStream); - #if !ASPNETCORE50 // If we're on full desktop CLR, utilize the underlying buffer directly as an optimization. byte[] underlyingBuffer = memoryStream.GetBuffer(); - secret = new ProtectedMemoryBlob(new ArraySegment(underlyingBuffer, 0, checked((int)memoryStream.Length))); + secret = new Secret(new ArraySegment(underlyingBuffer, 0, checked((int)memoryStream.Length))); Array.Clear(underlyingBuffer, 0, underlyingBuffer.Length); #else // Otherwise, need to make a copy of the buffer. byte[] clonedBuffer = memoryStream.ToArray(); - secret = new ProtectedMemoryBlob(clonedBuffer); + secret = new Secret(clonedBuffer); Array.Clear(clonedBuffer, 0, clonedBuffer.Length); #endif } diff --git a/src/Microsoft.AspNet.Security.DataProtection/XmlEncryption/DpapiXmlEncryptor.cs b/src/Microsoft.AspNet.Security.DataProtection/XmlEncryption/DpapiXmlEncryptor.cs index 6f33ed7ebf..553cda733e 100644 --- a/src/Microsoft.AspNet.Security.DataProtection/XmlEncryption/DpapiXmlEncryptor.cs +++ b/src/Microsoft.AspNet.Security.DataProtection/XmlEncryption/DpapiXmlEncryptor.cs @@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Security.DataProtection.XmlEncryption public XElement Encrypt([NotNull] XElement plaintextElement) { // First, convert the XML element to a byte[] so that it can be encrypted. - ProtectedMemoryBlob secret; + Secret secret; using (var memoryStream = new MemoryStream()) { plaintextElement.Save(memoryStream); @@ -39,12 +39,12 @@ namespace Microsoft.AspNet.Security.DataProtection.XmlEncryption #if !ASPNETCORE50 // If we're on full desktop CLR, utilize the underlying buffer directly as an optimization. byte[] underlyingBuffer = memoryStream.GetBuffer(); - secret = new ProtectedMemoryBlob(new ArraySegment(underlyingBuffer, 0, checked((int)memoryStream.Length))); + secret = new Secret(new ArraySegment(underlyingBuffer, 0, checked((int)memoryStream.Length))); Array.Clear(underlyingBuffer, 0, underlyingBuffer.Length); #else // Otherwise, need to make a copy of the buffer. byte[] clonedBuffer = memoryStream.ToArray(); - secret = new ProtectedMemoryBlob(clonedBuffer); + secret = new Secret(clonedBuffer); Array.Clear(clonedBuffer, 0, clonedBuffer.Length); #endif } diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs index c7c1acee95..34fa81a08c 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/CbcAuthenticatedEncryptorTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng public void Encrypt_Decrypt_RoundTrips() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(new byte[512 / 8]); + Secret kdk = new Secret(new byte[512 / 8]); CbcAuthenticatedEncryptor encryptor = new CbcAuthenticatedEncryptor(kdk, symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_CBC, symmetricAlgorithmKeySizeInBytes: 256 / 8, @@ -39,7 +39,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng public void Encrypt_Decrypt_Tampering_Fails() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(new byte[512 / 8]); + Secret kdk = new Secret(new byte[512 / 8]); CbcAuthenticatedEncryptor encryptor = new CbcAuthenticatedEncryptor(kdk, symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_CBC, symmetricAlgorithmKeySizeInBytes: 256 / 8, @@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng public void Encrypt_KnownKey() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(Encoding.UTF8.GetBytes("master key")); + Secret kdk = new Secret(Encoding.UTF8.GetBytes("master key")); CbcAuthenticatedEncryptor encryptor = new CbcAuthenticatedEncryptor(kdk, symmetricAlgorithmHandle: CachedAlgorithmHandles.AES_CBC, symmetricAlgorithmKeySizeInBytes: 256 / 8, diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs index 681de03f38..fb73ec6c61 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/Cng/GcmAuthenticatedEncryptorTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng public void Encrypt_Decrypt_RoundTrips() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(new byte[512 / 8]); + Secret kdk = new Secret(new byte[512 / 8]); GcmAuthenticatedEncryptor encryptor = new GcmAuthenticatedEncryptor(kdk, CachedAlgorithmHandles.AES_GCM, symmetricAlgorithmKeySizeInBytes: 256 / 8); ArraySegment plaintext = new ArraySegment(Encoding.UTF8.GetBytes("plaintext")); ArraySegment aad = new ArraySegment(Encoding.UTF8.GetBytes("aad")); @@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng public void Encrypt_Decrypt_Tampering_Fails() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(new byte[512 / 8]); + Secret kdk = new Secret(new byte[512 / 8]); GcmAuthenticatedEncryptor encryptor = new GcmAuthenticatedEncryptor(kdk, CachedAlgorithmHandles.AES_GCM, symmetricAlgorithmKeySizeInBytes: 256 / 8); ArraySegment plaintext = new ArraySegment(Encoding.UTF8.GetBytes("plaintext")); ArraySegment aad = new ArraySegment(Encoding.UTF8.GetBytes("aad")); @@ -80,7 +80,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Cng public void Encrypt_KnownKey() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(Encoding.UTF8.GetBytes("master key")); + Secret kdk = new Secret(Encoding.UTF8.GetBytes("master key")); GcmAuthenticatedEncryptor encryptor = new GcmAuthenticatedEncryptor(kdk, CachedAlgorithmHandles.AES_GCM, symmetricAlgorithmKeySizeInBytes: 128 / 8, genRandom: new SequentialGenRandom()); ArraySegment plaintext = new ArraySegment(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, 2, 3); ArraySegment aad = new ArraySegment(new byte[] { 7, 6, 5, 4, 3, 2, 1, 0 }, 1, 4); diff --git a/test/Microsoft.AspNet.Security.DataProtection.Test/Managed/ManagedAuthenticatedEncryptorTests.cs b/test/Microsoft.AspNet.Security.DataProtection.Test/Managed/ManagedAuthenticatedEncryptorTests.cs index bed597f852..345bb439f4 100644 --- a/test/Microsoft.AspNet.Security.DataProtection.Test/Managed/ManagedAuthenticatedEncryptorTests.cs +++ b/test/Microsoft.AspNet.Security.DataProtection.Test/Managed/ManagedAuthenticatedEncryptorTests.cs @@ -16,7 +16,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Managed public void Encrypt_Decrypt_RoundTrips() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(new byte[512 / 8]); + Secret kdk = new Secret(new byte[512 / 8]); ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk, symmetricAlgorithmFactory: Aes.Create, symmetricAlgorithmKeySizeInBytes: 256 / 8, @@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Managed public void Encrypt_Decrypt_Tampering_Fails() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(new byte[512 / 8]); + Secret kdk = new Secret(new byte[512 / 8]); ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk, symmetricAlgorithmFactory: Aes.Create, symmetricAlgorithmKeySizeInBytes: 256 / 8, @@ -82,7 +82,7 @@ namespace Microsoft.AspNet.Security.DataProtection.Test.Managed public void Encrypt_KnownKey() { // Arrange - ProtectedMemoryBlob kdk = new ProtectedMemoryBlob(Encoding.UTF8.GetBytes("master key")); + Secret kdk = new Secret(Encoding.UTF8.GetBytes("master key")); ManagedAuthenticatedEncryptor encryptor = new ManagedAuthenticatedEncryptor(kdk, symmetricAlgorithmFactory: Aes.Create, symmetricAlgorithmKeySizeInBytes: 256 / 8,