Merge branch 'ajbaaska/service-desc-cleanup' into dev

This commit is contained in:
Ajay Bhargav Baaskaran 2016-08-02 19:22:38 -07:00
commit eb17453322
35 changed files with 166 additions and 201 deletions

View File

@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.DataProtection
return arraySegment.Array; return arraySegment.Array;
} }
byte[] retVal = new byte[arraySegment.Count]; var retVal = new byte[arraySegment.Count];
Buffer.BlockCopy(arraySegment.Array, arraySegment.Offset, retVal, 0, retVal.Length); Buffer.BlockCopy(arraySegment.Array, arraySegment.Offset, retVal, 0, retVal.Length);
return retVal; return retVal;
} }

View File

@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption
public static byte[] Encrypt(this IAuthenticatedEncryptor encryptor, ArraySegment<byte> plaintext, ArraySegment<byte> additionalAuthenticatedData, uint preBufferSize, uint postBufferSize) public static byte[] Encrypt(this IAuthenticatedEncryptor encryptor, ArraySegment<byte> plaintext, ArraySegment<byte> additionalAuthenticatedData, uint preBufferSize, uint postBufferSize)
{ {
// Can we call the optimized version? // Can we call the optimized version?
IOptimizedAuthenticatedEncryptor optimizedEncryptor = encryptor as IOptimizedAuthenticatedEncryptor; var optimizedEncryptor = encryptor as IOptimizedAuthenticatedEncryptor;
if (optimizedEncryptor != null) if (optimizedEncryptor != null)
{ {
return optimizedEncryptor.Encrypt(plaintext, additionalAuthenticatedData, preBufferSize, postBufferSize); return optimizedEncryptor.Encrypt(plaintext, additionalAuthenticatedData, preBufferSize, postBufferSize);
@ -25,8 +25,8 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption
} }
else else
{ {
byte[] temp = encryptor.Encrypt(plaintext, additionalAuthenticatedData); var temp = encryptor.Encrypt(plaintext, additionalAuthenticatedData);
byte[] retVal = new byte[checked(preBufferSize + temp.Length + postBufferSize)]; var retVal = new byte[checked(preBufferSize + temp.Length + postBufferSize)];
Buffer.BlockCopy(temp, 0, retVal, checked((int)preBufferSize), temp.Length); Buffer.BlockCopy(temp, 0, retVal, checked((int)preBufferSize), temp.Length);
return retVal; return retVal;
} }
@ -39,13 +39,13 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption
public static void PerformSelfTest(this IAuthenticatedEncryptor encryptor) public static void PerformSelfTest(this IAuthenticatedEncryptor encryptor)
{ {
// Arrange // Arrange
Guid plaintextAsGuid = Guid.NewGuid(); var plaintextAsGuid = Guid.NewGuid();
byte[] plaintextAsBytes = plaintextAsGuid.ToByteArray(); var plaintextAsBytes = plaintextAsGuid.ToByteArray();
byte[] aad = Guid.NewGuid().ToByteArray(); var aad = Guid.NewGuid().ToByteArray();
// Act // Act
byte[] protectedData = encryptor.Encrypt(new ArraySegment<byte>(plaintextAsBytes), new ArraySegment<byte>(aad)); var protectedData = encryptor.Encrypt(new ArraySegment<byte>(plaintextAsBytes), new ArraySegment<byte>(aad));
byte[] roundTrippedData = encryptor.Decrypt(new ArraySegment<byte>(protectedData), new ArraySegment<byte>(aad)); var roundTrippedData = encryptor.Decrypt(new ArraySegment<byte>(protectedData), new ArraySegment<byte>(aad));
// Assert // Assert
CryptoUtil.Assert(roundTrippedData != null && roundTrippedData.Length == plaintextAsBytes.Length && plaintextAsGuid == new Guid(roundTrippedData), CryptoUtil.Assert(roundTrippedData != null && roundTrippedData.Length == plaintextAsBytes.Length && plaintextAsGuid == new Guid(roundTrippedData),

View File

@ -129,7 +129,7 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption
} }
// Make sure we're using a hash algorithm. We require a minimum 128-bit digest. // Make sure we're using a hash algorithm. We require a minimum 128-bit digest.
uint digestSize = algorithmHandle.GetHashDigestLength(); var digestSize = algorithmHandle.GetHashDigestLength();
AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked(digestSize * 8)); AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked(digestSize * 8));
// all good! // all good!

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat
} }
} }
XElement masterKeyElement = new XElement("masterKey", var masterKeyElement = new XElement("masterKey",
new XComment(" Warning: the key below is in an unencrypted form. "), new XComment(" Warning: the key below is in an unencrypted form. "),
new XElement("value", unprotectedSecretAsBase64String)); new XElement("value", unprotectedSecretAsBase64String));
masterKeyElement.MarkAsRequiresEncryption(); masterKeyElement.MarkAsRequiresEncryption();

View File

@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
private byte[] CreateContextHeader() private byte[] CreateContextHeader()
{ {
byte[] retVal = new byte[checked( var retVal = new byte[checked(
1 /* KDF alg */ 1 /* KDF alg */
+ 1 /* chaining mode */ + 1 /* chaining mode */
+ sizeof(uint) /* sym alg key size */ + sizeof(uint) /* sym alg key size */
@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
BitHelpers.WriteTo(ref ptr, _hmacAlgorithmDigestLengthInBytes); BitHelpers.WriteTo(ref ptr, _hmacAlgorithmDigestLengthInBytes);
// See the design document for an explanation of the following code. // See the design document for an explanation of the following code.
byte[] tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes]; var tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes];
fixed (byte* pbTempKeys = tempKeys) fixed (byte* pbTempKeys = tempKeys)
{ {
byte dummy; byte dummy;
@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// Assumption: pbCipherText := { keyModifier | IV | encryptedData | MAC(IV | encryptedPayload) } // Assumption: pbCipherText := { keyModifier | IV | encryptedData | MAC(IV | encryptedPayload) }
uint cbEncryptedData = checked(cbCiphertext - (KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + _hmacAlgorithmDigestLengthInBytes)); var cbEncryptedData = checked(cbCiphertext - (KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + _hmacAlgorithmDigestLengthInBytes));
// Calculate offsets // Calculate offsets
byte* pbKeyModifier = pbCiphertext; byte* pbKeyModifier = pbCiphertext;
@ -161,7 +161,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// Use the KDF to recreate the symmetric encryption and HMAC subkeys // Use the KDF to recreate the symmetric encryption and HMAC subkeys
// We'll need a temporary buffer to hold them // We'll need a temporary buffer to hold them
uint cbTempSubkeys = checked(_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes); var cbTempSubkeys = checked(_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes);
byte* pbTempSubkeys = stackalloc byte[checked((int)cbTempSubkeys)]; byte* pbTempSubkeys = stackalloc byte[checked((int)cbTempSubkeys)];
try try
{ {
@ -224,7 +224,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// assume PKCS#7). So unfortunately we're stuck with the temporary buffer. // assume PKCS#7). So unfortunately we're stuck with the temporary buffer.
// (Querying the output size won't mutate the IV.) // (Querying the output size won't mutate the IV.)
uint dwEstimatedDecryptedByteCount; uint dwEstimatedDecryptedByteCount;
int ntstatus = UnsafeNativeMethods.BCryptDecrypt( var ntstatus = UnsafeNativeMethods.BCryptDecrypt(
hKey: symmetricKeyHandle, hKey: symmetricKeyHandle,
pbInput: pbInput, pbInput: pbInput,
cbInput: cbInput, cbInput: cbInput,
@ -237,7 +237,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING); dwFlags: BCryptEncryptFlags.BCRYPT_BLOCK_PADDING);
UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus); UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);
byte[] decryptedPayload = new byte[dwEstimatedDecryptedByteCount]; var decryptedPayload = new byte[dwEstimatedDecryptedByteCount];
uint dwActualDecryptedByteCount; uint dwActualDecryptedByteCount;
fixed (byte* pbDecryptedPayload = decryptedPayload) fixed (byte* pbDecryptedPayload = decryptedPayload)
{ {
@ -268,7 +268,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
else else
{ {
// payload takes up only a partial buffer // payload takes up only a partial buffer
byte[] resizedDecryptedPayload = new byte[dwActualDecryptedByteCount]; var resizedDecryptedPayload = new byte[dwActualDecryptedByteCount];
Buffer.BlockCopy(decryptedPayload, 0, resizedDecryptedPayload, 0, resizedDecryptedPayload.Length); Buffer.BlockCopy(decryptedPayload, 0, resizedDecryptedPayload, 0, resizedDecryptedPayload.Length);
return resizedDecryptedPayload; return resizedDecryptedPayload;
} }
@ -282,7 +282,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
UnsafeBufferUtil.BlockCopy(from: pbIV, to: pbClonedIV, byteCount: _symmetricAlgorithmBlockSizeInBytes); UnsafeBufferUtil.BlockCopy(from: pbIV, to: pbClonedIV, byteCount: _symmetricAlgorithmBlockSizeInBytes);
uint dwEncryptedBytes; uint dwEncryptedBytes;
int ntstatus = UnsafeNativeMethods.BCryptEncrypt( var ntstatus = UnsafeNativeMethods.BCryptEncrypt(
hKey: symmetricKeyHandle, hKey: symmetricKeyHandle,
pbInput: pbInput, pbInput: pbInput,
cbInput: cbInput, cbInput: cbInput,
@ -303,13 +303,13 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
{ {
// This buffer will be used to hold the symmetric encryption and HMAC subkeys // This buffer will be used to hold the symmetric encryption and HMAC subkeys
// used in the generation of this payload. // used in the generation of this payload.
uint cbTempSubkeys = checked(_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes); var cbTempSubkeys = checked(_symmetricAlgorithmSubkeyLengthInBytes + _hmacAlgorithmSubkeyLengthInBytes);
byte* pbTempSubkeys = stackalloc byte[checked((int)cbTempSubkeys)]; byte* pbTempSubkeys = stackalloc byte[checked((int)cbTempSubkeys)];
try try
{ {
// Randomly generate the key modifier and IV. // Randomly generate the key modifier and IV.
uint cbKeyModifierAndIV = checked(KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes); var cbKeyModifierAndIV = checked(KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes);
byte* pbKeyModifierAndIV = stackalloc byte[checked((int)cbKeyModifierAndIV)]; byte* pbKeyModifierAndIV = stackalloc byte[checked((int)cbKeyModifierAndIV)];
_genRandom.GenRandom(pbKeyModifierAndIV, cbKeyModifierAndIV); _genRandom.GenRandom(pbKeyModifierAndIV, cbKeyModifierAndIV);
@ -335,10 +335,10 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
{ {
// We can't assume PKCS#7 padding (maybe the underlying provider is really 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. // so we need to query the padded output size before we can allocate the return value array.
uint cbOutputCiphertext = GetCbcEncryptedOutputSizeWithPadding(symmetricKeyHandle, pbPlaintext, cbPlaintext); var cbOutputCiphertext = GetCbcEncryptedOutputSizeWithPadding(symmetricKeyHandle, pbPlaintext, cbPlaintext);
// Allocate return value array and start copying some data // Allocate return value array and start copying some data
byte[] retVal = new byte[checked(cbPreBuffer + KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + cbOutputCiphertext + _hmacAlgorithmDigestLengthInBytes + cbPostBuffer)]; var retVal = new byte[checked(cbPreBuffer + KEY_MODIFIER_SIZE_IN_BYTES + _symmetricAlgorithmBlockSizeInBytes + cbOutputCiphertext + _hmacAlgorithmDigestLengthInBytes + cbPostBuffer)];
fixed (byte* pbRetVal = retVal) fixed (byte* pbRetVal = retVal)
{ {
// Calculate offsets // Calculate offsets
@ -395,7 +395,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// Calling BCryptEncrypt with a null output pointer will cause it to return the total number // Calling BCryptEncrypt with a null output pointer will cause it to return the total number
// of bytes required for the output buffer. // of bytes required for the output buffer.
uint dwResult; uint dwResult;
int ntstatus = UnsafeNativeMethods.BCryptEncrypt( var ntstatus = UnsafeNativeMethods.BCryptEncrypt(
hKey: symmetricKeyHandle, hKey: symmetricKeyHandle,
pbInput: pbInput, pbInput: pbInput,
cbInput: cbInput, cbInput: cbInput,

View File

@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
{ {
Debug.Assert(secret != null); Debug.Assert(secret != null);
byte[] plaintextSecret = new byte[secret.Length]; var plaintextSecret = new byte[secret.Length];
fixed (byte* pbPlaintextSecret = plaintextSecret) fixed (byte* pbPlaintextSecret = plaintextSecret)
{ {
try try
@ -66,24 +66,24 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
{ {
byte dummy; // provides a valid memory address if the secret or entropy has zero length byte dummy; // provides a valid memory address if the secret or entropy has zero length
DATA_BLOB dataIn = new DATA_BLOB() var dataIn = new DATA_BLOB()
{ {
cbData = cbSecret, cbData = cbSecret,
pbData = (pbSecret != null) ? pbSecret : &dummy pbData = (pbSecret != null) ? pbSecret : &dummy
}; };
DATA_BLOB entropy = new DATA_BLOB() var entropy = new DATA_BLOB()
{ {
cbData = cbOptionalEntropy, cbData = cbOptionalEntropy,
pbData = (pbOptionalEntropy != null) ? pbOptionalEntropy : &dummy pbData = (pbOptionalEntropy != null) ? pbOptionalEntropy : &dummy
}; };
DATA_BLOB dataOut = default(DATA_BLOB); var dataOut = default(DATA_BLOB);
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
#endif #endif
try try
{ {
bool success = UnsafeNativeMethods.CryptProtectData( var success = UnsafeNativeMethods.CryptProtectData(
pDataIn: &dataIn, pDataIn: &dataIn,
szDataDescr: IntPtr.Zero, szDataDescr: IntPtr.Zero,
pOptionalEntropy: &entropy, pOptionalEntropy: &entropy,
@ -93,12 +93,12 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
pDataOut: out dataOut); pDataOut: out dataOut);
if (!success) if (!success)
{ {
int errorCode = Marshal.GetLastWin32Error(); var errorCode = Marshal.GetLastWin32Error();
throw new CryptographicException(errorCode); throw new CryptographicException(errorCode);
} }
int dataLength = checked((int)dataOut.cbData); var dataLength = checked((int)dataOut.cbData);
byte[] retVal = new byte[dataLength]; var retVal = new byte[dataLength];
Marshal.Copy((IntPtr)dataOut.pbData, retVal, 0, dataLength); Marshal.Copy((IntPtr)dataOut.pbData, retVal, 0, dataLength);
return retVal; return retVal;
} }
@ -118,7 +118,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
Debug.Assert(secret != null); Debug.Assert(secret != null);
Debug.Assert(protectionDescriptorHandle != null); Debug.Assert(protectionDescriptorHandle != null);
byte[] plaintextSecret = new byte[secret.Length]; var plaintextSecret = new byte[secret.Length];
fixed (byte* pbPlaintextSecret = plaintextSecret) fixed (byte* pbPlaintextSecret = plaintextSecret)
{ {
try try
@ -147,7 +147,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// Perform the encryption operation, putting the protected data into LocalAlloc-allocated memory. // Perform the encryption operation, putting the protected data into LocalAlloc-allocated memory.
LocalAllocHandle protectedData; LocalAllocHandle protectedData;
uint cbProtectedData; uint cbProtectedData;
int ntstatus = UnsafeNativeMethods.NCryptProtectSecret( var ntstatus = UnsafeNativeMethods.NCryptProtectSecret(
hDescriptor: protectionDescriptorHandle, hDescriptor: protectionDescriptorHandle,
dwFlags: NCRYPT_SILENT_FLAG, dwFlags: NCRYPT_SILENT_FLAG,
pbData: pbData, pbData: pbData,
@ -162,12 +162,12 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// Copy the data from LocalAlloc-allocated memory into a managed memory buffer. // Copy the data from LocalAlloc-allocated memory into a managed memory buffer.
using (protectedData) using (protectedData)
{ {
byte[] retVal = new byte[cbProtectedData]; var retVal = new byte[cbProtectedData];
if (cbProtectedData > 0) if (cbProtectedData > 0)
{ {
fixed (byte* pbRetVal = retVal) fixed (byte* pbRetVal = retVal)
{ {
bool handleAcquired = false; var handleAcquired = false;
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
#endif #endif
@ -206,24 +206,24 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
{ {
byte dummy; // provides a valid memory address if the secret or entropy has zero length byte dummy; // provides a valid memory address if the secret or entropy has zero length
DATA_BLOB dataIn = new DATA_BLOB() var dataIn = new DATA_BLOB()
{ {
cbData = cbProtectedData, cbData = cbProtectedData,
pbData = (pbProtectedData != null) ? pbProtectedData : &dummy pbData = (pbProtectedData != null) ? pbProtectedData : &dummy
}; };
DATA_BLOB entropy = new DATA_BLOB() var entropy = new DATA_BLOB()
{ {
cbData = cbOptionalEntropy, cbData = cbOptionalEntropy,
pbData = (pbOptionalEntropy != null) ? pbOptionalEntropy : &dummy pbData = (pbOptionalEntropy != null) ? pbOptionalEntropy : &dummy
}; };
DATA_BLOB dataOut = default(DATA_BLOB); var dataOut = default(DATA_BLOB);
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
#endif #endif
try try
{ {
bool success = UnsafeNativeMethods.CryptUnprotectData( var success = UnsafeNativeMethods.CryptUnprotectData(
pDataIn: &dataIn, pDataIn: &dataIn,
ppszDataDescr: IntPtr.Zero, ppszDataDescr: IntPtr.Zero,
pOptionalEntropy: &entropy, pOptionalEntropy: &entropy,
@ -233,7 +233,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
pDataOut: out dataOut); pDataOut: out dataOut);
if (!success) if (!success)
{ {
int errorCode = Marshal.GetLastWin32Error(); var errorCode = Marshal.GetLastWin32Error();
throw new CryptographicException(errorCode); throw new CryptographicException(errorCode);
} }
@ -271,7 +271,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// First, decrypt the payload into LocalAlloc-allocated memory. // First, decrypt the payload into LocalAlloc-allocated memory.
LocalAllocHandle unencryptedPayloadHandle; LocalAllocHandle unencryptedPayloadHandle;
uint cbUnencryptedPayload; uint cbUnencryptedPayload;
int ntstatus = UnsafeNativeMethods.NCryptUnprotectSecret( var ntstatus = UnsafeNativeMethods.NCryptUnprotectSecret(
phDescriptor: IntPtr.Zero, phDescriptor: IntPtr.Zero,
dwFlags: NCRYPT_SILENT_FLAG, dwFlags: NCRYPT_SILENT_FLAG,
pbProtectedBlob: pbData, pbProtectedBlob: pbData,
@ -290,7 +290,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// the window is extremely small and AppDomain unloads should not happen here in practice. // the window is extremely small and AppDomain unloads should not happen here in practice.
using (unencryptedPayloadHandle) using (unencryptedPayloadHandle)
{ {
bool handleAcquired = false; var handleAcquired = false;
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
#endif #endif
@ -331,7 +331,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
NCryptDescriptorHandle descriptorHandle; NCryptDescriptorHandle descriptorHandle;
LocalAllocHandle unprotectedDataHandle; LocalAllocHandle unprotectedDataHandle;
uint cbUnprotectedData; uint cbUnprotectedData;
int ntstatus = UnsafeNativeMethods.NCryptUnprotectSecret( var ntstatus = UnsafeNativeMethods.NCryptUnprotectSecret(
phDescriptor: out descriptorHandle, phDescriptor: out descriptorHandle,
dwFlags: NCRYPT_UNPROTECT_NO_DECRYPT, dwFlags: NCRYPT_UNPROTECT_NO_DECRYPT,
pbProtectedBlob: pbData, pbProtectedBlob: pbData,

View File

@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
private byte[] CreateContextHeader() private byte[] CreateContextHeader()
{ {
byte[] retVal = new byte[checked( var retVal = new byte[checked(
1 /* KDF alg */ 1 /* KDF alg */
+ 1 /* chaining mode */ + 1 /* chaining mode */
+ sizeof(uint) /* sym alg key size */ + sizeof(uint) /* sym alg key size */
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
BitHelpers.WriteTo(ref ptr, TAG_SIZE_IN_BYTES); BitHelpers.WriteTo(ref ptr, TAG_SIZE_IN_BYTES);
// See the design document for an explanation of the following code. // See the design document for an explanation of the following code.
byte[] tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes]; var tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes];
fixed (byte* pbTempKeys = tempKeys) fixed (byte* pbTempKeys = tempKeys)
{ {
byte dummy; byte dummy;
@ -125,9 +125,9 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// Assumption: pbCipherText := { keyModifier || nonce || encryptedData || authenticationTag } // Assumption: pbCipherText := { keyModifier || nonce || encryptedData || authenticationTag }
uint cbPlaintext = checked(cbCiphertext - (KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES)); var cbPlaintext = checked(cbCiphertext - (KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + TAG_SIZE_IN_BYTES));
byte[] retVal = new byte[cbPlaintext]; var retVal = new byte[cbPlaintext];
fixed (byte* pbRetVal = retVal) fixed (byte* pbRetVal = retVal)
{ {
// Calculate offsets // Calculate offsets
@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
// The call to BCryptDecrypt will also validate the authentication tag // The call to BCryptDecrypt will also validate the authentication tag
uint cbDecryptedBytesWritten; uint cbDecryptedBytesWritten;
int ntstatus = UnsafeNativeMethods.BCryptDecrypt( var ntstatus = UnsafeNativeMethods.BCryptDecrypt(
hKey: decryptionSubkeyHandle, hKey: decryptionSubkeyHandle,
pbInput: pbEncryptedData, pbInput: pbEncryptedData,
cbInput: cbPlaintext, cbInput: cbPlaintext,
@ -216,7 +216,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
using (var keyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbKey, cbKey)) using (var keyHandle = _symmetricAlgorithmHandle.GenerateSymmetricKey(pbKey, cbKey))
{ {
uint cbResult; uint cbResult;
int ntstatus = UnsafeNativeMethods.BCryptEncrypt( var ntstatus = UnsafeNativeMethods.BCryptEncrypt(
hKey: keyHandle, hKey: keyHandle,
pbInput: pbPlaintextData, pbInput: pbPlaintextData,
cbInput: cbPlaintextData, cbInput: cbPlaintextData,
@ -236,7 +236,7 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
{ {
// Allocate a buffer to hold the key modifier, nonce, encrypted data, and tag. // Allocate a buffer to hold the key modifier, nonce, encrypted data, and tag.
// In GCM, the encrypted output will be the same length as the plaintext input. // In GCM, the encrypted output will be the same length as the plaintext input.
byte[] retVal = new byte[checked(cbPreBuffer + KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + cbPlaintext + TAG_SIZE_IN_BYTES + cbPostBuffer)]; var retVal = new byte[checked(cbPreBuffer + KEY_MODIFIER_SIZE_IN_BYTES + NONCE_SIZE_IN_BYTES + cbPlaintext + TAG_SIZE_IN_BYTES + cbPostBuffer)];
fixed (byte* pbRetVal = retVal) fixed (byte* pbRetVal = retVal)
{ {
// Calculate offsets // Calculate offsets

View File

@ -528,7 +528,7 @@ namespace Microsoft.AspNetCore.DataProtection
private static void RemoveAllServicesOfType(IServiceCollection services, Type serviceType) private static void RemoveAllServicesOfType(IServiceCollection services, Type serviceType)
{ {
// We go backward since we're modifying the collection in-place. // We go backward since we're modifying the collection in-place.
for (int i = services.Count - 1; i >= 0; i--) for (var i = services.Count - 1; i >= 0; i--)
{ {
if (services[i]?.ServiceType == serviceType) if (services[i]?.ServiceType == serviceType)
{ {

View File

@ -24,20 +24,6 @@ namespace Microsoft.Extensions.DependencyInjection
/// </summary> /// </summary>
internal static class DataProtectionServiceDescriptors internal static class DataProtectionServiceDescriptors
{ {
/// <summary>
/// An <see cref="IConfigureOptions{DataProtectionOptions}"/> backed by the host-provided defaults.
/// </summary>
public static ServiceDescriptor ConfigureOptions_DataProtectionOptions()
{
return ServiceDescriptor.Transient<IConfigureOptions<DataProtectionOptions>>(services =>
{
return new ConfigureOptions<DataProtectionOptions>(options =>
{
options.ApplicationDiscriminator = services.GetApplicationUniqueIdentifier();
});
});
}
/// <summary> /// <summary>
/// An <see cref="IConfigureOptions{KeyManagementOptions}"/> where the key lifetime is specified explicitly. /// An <see cref="IConfigureOptions{KeyManagementOptions}"/> where the key lifetime is specified explicitly.
/// </summary> /// </summary>
@ -53,14 +39,6 @@ namespace Microsoft.Extensions.DependencyInjection
}); });
} }
/// <summary>
/// An <see cref="IAuthenticatedEncryptorConfiguration"/> backed by default algorithmic options.
/// </summary>
public static ServiceDescriptor IAuthenticatedEncryptorConfiguration_Default()
{
return IAuthenticatedEncryptorConfiguration_FromSettings(new AuthenticatedEncryptionSettings());
}
/// <summary> /// <summary>
/// An <see cref="IAuthenticatedEncryptorConfiguration"/> backed by an <see cref="IInternalAuthenticatedEncryptionSettings"/>. /// An <see cref="IAuthenticatedEncryptorConfiguration"/> backed by an <see cref="IInternalAuthenticatedEncryptionSettings"/>.
/// </summary> /// </summary>
@ -79,18 +57,6 @@ namespace Microsoft.Extensions.DependencyInjection
} }
#endif #endif
/// <summary>
/// An <see cref="IDataProtectionProvider"/> backed by the default keyring.
/// </summary>
public static ServiceDescriptor IDataProtectionProvider_Default()
{
return ServiceDescriptor.Singleton<IDataProtectionProvider>(
services => DataProtectionProviderFactory.GetProviderFromServices(
options: services.GetRequiredService<IOptions<DataProtectionOptions>>().Value,
services: services,
mustCreateImmediately: true /* this is the ultimate fallback */));
}
/// <summary> /// <summary>
/// An ephemeral <see cref="IDataProtectionProvider"/>. /// An ephemeral <see cref="IDataProtectionProvider"/>.
/// </summary> /// </summary>
@ -110,14 +76,6 @@ namespace Microsoft.Extensions.DependencyInjection
return ServiceDescriptor.Singleton<IKeyEscrowSink>(services => services.GetActivator().CreateInstance<IKeyEscrowSink>(implementationTypeName)); return ServiceDescriptor.Singleton<IKeyEscrowSink>(services => services.GetActivator().CreateInstance<IKeyEscrowSink>(implementationTypeName));
} }
/// <summary>
/// An <see cref="IKeyManager"/> backed by the default XML key manager.
/// </summary>
public static ServiceDescriptor IKeyManager_Default()
{
return ServiceDescriptor.Singleton<IKeyManager>(services => new XmlKeyManager(services));
}
#if !NETSTANDARD1_3 // [[ISSUE60]] Remove this #ifdef when Core CLR gets support for EncryptedXml #if !NETSTANDARD1_3 // [[ISSUE60]] Remove this #ifdef when Core CLR gets support for EncryptedXml
/// <summary> /// <summary>
@ -167,14 +125,6 @@ namespace Microsoft.Extensions.DependencyInjection
return ServiceDescriptor.Singleton<IXmlRepository>(services => new FileSystemXmlRepository(directory, services)); return ServiceDescriptor.Singleton<IXmlRepository>(services => new FileSystemXmlRepository(directory, services));
} }
/// <summary>
/// An <see cref="IXmlRepository"/> backed by volatile in-process memory.
/// </summary>
public static ServiceDescriptor IXmlRepository_InMemory()
{
return ServiceDescriptor.Singleton<IXmlRepository>(services => new EphemeralXmlRepository(services));
}
/// <summary> /// <summary>
/// An <see cref="IXmlRepository"/> backed by the Windows registry. /// An <see cref="IXmlRepository"/> backed by the Windows registry.
/// </summary> /// </summary>

View File

@ -5,12 +5,14 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Cryptography.Cng; using Microsoft.AspNetCore.Cryptography.Cng;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Microsoft.AspNetCore.DataProtection.Cng; using Microsoft.AspNetCore.DataProtection.Cng;
using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal; using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal;
using Microsoft.AspNetCore.DataProtection.Repositories; using Microsoft.AspNetCore.DataProtection.Repositories;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Win32; using Microsoft.Win32;
namespace Microsoft.Extensions.DependencyInjection namespace Microsoft.Extensions.DependencyInjection
@ -34,7 +36,7 @@ namespace Microsoft.Extensions.DependencyInjection
// we'll not use the fallback at all. // we'll not use the fallback at all.
yield return ServiceDescriptor.Singleton<IDefaultKeyServices>(services => yield return ServiceDescriptor.Singleton<IDefaultKeyServices>(services =>
{ {
ILogger log = services.GetLogger(typeof(DataProtectionServices)); var log = services.GetLogger(typeof(DataProtectionServices));
ServiceDescriptor keyEncryptorDescriptor = null; ServiceDescriptor keyEncryptorDescriptor = null;
ServiceDescriptor keyRepositoryDescriptor = null; ServiceDescriptor keyRepositoryDescriptor = null;
@ -92,7 +94,8 @@ namespace Microsoft.Extensions.DependencyInjection
{ {
// Final fallback - use an ephemeral repository since we don't know where else to go. // Final fallback - use an ephemeral repository since we don't know where else to go.
// This can only be used for development scenarios. // This can only be used for development scenarios.
keyRepositoryDescriptor = DataProtectionServiceDescriptors.IXmlRepository_InMemory(); keyRepositoryDescriptor = ServiceDescriptor.Singleton<IXmlRepository>(
s => new EphemeralXmlRepository(s));
log?.UsingEphemeralKeyRepository(); log?.UsingEphemeralKeyRepository();
} }
@ -106,8 +109,13 @@ namespace Microsoft.Extensions.DependencyInjection
}); });
// Provide root key management and data protection services // Provide root key management and data protection services
yield return DataProtectionServiceDescriptors.IKeyManager_Default(); yield return ServiceDescriptor.Singleton<IKeyManager>(services => new XmlKeyManager(services));
yield return DataProtectionServiceDescriptors.IDataProtectionProvider_Default();
yield return ServiceDescriptor.Singleton<IDataProtectionProvider>(
services => DataProtectionProviderFactory.GetProviderFromServices(
options: services.GetRequiredService<IOptions<DataProtectionOptions>>().Value,
services: services,
mustCreateImmediately: true /* this is the ultimate fallback */));
// Provide services required for XML encryption // Provide services required for XML encryption
#if !NETSTANDARD1_3 // [[ISSUE60]] Remove this #ifdef when Core CLR gets support for EncryptedXml #if !NETSTANDARD1_3 // [[ISSUE60]] Remove this #ifdef when Core CLR gets support for EncryptedXml
@ -115,10 +123,16 @@ namespace Microsoft.Extensions.DependencyInjection
#endif #endif
// Hook up the logic which allows populating default options // Hook up the logic which allows populating default options
yield return DataProtectionServiceDescriptors.ConfigureOptions_DataProtectionOptions(); yield return ServiceDescriptor.Transient<IConfigureOptions<DataProtectionOptions>>(services =>
{
return new ConfigureOptions<DataProtectionOptions>(options =>
{
options.ApplicationDiscriminator = services.GetApplicationUniqueIdentifier();
});
});
// Read and apply policy from the registry, overriding any other defaults. // Read and apply policy from the registry, overriding any other defaults.
bool encryptorConfigurationReadFromRegistry = false; var encryptorConfigurationReadFromRegistry = false;
if (OSVersionUtil.IsWindows()) if (OSVersionUtil.IsWindows())
{ {
foreach (var descriptor in RegistryPolicyResolver.ResolveDefaultPolicy()) foreach (var descriptor in RegistryPolicyResolver.ResolveDefaultPolicy())
@ -134,7 +148,8 @@ namespace Microsoft.Extensions.DependencyInjection
// Finally, provide a fallback encryptor configuration if one wasn't already specified. // Finally, provide a fallback encryptor configuration if one wasn't already specified.
if (!encryptorConfigurationReadFromRegistry) if (!encryptorConfigurationReadFromRegistry)
{ {
yield return DataProtectionServiceDescriptors.IAuthenticatedEncryptorConfiguration_Default(); yield return DataProtectionServiceDescriptors.IAuthenticatedEncryptorConfiguration_FromSettings(
new AuthenticatedEncryptionSettings());;
} }
} }
} }

View File

@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.DataProtection
{ {
public static InvalidOperationException CertificateXmlEncryptor_CertificateNotFound(string thumbprint) public static InvalidOperationException CertificateXmlEncryptor_CertificateNotFound(string thumbprint)
{ {
string message = Resources.FormatCertificateXmlEncryptor_CertificateNotFound(thumbprint); var message = Resources.FormatCertificateXmlEncryptor_CertificateNotFound(thumbprint);
return new InvalidOperationException(message); return new InvalidOperationException(message);
} }
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.DataProtection
public static ArgumentException Common_BufferIncorrectlySized(string parameterName, int actualSize, int expectedSize) public static ArgumentException Common_BufferIncorrectlySized(string parameterName, int actualSize, int expectedSize)
{ {
string message = Resources.FormatCommon_BufferIncorrectlySized(actualSize, expectedSize); var message = Resources.FormatCommon_BufferIncorrectlySized(actualSize, expectedSize);
return new ArgumentException(message, parameterName); return new ArgumentException(message, parameterName);
} }
@ -33,19 +33,19 @@ namespace Microsoft.AspNetCore.DataProtection
public static CryptographicException CryptCommon_PayloadInvalid() public static CryptographicException CryptCommon_PayloadInvalid()
{ {
string message = Resources.CryptCommon_PayloadInvalid; var message = Resources.CryptCommon_PayloadInvalid;
return new CryptographicException(message); return new CryptographicException(message);
} }
public static InvalidOperationException Common_PropertyCannotBeNullOrEmpty(string propertyName) public static InvalidOperationException Common_PropertyCannotBeNullOrEmpty(string propertyName)
{ {
string message = String.Format(CultureInfo.CurrentCulture, Resources.Common_PropertyCannotBeNullOrEmpty, propertyName); var message = String.Format(CultureInfo.CurrentCulture, Resources.Common_PropertyCannotBeNullOrEmpty, propertyName);
return new InvalidOperationException(message); return new InvalidOperationException(message);
} }
public static InvalidOperationException Common_PropertyMustBeNonNegative(string propertyName) public static InvalidOperationException Common_PropertyMustBeNonNegative(string propertyName)
{ {
string message = String.Format(CultureInfo.CurrentCulture, Resources.Common_PropertyMustBeNonNegative, propertyName); var message = String.Format(CultureInfo.CurrentCulture, Resources.Common_PropertyMustBeNonNegative, propertyName);
return new InvalidOperationException(message); return new InvalidOperationException(message);
} }
@ -56,13 +56,13 @@ namespace Microsoft.AspNetCore.DataProtection
public static CryptographicException Common_KeyNotFound(Guid id) public static CryptographicException Common_KeyNotFound(Guid id)
{ {
string message = String.Format(CultureInfo.CurrentCulture, Resources.Common_KeyNotFound, id); var message = String.Format(CultureInfo.CurrentCulture, Resources.Common_KeyNotFound, id);
return new CryptographicException(message); return new CryptographicException(message);
} }
public static CryptographicException Common_KeyRevoked(Guid id) public static CryptographicException Common_KeyRevoked(Guid id)
{ {
string message = String.Format(CultureInfo.CurrentCulture, Resources.Common_KeyRevoked, id); var message = String.Format(CultureInfo.CurrentCulture, Resources.Common_KeyRevoked, id);
return new CryptographicException(message); return new CryptographicException(message);
} }
@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.DataProtection
public static InvalidOperationException XmlKeyManager_DuplicateKey(Guid keyId) public static InvalidOperationException XmlKeyManager_DuplicateKey(Guid keyId)
{ {
string message = String.Format(CultureInfo.CurrentCulture, Resources.XmlKeyManager_DuplicateKey, keyId); var message = String.Format(CultureInfo.CurrentCulture, Resources.XmlKeyManager_DuplicateKey, keyId);
return new InvalidOperationException(message); return new InvalidOperationException(message);
} }
} }

View File

@ -127,7 +127,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
public DefaultKeyResolution ResolveDefaultKeyPolicy(DateTimeOffset now, IEnumerable<IKey> allKeys) public DefaultKeyResolution ResolveDefaultKeyPolicy(DateTimeOffset now, IEnumerable<IKey> allKeys)
{ {
DefaultKeyResolution retVal = default(DefaultKeyResolution); var retVal = default(DefaultKeyResolution);
retVal.DefaultKey = FindDefaultKey(now, allKeys, out retVal.FallbackKey, out retVal.ShouldGenerateNewKey); retVal.DefaultKey = FindDefaultKey(now, allKeys, out retVal.FallbackKey, out retVal.ShouldGenerateNewKey);
return retVal; return retVal;
} }

View File

@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement.Internal
/// </summary> /// </summary>
internal CacheableKeyRing WithTemporaryExtendedLifetime(DateTimeOffset now) internal CacheableKeyRing WithTemporaryExtendedLifetime(DateTimeOffset now)
{ {
TimeSpan extension = TimeSpan.FromMinutes(2); var extension = TimeSpan.FromMinutes(2);
return new CacheableKeyRing(CancellationToken.None, now + extension, KeyRing); return new CacheableKeyRing(CancellationToken.None, now + extension, KeyRing);
} }
} }

View File

@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
{ {
// simple double-check lock pattern // simple double-check lock pattern
// we can't use LazyInitializer<T> because we don't have a simple value factory // we can't use LazyInitializer<T> because we don't have a simple value factory
IAuthenticatedEncryptor encryptor = Volatile.Read(ref _encryptor); var encryptor = Volatile.Read(ref _encryptor);
if (encryptor == null) if (encryptor == null)
{ {
lock (this) lock (this)

View File

@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
{ {
if (originalPurposes != null && originalPurposes.Length > 0) if (originalPurposes != null && originalPurposes.Length > 0)
{ {
string[] newPurposes = new string[originalPurposes.Length + 1]; var newPurposes = new string[originalPurposes.Length + 1];
Array.Copy(originalPurposes, 0, newPurposes, 0, originalPurposes.Length); Array.Copy(originalPurposes, 0, newPurposes, 0, originalPurposes.Length);
newPurposes[originalPurposes.Length] = newPurpose; newPurposes[originalPurposes.Length] = newPurpose;
return newPurposes; return newPurposes;
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
} }
UnprotectStatus status; UnprotectStatus status;
byte[] retVal = UnprotectCore(protectedData, ignoreRevocationErrors, status: out status); var retVal = UnprotectCore(protectedData, ignoreRevocationErrors, status: out status);
requiresMigration = (status != UnprotectStatus.Ok); requiresMigration = (status != UnprotectStatus.Ok);
wasRevoked = (status == UnprotectStatus.DecryptionKeyWasRevoked); wasRevoked = (status == UnprotectStatus.DecryptionKeyWasRevoked);
return retVal; return retVal;
@ -117,10 +117,10 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
// We'll need to apply the default key id to the template if it hasn't already been applied. // We'll need to apply the default key id to the template if it hasn't already been applied.
// If the default key id has been updated since the last call to Protect, also write back the updated template. // If the default key id has been updated since the last call to Protect, also write back the updated template.
byte[] aad = _aadTemplate.GetAadForKey(defaultKeyId, isProtecting: true); var aad = _aadTemplate.GetAadForKey(defaultKeyId, isProtecting: true);
// We allocate a 20-byte pre-buffer so that we can inject the magic header and key id into the return value. // We allocate a 20-byte pre-buffer so that we can inject the magic header and key id into the return value.
byte[] retVal = defaultEncryptorInstance.Encrypt( var retVal = defaultEncryptorInstance.Encrypt(
plaintext: new ArraySegment<byte>(plaintext), plaintext: new ArraySegment<byte>(plaintext),
additionalAuthenticatedData: new ArraySegment<byte>(aad), additionalAuthenticatedData: new ArraySegment<byte>(aad),
preBufferSize: (uint)(sizeof(uint) + sizeof(Guid)), preBufferSize: (uint)(sizeof(uint) + sizeof(Guid)),
@ -324,7 +324,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
{ {
writer.WriteBigEndian(MAGIC_HEADER_V0); writer.WriteBigEndian(MAGIC_HEADER_V0);
Debug.Assert(ms.Position == sizeof(uint)); Debug.Assert(ms.Position == sizeof(uint));
long posPurposeCount = writer.Seek(sizeof(Guid), SeekOrigin.Current); // skip over where the key id will be stored; we'll fill it in later var posPurposeCount = writer.Seek(sizeof(Guid), SeekOrigin.Current); // skip over where the key id will be stored; we'll fill it in later
writer.Seek(sizeof(uint), SeekOrigin.Current); // skip over where the purposeCount will be stored; we'll fill it in later writer.Seek(sizeof(uint), SeekOrigin.Current); // skip over where the purposeCount will be stored; we'll fill it in later
uint purposeCount = 0; uint purposeCount = 0;
@ -347,7 +347,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
{ {
// Multiple threads might be trying to read and write the _aadTemplate field // Multiple threads might be trying to read and write the _aadTemplate field
// simultaneously. We need to make sure all accesses to it are thread-safe. // simultaneously. We need to make sure all accesses to it are thread-safe.
byte[] existingTemplate = Volatile.Read(ref _aadTemplate); var existingTemplate = Volatile.Read(ref _aadTemplate);
Debug.Assert(existingTemplate.Length >= sizeof(uint) /* MAGIC_HEADER */ + sizeof(Guid) /* keyId */); Debug.Assert(existingTemplate.Length >= sizeof(uint) /* MAGIC_HEADER */ + sizeof(Guid) /* keyId */);
// If the template is already initialized to this key id, return it. // If the template is already initialized to this key id, return it.

View File

@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
_logger?.UsingKeyAsDefaultKey(defaultKey.KeyId); _logger?.UsingKeyAsDefaultKey(defaultKey.KeyId);
DateTimeOffset nextAutoRefreshTime = now + GetRefreshPeriodWithJitter(_keyManagementOptions.KeyRingRefreshPeriod); var nextAutoRefreshTime = now + GetRefreshPeriodWithJitter(_keyManagementOptions.KeyRingRefreshPeriod);
// The cached keyring should expire at the earliest of (default key expiration, next auto-refresh time). // The cached keyring should expire at the earliest of (default key expiration, next auto-refresh time).
// Since the refresh period and safety window are not user-settable, we can guarantee that there's at // Since the refresh period and safety window are not user-settable, we can guarantee that there's at
@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
// update the keyring, and all other threads will continue to use the existing cached // update the keyring, and all other threads will continue to use the existing cached
// keyring while the first thread performs the update. There is an exception: if there // keyring while the first thread performs the update. There is an exception: if there
// is no usable existing cached keyring, all callers must block until the keyring exists. // is no usable existing cached keyring, all callers must block until the keyring exists.
bool acquiredLock = false; var acquiredLock = false;
try try
{ {
Monitor.TryEnter(_cacheableKeyRingLockObj, (existingCacheableKeyRing != null) ? 0 : Timeout.Infinite, ref acquiredLock); Monitor.TryEnter(_cacheableKeyRingLockObj, (existingCacheableKeyRing != null) ? 0 : Timeout.Infinite, ref acquiredLock);

View File

@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
{ {
// ProcessKeyElement can return null in the case of failure, and if this happens we'll move on. // ProcessKeyElement can return null in the case of failure, and if this happens we'll move on.
// Still need to throw if we see duplicate keys with the same id. // Still need to throw if we see duplicate keys with the same id.
KeyBase key = ProcessKeyElement(element); var key = ProcessKeyElement(element);
if (key != null) if (key != null)
{ {
if (keyIdToKeyMap.ContainsKey(key.KeyId)) if (keyIdToKeyMap.ContainsKey(key.KeyId))
@ -154,7 +154,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
} }
else if (element.Name == RevocationElementName) else if (element.Name == RevocationElementName)
{ {
object revocationInfo = ProcessRevocationElement(element); var revocationInfo = ProcessRevocationElement(element);
if (revocationInfo is Guid) if (revocationInfo is Guid)
{ {
// a single key was revoked // a single key was revoked
@ -276,7 +276,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
else else
{ {
// only one key is being revoked // only one key is being revoked
Guid keyId = XmlConvert.ToGuid(keyIdAsString); var keyId = XmlConvert.ToGuid(keyIdAsString);
_logger?.FoundRevocationOfKey(keyId); _logger?.FoundRevocationOfKey(keyId);
return keyId; return keyId;
} }
@ -397,7 +397,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
var possiblyEncryptedKeyElement = KeyEncryptor?.EncryptIfNecessary(keyElement) ?? keyElement; var possiblyEncryptedKeyElement = KeyEncryptor?.EncryptIfNecessary(keyElement) ?? keyElement;
// Persist it to the underlying repository and trigger the cancellation token. // Persist it to the underlying repository and trigger the cancellation token.
string friendlyName = Invariant($"key-{keyId:D}"); var friendlyName = Invariant($"key-{keyId:D}");
KeyRepository.StoreElement(possiblyEncryptedKeyElement, friendlyName); KeyRepository.StoreElement(possiblyEncryptedKeyElement, friendlyName);
TriggerAndResetCacheExpirationToken(); TriggerAndResetCacheExpirationToken();
@ -415,11 +415,11 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
try try
{ {
// Figure out who will be deserializing this // Figure out who will be deserializing this
XElement descriptorElement = keyElement.Element(DescriptorElementName); var descriptorElement = keyElement.Element(DescriptorElementName);
string descriptorDeserializerTypeName = (string)descriptorElement.Attribute(DeserializerTypeAttributeName); string descriptorDeserializerTypeName = (string)descriptorElement.Attribute(DeserializerTypeAttributeName);
// Decrypt the descriptor element and pass it to the descriptor for consumption // Decrypt the descriptor element and pass it to the descriptor for consumption
XElement unencryptedInputToDeserializer = descriptorElement.Elements().Single().DecryptElement(_activator); var unencryptedInputToDeserializer = descriptorElement.Elements().Single().DecryptElement(_activator);
var deserializerInstance = _activator.CreateInstance<IAuthenticatedEncryptorDescriptorDeserializer>(descriptorDeserializerTypeName); var deserializerInstance = _activator.CreateInstance<IAuthenticatedEncryptorDescriptorDeserializer>(descriptorDeserializerTypeName);
var descriptorInstance = deserializerInstance.ImportFromXml(unencryptedInputToDeserializer); var descriptorInstance = deserializerInstance.ImportFromXml(unencryptedInputToDeserializer);
@ -450,7 +450,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
new XElement(ReasonElementName, reason)); new XElement(ReasonElementName, reason));
// Persist it to the underlying repository and trigger the cancellation token // Persist it to the underlying repository and trigger the cancellation token
string friendlyName = Invariant($"revocation-{keyId:D}"); var friendlyName = Invariant($"revocation-{keyId:D}");
KeyRepository.StoreElement(revocationElement, friendlyName); KeyRepository.StoreElement(revocationElement, friendlyName);
TriggerAndResetCacheExpirationToken(); TriggerAndResetCacheExpirationToken();
} }

View File

@ -72,7 +72,7 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
var EMPTY_ARRAY = new byte[0]; var EMPTY_ARRAY = new byte[0];
var EMPTY_ARRAY_SEGMENT = new ArraySegment<byte>(EMPTY_ARRAY); var EMPTY_ARRAY_SEGMENT = new ArraySegment<byte>(EMPTY_ARRAY);
byte[] retVal = new byte[checked( var retVal = new byte[checked(
1 /* KDF alg */ 1 /* KDF alg */
+ 1 /* chaining mode */ + 1 /* chaining mode */
+ sizeof(uint) /* sym alg key size */ + sizeof(uint) /* sym alg key size */
@ -82,7 +82,7 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
+ _symmetricAlgorithmBlockSizeInBytes /* ciphertext of encrypted empty string */ + _symmetricAlgorithmBlockSizeInBytes /* ciphertext of encrypted empty string */
+ _validationAlgorithmDigestLengthInBytes /* digest of HMACed empty string */)]; + _validationAlgorithmDigestLengthInBytes /* digest of HMACed empty string */)];
int idx = 0; var idx = 0;
// First is the two-byte header // First is the two-byte header
retVal[idx++] = 0; // 0x00 = SP800-108 CTR KDF w/ HMACSHA512 PRF retVal[idx++] = 0; // 0x00 = SP800-108 CTR KDF w/ HMACSHA512 PRF
@ -97,7 +97,7 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
BitHelpers.WriteTo(retVal, ref idx, _validationAlgorithmDigestLengthInBytes); BitHelpers.WriteTo(retVal, ref idx, _validationAlgorithmDigestLengthInBytes);
// See the design document for an explanation of the following code. // See the design document for an explanation of the following code.
byte[] tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes + _validationAlgorithmSubkeyLengthInBytes]; var tempKeys = new byte[_symmetricAlgorithmSubkeyLengthInBytes + _validationAlgorithmSubkeyLengthInBytes];
ManagedSP800_108_CTR_HMACSHA512.DeriveKeys( ManagedSP800_108_CTR_HMACSHA512.DeriveKeys(
kdk: EMPTY_ARRAY, kdk: EMPTY_ARRAY,
label: EMPTY_ARRAY_SEGMENT, label: EMPTY_ARRAY_SEGMENT,
@ -114,7 +114,7 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
rgbKey: new ArraySegment<byte>(tempKeys, 0, _symmetricAlgorithmSubkeyLengthInBytes).AsStandaloneArray(), rgbKey: new ArraySegment<byte>(tempKeys, 0, _symmetricAlgorithmSubkeyLengthInBytes).AsStandaloneArray(),
rgbIV: new byte[_symmetricAlgorithmBlockSizeInBytes])) rgbIV: new byte[_symmetricAlgorithmBlockSizeInBytes]))
{ {
byte[] ciphertext = cryptoTransform.TransformFinalBlock(EMPTY_ARRAY, 0, 0); var ciphertext = cryptoTransform.TransformFinalBlock(EMPTY_ARRAY, 0, 0);
CryptoUtil.Assert(ciphertext != null && ciphertext.Length == _symmetricAlgorithmBlockSizeInBytes, "ciphertext != null && ciphertext.Length == _symmetricAlgorithmBlockSizeInBytes"); CryptoUtil.Assert(ciphertext != null && ciphertext.Length == _symmetricAlgorithmBlockSizeInBytes, "ciphertext != null && ciphertext.Length == _symmetricAlgorithmBlockSizeInBytes");
Buffer.BlockCopy(ciphertext, 0, retVal, idx, ciphertext.Length); Buffer.BlockCopy(ciphertext, 0, retVal, idx, ciphertext.Length);
} }
@ -125,7 +125,7 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
// MAC a zero-length input string and copy the digest to the return buffer. // MAC a zero-length input string and copy the digest to the return buffer.
using (var hashAlg = CreateValidationAlgorithm(new ArraySegment<byte>(tempKeys, _symmetricAlgorithmSubkeyLengthInBytes, _validationAlgorithmSubkeyLengthInBytes).AsStandaloneArray())) using (var hashAlg = CreateValidationAlgorithm(new ArraySegment<byte>(tempKeys, _symmetricAlgorithmSubkeyLengthInBytes, _validationAlgorithmSubkeyLengthInBytes).AsStandaloneArray()))
{ {
byte[] digest = hashAlg.ComputeHash(EMPTY_ARRAY); var digest = hashAlg.ComputeHash(EMPTY_ARRAY);
CryptoUtil.Assert(digest != null && digest.Length == _validationAlgorithmDigestLengthInBytes, "digest != null && digest.Length == _validationAlgorithmDigestLengthInBytes"); CryptoUtil.Assert(digest != null && digest.Length == _validationAlgorithmDigestLengthInBytes, "digest != null && digest.Length == _validationAlgorithmDigestLengthInBytes");
Buffer.BlockCopy(digest, 0, retVal, idx, digest.Length); Buffer.BlockCopy(digest, 0, retVal, idx, digest.Length);
} }
@ -187,16 +187,16 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
} }
ArraySegment<byte> keyModifier = new ArraySegment<byte>(protectedPayload.Array, keyModifierOffset, ivOffset - keyModifierOffset); ArraySegment<byte> keyModifier = new ArraySegment<byte>(protectedPayload.Array, keyModifierOffset, ivOffset - keyModifierOffset);
byte[] iv = new byte[_symmetricAlgorithmBlockSizeInBytes]; var iv = new byte[_symmetricAlgorithmBlockSizeInBytes];
Buffer.BlockCopy(protectedPayload.Array, ivOffset, iv, 0, iv.Length); Buffer.BlockCopy(protectedPayload.Array, ivOffset, iv, 0, iv.Length);
// Step 2: Decrypt the KDK and use it to restore the original encryption and MAC keys. // Step 2: Decrypt the KDK and use it to restore the original encryption and MAC keys.
// We pin all unencrypted keys to limit their exposure via GC relocation. // We pin all unencrypted keys to limit their exposure via GC relocation.
byte[] decryptedKdk = new byte[_keyDerivationKey.Length]; var decryptedKdk = new byte[_keyDerivationKey.Length];
byte[] decryptionSubkey = new byte[_symmetricAlgorithmSubkeyLengthInBytes]; var decryptionSubkey = new byte[_symmetricAlgorithmSubkeyLengthInBytes];
byte[] validationSubkey = new byte[_validationAlgorithmSubkeyLengthInBytes]; var validationSubkey = new byte[_validationAlgorithmSubkeyLengthInBytes];
byte[] derivedKeysBuffer = new byte[checked(decryptionSubkey.Length + validationSubkey.Length)]; var derivedKeysBuffer = new byte[checked(decryptionSubkey.Length + validationSubkey.Length)];
fixed (byte* __unused__1 = decryptedKdk) fixed (byte* __unused__1 = decryptedKdk)
fixed (byte* __unused__2 = decryptionSubkey) fixed (byte* __unused__2 = decryptionSubkey)
@ -289,8 +289,8 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
// Step 1: Generate a random key modifier and IV for this operation. // Step 1: Generate a random key modifier and IV for this operation.
// Both will be equal to the block size of the block cipher algorithm. // Both will be equal to the block size of the block cipher algorithm.
byte[] keyModifier = _genRandom.GenRandom(KEY_MODIFIER_SIZE_IN_BYTES); var keyModifier = _genRandom.GenRandom(KEY_MODIFIER_SIZE_IN_BYTES);
byte[] iv = _genRandom.GenRandom(_symmetricAlgorithmBlockSizeInBytes); var iv = _genRandom.GenRandom(_symmetricAlgorithmBlockSizeInBytes);
// Step 2: Copy the key modifier and the IV to the output stream since they'll act as a header. // Step 2: Copy the key modifier and the IV to the output stream since they'll act as a header.
@ -302,10 +302,10 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
// Step 3: Decrypt the KDK, and use it to generate new encryption and HMAC keys. // Step 3: Decrypt the KDK, and use it to generate new encryption and HMAC keys.
// We pin all unencrypted keys to limit their exposure via GC relocation. // We pin all unencrypted keys to limit their exposure via GC relocation.
byte[] decryptedKdk = new byte[_keyDerivationKey.Length]; var decryptedKdk = new byte[_keyDerivationKey.Length];
byte[] encryptionSubkey = new byte[_symmetricAlgorithmSubkeyLengthInBytes]; var encryptionSubkey = new byte[_symmetricAlgorithmSubkeyLengthInBytes];
byte[] validationSubkey = new byte[_validationAlgorithmSubkeyLengthInBytes]; var validationSubkey = new byte[_validationAlgorithmSubkeyLengthInBytes];
byte[] derivedKeysBuffer = new byte[checked(encryptionSubkey.Length + validationSubkey.Length)]; var derivedKeysBuffer = new byte[checked(encryptionSubkey.Length + validationSubkey.Length)];
fixed (byte* __unused__1 = decryptedKdk) fixed (byte* __unused__1 = decryptedKdk)
fixed (byte* __unused__2 = encryptionSubkey) fixed (byte* __unused__2 = encryptionSubkey)
@ -345,12 +345,12 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
{ {
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
// As an optimization, avoid duplicating the underlying buffer if we're on desktop CLR. // As an optimization, avoid duplicating the underlying buffer if we're on desktop CLR.
byte[] underlyingBuffer = outputStream.GetBuffer(); var underlyingBuffer = outputStream.GetBuffer();
#else #else
byte[] underlyingBuffer = outputStream.ToArray(); var underlyingBuffer = outputStream.ToArray();
#endif #endif
byte[] mac = validationAlgorithm.ComputeHash(underlyingBuffer, KEY_MODIFIER_SIZE_IN_BYTES, checked((int)outputStream.Length - KEY_MODIFIER_SIZE_IN_BYTES)); var mac = validationAlgorithm.ComputeHash(underlyingBuffer, KEY_MODIFIER_SIZE_IN_BYTES, checked((int)outputStream.Length - KEY_MODIFIER_SIZE_IN_BYTES));
outputStream.Write(mac, 0, mac.Length); outputStream.Write(mac, 0, mac.Length);
// At this point, outputStream := { keyModifier || IV || ciphertext || MAC(IV || ciphertext) } // At this point, outputStream := { keyModifier || IV || ciphertext || MAC(IV || ciphertext) }

View File

@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.DataProtection.Managed
public byte[] GenRandom(int numBytes) public byte[] GenRandom(int numBytes)
{ {
byte[] bytes = new byte[numBytes]; var bytes = new byte[numBytes];
_rng.GetBytes(bytes); _rng.GetBytes(bytes);
return bytes; return bytes;
} }

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.DataProtection
{ {
if (propInfo.IsDefined(typeof(ApplyPolicyAttribute))) if (propInfo.IsDefined(typeof(ApplyPolicyAttribute)))
{ {
object valueFromRegistry = key.GetValue(propInfo.Name); var valueFromRegistry = key.GetValue(propInfo.Name);
if (valueFromRegistry != null) if (valueFromRegistry != null)
{ {
if (propInfo.PropertyType == typeof(string)) if (propInfo.PropertyType == typeof(string))
@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.DataProtection
{ {
foreach (string sinkFromRegistry in sinksFromRegistry.Split(';')) foreach (string sinkFromRegistry in sinksFromRegistry.Split(';'))
{ {
string candidate = sinkFromRegistry.Trim(); var candidate = sinkFromRegistry.Trim();
if (!String.IsNullOrEmpty(candidate)) if (!String.IsNullOrEmpty(candidate))
{ {
typeof(IKeyEscrowSink).AssertIsAssignableFrom(Type.GetType(candidate, throwOnError: true)); typeof(IKeyEscrowSink).AssertIsAssignableFrom(Type.GetType(candidate, throwOnError: true));
@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.DataProtection
/// </summary> /// </summary>
public static ServiceDescriptor[] ResolveDefaultPolicy() public static ServiceDescriptor[] ResolveDefaultPolicy()
{ {
RegistryKey subKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\DotNetPackages\Microsoft.AspNetCore.DataProtection"); var subKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\DotNetPackages\Microsoft.AspNetCore.DataProtection");
if (subKey != null) if (subKey != null)
{ {
using (subKey) using (subKey)

View File

@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
throw new ArgumentNullException(nameof(element)); throw new ArgumentNullException(nameof(element));
} }
XElement cloned = new XElement(element); // makes a deep copy so caller doesn't inadvertently modify it var cloned = new XElement(element); // makes a deep copy so caller doesn't inadvertently modify it
// under lock for thread safety // under lock for thread safety
lock (_storedElements) lock (_storedElements)

View File

@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
{ {
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
// Environment.GetFolderPath returns null if the user profile isn't loaded. // Environment.GetFolderPath returns null if the user profile isn't loaded.
string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (!String.IsNullOrEmpty(folderPath)) if (!String.IsNullOrEmpty(folderPath))
{ {
return GetKeyStorageDirectoryFromBaseAppDataPath(folderPath); return GetKeyStorageDirectoryFromBaseAppDataPath(folderPath);
@ -161,7 +161,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
// the %HOME% variable to build up our base key storage path. // the %HOME% variable to build up our base key storage path.
if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID"))) if (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID")))
{ {
string homeEnvVar = Environment.GetEnvironmentVariable("HOME"); var homeEnvVar = Environment.GetEnvironmentVariable("HOME");
if (!String.IsNullOrEmpty(homeEnvVar)) if (!String.IsNullOrEmpty(homeEnvVar))
{ {
return GetKeyStorageDirectoryFromBaseAppDataPath(homeEnvVar); return GetKeyStorageDirectoryFromBaseAppDataPath(homeEnvVar);
@ -202,7 +202,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
if (!IsSafeFilename(friendlyName)) if (!IsSafeFilename(friendlyName))
{ {
string newFriendlyName = Guid.NewGuid().ToString(); var newFriendlyName = Guid.NewGuid().ToString();
_logger?.NameIsNotSafeFileName(friendlyName, newFriendlyName); _logger?.NameIsNotSafeFileName(friendlyName, newFriendlyName);
friendlyName = newFriendlyName; friendlyName = newFriendlyName;
} }
@ -217,8 +217,8 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
// crashes mid-write, we won't end up with a corrupt .xml file. // crashes mid-write, we won't end up with a corrupt .xml file.
Directory.Create(); // won't throw if the directory already exists Directory.Create(); // won't throw if the directory already exists
string tempFilename = Path.Combine(Directory.FullName, Guid.NewGuid().ToString() + ".tmp"); var tempFilename = Path.Combine(Directory.FullName, Guid.NewGuid().ToString() + ".tmp");
string finalFilename = Path.Combine(Directory.FullName, filename + ".xml"); var finalFilename = Path.Combine(Directory.FullName, filename + ".xml");
try try
{ {

View File

@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
foreach (string valueName in RegistryKey.GetValueNames()) foreach (string valueName in RegistryKey.GetValueNames())
{ {
XElement element = ReadElementFromRegKey(RegistryKey, valueName); var element = ReadElementFromRegKey(RegistryKey, valueName);
if (element != null) if (element != null)
{ {
yield return element; yield return element;
@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
// Even though this is in HKLM, WAS ensures that applications hosted in IIS are properly isolated. // Even though this is in HKLM, WAS ensures that applications hosted in IIS are properly isolated.
// See APP_POOL::EnsureSharedMachineKeyStorage in WAS source for more info. // See APP_POOL::EnsureSharedMachineKeyStorage in WAS source for more info.
// The version number will need to change if IIS hosts Core CLR directly. // The version number will need to change if IIS hosts Core CLR directly.
string aspnetAutoGenKeysBaseKeyName = Invariant($@"SOFTWARE\Microsoft\ASP.NET\4.0.30319.0\AutoGenKeys\{WindowsIdentity.GetCurrent().User.Value}"); var aspnetAutoGenKeysBaseKeyName = Invariant($@"SOFTWARE\Microsoft\ASP.NET\4.0.30319.0\AutoGenKeys\{WindowsIdentity.GetCurrent().User.Value}");
var aspnetBaseKey = hklmBaseKey.OpenSubKey(aspnetAutoGenKeysBaseKeyName, writable: true); var aspnetBaseKey = hklmBaseKey.OpenSubKey(aspnetAutoGenKeysBaseKeyName, writable: true);
if (aspnetBaseKey != null) if (aspnetBaseKey != null)
{ {
@ -143,7 +143,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
{ {
_logger?.ReadingDataFromRegistryKeyValue(regKey, valueName); _logger?.ReadingDataFromRegistryKeyValue(regKey, valueName);
string data = regKey.GetValue(valueName) as string; var data = regKey.GetValue(valueName) as string;
return (!String.IsNullOrEmpty(data)) ? XElement.Parse(data) : null; return (!String.IsNullOrEmpty(data)) ? XElement.Parse(data) : null;
} }
@ -156,7 +156,7 @@ namespace Microsoft.AspNetCore.DataProtection.Repositories
if (!IsSafeRegistryValueName(friendlyName)) if (!IsSafeRegistryValueName(friendlyName))
{ {
string newFriendlyName = Guid.NewGuid().ToString(); var newFriendlyName = Guid.NewGuid().ToString();
_logger?.NameIsNotSafeRegistryValueName(friendlyName, newFriendlyName); _logger?.NameIsNotSafeRegistryValueName(friendlyName, newFriendlyName);
friendlyName = newFriendlyName; friendlyName = newFriendlyName;
} }

View File

@ -13,13 +13,13 @@ namespace Microsoft.AspNetCore.DataProtection.SP800_108
public static void DeriveKeys(byte[] kdk, ArraySegment<byte> label, ArraySegment<byte> context, Func<byte[], HashAlgorithm> prfFactory, ArraySegment<byte> output) public static void DeriveKeys(byte[] kdk, ArraySegment<byte> label, ArraySegment<byte> context, Func<byte[], HashAlgorithm> prfFactory, ArraySegment<byte> output)
{ {
// make copies so we can mutate these local vars // make copies so we can mutate these local vars
int outputOffset = output.Offset; var outputOffset = output.Offset;
int outputCount = output.Count; var outputCount = output.Count;
using (HashAlgorithm prf = prfFactory(kdk)) using (var prf = prfFactory(kdk))
{ {
// See SP800-108, Sec. 5.1 for the format of the input to the PRF routine. // See SP800-108, Sec. 5.1 for the format of the input to the PRF routine.
byte[] prfInput = new byte[checked(sizeof(uint) /* [i]_2 */ + label.Count + 1 /* 0x00 */ + context.Count + sizeof(uint) /* [K]_2 */)]; var prfInput = new byte[checked(sizeof(uint) /* [i]_2 */ + label.Count + 1 /* 0x00 */ + context.Count + sizeof(uint) /* [K]_2 */)];
// Copy [L]_2 to prfInput since it's stable over all iterations // Copy [L]_2 to prfInput since it's stable over all iterations
uint outputSizeInBits = (uint)checked((int)outputCount * 8); uint outputSizeInBits = (uint)checked((int)outputCount * 8);
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.DataProtection.SP800_108
Buffer.BlockCopy(label.Array, label.Offset, prfInput, sizeof(uint), label.Count); Buffer.BlockCopy(label.Array, label.Offset, prfInput, sizeof(uint), label.Count);
Buffer.BlockCopy(context.Array, context.Offset, prfInput, sizeof(int) + label.Count + 1, context.Count); Buffer.BlockCopy(context.Array, context.Offset, prfInput, sizeof(int) + label.Count + 1, context.Count);
int prfOutputSizeInBytes = prf.GetDigestSizeInBytes(); var prfOutputSizeInBytes = prf.GetDigestSizeInBytes();
for (uint i = 1; outputCount > 0; i++) for (uint i = 1; outputCount > 0; i++)
{ {
// Copy [i]_2 to prfInput since it mutates with each iteration // Copy [i]_2 to prfInput since it mutates with each iteration
@ -42,9 +42,9 @@ namespace Microsoft.AspNetCore.DataProtection.SP800_108
prfInput[3] = (byte)(i); prfInput[3] = (byte)(i);
// Run the PRF and copy the results to the output buffer // Run the PRF and copy the results to the output buffer
byte[] prfOutput = prf.ComputeHash(prfInput); var prfOutput = prf.ComputeHash(prfInput);
CryptoUtil.Assert(prfOutputSizeInBytes == prfOutput.Length, "prfOutputSizeInBytes == prfOutput.Length"); CryptoUtil.Assert(prfOutputSizeInBytes == prfOutput.Length, "prfOutputSizeInBytes == prfOutput.Length");
int numBytesToCopyThisIteration = Math.Min(prfOutputSizeInBytes, outputCount); var numBytesToCopyThisIteration = Math.Min(prfOutputSizeInBytes, outputCount);
Buffer.BlockCopy(prfOutput, 0, output.Array, outputOffset, numBytesToCopyThisIteration); Buffer.BlockCopy(prfOutput, 0, output.Array, outputOffset, numBytesToCopyThisIteration);
Array.Clear(prfOutput, 0, prfOutput.Length); // contains key material, so delete it Array.Clear(prfOutput, 0, prfOutput.Length); // contains key material, so delete it
@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.DataProtection.SP800_108
public static void DeriveKeysWithContextHeader(byte[] kdk, ArraySegment<byte> label, byte[] contextHeader, ArraySegment<byte> context, Func<byte[], HashAlgorithm> prfFactory, ArraySegment<byte> output) public static void DeriveKeysWithContextHeader(byte[] kdk, ArraySegment<byte> label, byte[] contextHeader, ArraySegment<byte> context, Func<byte[], HashAlgorithm> prfFactory, ArraySegment<byte> output)
{ {
byte[] combinedContext = new byte[checked(contextHeader.Length + context.Count)]; var combinedContext = new byte[checked(contextHeader.Length + context.Count)];
Buffer.BlockCopy(contextHeader, 0, combinedContext, 0, contextHeader.Length); Buffer.BlockCopy(contextHeader, 0, combinedContext, 0, contextHeader.Length);
Buffer.BlockCopy(context.Array, context.Offset, combinedContext, contextHeader.Length, context.Count); Buffer.BlockCopy(context.Array, context.Offset, combinedContext, contextHeader.Length, context.Count);
DeriveKeys(kdk, label, new ArraySegment<byte>(combinedContext), prfFactory, output); DeriveKeys(kdk, label, new ArraySegment<byte>(combinedContext), prfFactory, output);

View File

@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.DataProtection.SP800_108
{ {
public static void DeriveKeyWithContextHeader(this ISP800_108_CTR_HMACSHA512Provider provider, byte* pbLabel, uint cbLabel, byte[] contextHeader, byte* pbContext, uint cbContext, byte* pbDerivedKey, uint cbDerivedKey) public static void DeriveKeyWithContextHeader(this ISP800_108_CTR_HMACSHA512Provider provider, byte* pbLabel, uint cbLabel, byte[] contextHeader, byte* pbContext, uint cbContext, byte* pbDerivedKey, uint cbDerivedKey)
{ {
uint cbCombinedContext = checked((uint)contextHeader.Length + cbContext); var cbCombinedContext = checked((uint)contextHeader.Length + cbContext);
// Try allocating the combined context on the stack to avoid temporary managed objects; only fall back to heap if buffers are too large. // Try allocating the combined context on the stack to avoid temporary managed objects; only fall back to heap if buffers are too large.
byte[] heapAllocatedCombinedContext = (cbCombinedContext > Constants.MAX_STACKALLOC_BYTES) ? new byte[cbCombinedContext] : null; byte[] heapAllocatedCombinedContext = (cbCombinedContext > Constants.MAX_STACKALLOC_BYTES) ? new byte[cbCombinedContext] : null;

View File

@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.DataProtection.SP800_108
// Creates a provider from the given secret. // Creates a provider from the given secret.
public static ISP800_108_CTR_HMACSHA512Provider CreateProvider(Secret kdk) public static ISP800_108_CTR_HMACSHA512Provider CreateProvider(Secret kdk)
{ {
uint secretLengthInBytes = checked((uint)kdk.Length); var secretLengthInBytes = checked((uint)kdk.Length);
if (secretLengthInBytes == 0) if (secretLengthInBytes == 0)
{ {
return CreateEmptyProvider(); return CreateEmptyProvider();

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.DataProtection.SP800_108
// NOTE: pbDerivedKey and cbDerivedKey are modified as data is copied to the output buffer. // NOTE: pbDerivedKey and cbDerivedKey are modified as data is copied to the output buffer.
// this will be zero-inited // this will be zero-inited
byte[] tempInputBuffer = new byte[checked( var tempInputBuffer = new byte[checked(
sizeof(int) /* [i] */ sizeof(int) /* [i] */
+ cbLabel /* Label */ + cbLabel /* Label */
+ 1 /* 0x00 */ + 1 /* 0x00 */

View File

@ -45,14 +45,14 @@ namespace Microsoft.AspNetCore.DataProtection.SP800_108
pBuffers[2].cbBuffer = checked(SHA512_ALG_CHAR_COUNT * sizeof(char)); pBuffers[2].cbBuffer = checked(SHA512_ALG_CHAR_COUNT * sizeof(char));
// Add the header which points to the buffers // Add the header which points to the buffers
BCryptBufferDesc bufferDesc = default(BCryptBufferDesc); var bufferDesc = default(BCryptBufferDesc);
BCryptBufferDesc.Initialize(ref bufferDesc); BCryptBufferDesc.Initialize(ref bufferDesc);
bufferDesc.cBuffers = 3; bufferDesc.cBuffers = 3;
bufferDesc.pBuffers = pBuffers; bufferDesc.pBuffers = pBuffers;
// Finally, invoke the KDF // Finally, invoke the KDF
uint numBytesDerived; uint numBytesDerived;
int ntstatus = UnsafeNativeMethods.BCryptKeyDerivation( var ntstatus = UnsafeNativeMethods.BCryptKeyDerivation(
hKey: _keyHandle, hKey: _keyHandle,
pParameterList: &bufferDesc, pParameterList: &bufferDesc,
pbDerivedKey: pbDerivedKey, pbDerivedKey: pbDerivedKey,

View File

@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.DataProtection
throw new ArgumentNullException(nameof(secret)); throw new ArgumentNullException(nameof(secret));
} }
Secret other = secret as Secret; var other = secret as Secret;
if (other != null) if (other != null)
{ {
// Fast-track: simple deep copy scenario. // Fast-track: simple deep copy scenario.
@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.DataProtection
{ {
// Copy the secret to a temporary managed buffer, then protect the buffer. // Copy the secret to a temporary managed buffer, then protect the buffer.
// We pin the temp buffer and zero it out when we're finished to limit exposure of the secret. // We pin the temp buffer and zero it out when we're finished to limit exposure of the secret.
byte[] tempPlaintextBuffer = new byte[secret.Length]; var tempPlaintextBuffer = new byte[secret.Length];
fixed (byte* pbTempPlaintextBuffer = tempPlaintextBuffer) fixed (byte* pbTempPlaintextBuffer = tempPlaintextBuffer)
{ {
try try
@ -136,14 +136,14 @@ namespace Microsoft.AspNetCore.DataProtection
// mark this memory page as non-pageable, but this is fraught with peril. // mark this memory page as non-pageable, but this is fraught with peril.
if (!OSVersionUtil.IsWindows()) if (!OSVersionUtil.IsWindows())
{ {
SecureLocalAllocHandle handle = SecureLocalAllocHandle.Allocate((IntPtr)checked((int)cbPlaintext)); var handle = SecureLocalAllocHandle.Allocate((IntPtr)checked((int)cbPlaintext));
UnsafeBufferUtil.BlockCopy(from: pbPlaintext, to: handle, byteCount: cbPlaintext); UnsafeBufferUtil.BlockCopy(from: pbPlaintext, to: handle, byteCount: cbPlaintext);
return handle; return handle;
} }
// We need to make sure we're a multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE. // We need to make sure we're a multiple of CRYPTPROTECTMEMORY_BLOCK_SIZE.
uint numTotalBytesToAllocate = cbPlaintext; var numTotalBytesToAllocate = cbPlaintext;
uint numBytesPaddingRequired = CRYPTPROTECTMEMORY_BLOCK_SIZE - (numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE); var numBytesPaddingRequired = CRYPTPROTECTMEMORY_BLOCK_SIZE - (numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE);
if (numBytesPaddingRequired == CRYPTPROTECTMEMORY_BLOCK_SIZE) if (numBytesPaddingRequired == CRYPTPROTECTMEMORY_BLOCK_SIZE)
{ {
numBytesPaddingRequired = 0; // we're already a proper multiple of the block size numBytesPaddingRequired = 0; // we're already a proper multiple of the block size
@ -152,7 +152,7 @@ namespace Microsoft.AspNetCore.DataProtection
CryptoUtil.Assert(numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE == 0, "numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE == 0"); CryptoUtil.Assert(numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE == 0, "numTotalBytesToAllocate % CRYPTPROTECTMEMORY_BLOCK_SIZE == 0");
// Allocate and copy plaintext data; padding is uninitialized / undefined. // Allocate and copy plaintext data; padding is uninitialized / undefined.
SecureLocalAllocHandle encryptedMemoryHandle = SecureLocalAllocHandle.Allocate((IntPtr)numTotalBytesToAllocate); var encryptedMemoryHandle = SecureLocalAllocHandle.Allocate((IntPtr)numTotalBytesToAllocate);
UnsafeBufferUtil.BlockCopy(from: pbPlaintext, to: encryptedMemoryHandle, byteCount: cbPlaintext); UnsafeBufferUtil.BlockCopy(from: pbPlaintext, to: encryptedMemoryHandle, byteCount: cbPlaintext);
// Finally, CryptProtectMemory the whole mess. // Finally, CryptProtectMemory the whole mess.
@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.DataProtection
return new Secret(ManagedGenRandomImpl.Instance.GenRandom(numBytes)); return new Secret(ManagedGenRandomImpl.Instance.GenRandom(numBytes));
} }
byte[] bytes = new byte[numBytes]; var bytes = new byte[numBytes];
fixed (byte* pbBytes = bytes) fixed (byte* pbBytes = bytes)
{ {
try try

View File

@ -112,7 +112,7 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
// ... // ...
// </EncryptedData> // </EncryptedData>
XElement encryptedElement = EncryptElement(plaintextElement); var encryptedElement = EncryptElement(plaintextElement);
return new EncryptedXmlInfo(encryptedElement, typeof(EncryptedXmlDecryptor)); return new EncryptedXmlInfo(encryptedElement, typeof(EncryptedXmlDecryptor));
} }

View File

@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
// <value>{base64}</value> // <value>{base64}</value>
// </encryptedKey> // </encryptedKey>
byte[] protectedSecret = Convert.FromBase64String((string)encryptedElement.Element("value")); var protectedSecret = Convert.FromBase64String((string)encryptedElement.Element("value"));
if (_logger.IsDebugLevelEnabled()) if (_logger.IsDebugLevelEnabled())
{ {
string protectionDescriptorRule; string protectionDescriptorRule;
@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
_logger.DecryptingSecretElementUsingWindowsDPAPING(protectionDescriptorRule); _logger.DecryptingSecretElementUsingWindowsDPAPING(protectionDescriptorRule);
} }
using (Secret secret = DpapiSecretSerializerHelper.UnprotectWithDpapiNG(protectedSecret)) using (var secret = DpapiSecretSerializerHelper.UnprotectWithDpapiNG(protectedSecret))
{ {
return secret.ToXElement(); return secret.ToXElement();
} }

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
CryptoUtil.AssertPlatformIsWindows8OrLater(); CryptoUtil.AssertPlatformIsWindows8OrLater();
int ntstatus = UnsafeNativeMethods.NCryptCreateProtectionDescriptor(protectionDescriptorRule, (uint)flags, out _protectionDescriptorHandle); var ntstatus = UnsafeNativeMethods.NCryptCreateProtectionDescriptor(protectionDescriptorRule, (uint)flags, out _protectionDescriptorHandle);
UnsafeNativeMethods.ThrowExceptionForNCryptStatus(ntstatus); UnsafeNativeMethods.ThrowExceptionForNCryptStatus(ntstatus);
CryptoUtil.AssertSafeHandleIsValid(_protectionDescriptorHandle); CryptoUtil.AssertSafeHandleIsValid(_protectionDescriptorHandle);
@ -72,14 +72,14 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
throw new ArgumentNullException(nameof(plaintextElement)); throw new ArgumentNullException(nameof(plaintextElement));
} }
string protectionDescriptorRuleString = _protectionDescriptorHandle.GetProtectionDescriptorRuleString(); var protectionDescriptorRuleString = _protectionDescriptorHandle.GetProtectionDescriptorRuleString();
_logger?.EncryptingToWindowsDPAPINGUsingProtectionDescriptorRule(protectionDescriptorRuleString); _logger?.EncryptingToWindowsDPAPINGUsingProtectionDescriptorRule(protectionDescriptorRuleString);
// Convert the XML element to a binary secret so that it can be run through DPAPI // Convert the XML element to a binary secret so that it can be run through DPAPI
byte[] cngDpapiEncryptedData; byte[] cngDpapiEncryptedData;
try try
{ {
using (Secret plaintextElementAsSecret = plaintextElement.ToSecret()) using (var plaintextElementAsSecret = plaintextElement.ToSecret())
{ {
cngDpapiEncryptedData = DpapiSecretSerializerHelper.ProtectWithDpapiNG(plaintextElementAsSecret, _protectionDescriptorHandle); cngDpapiEncryptedData = DpapiSecretSerializerHelper.ProtectWithDpapiNG(plaintextElementAsSecret, _protectionDescriptorHandle);
} }
@ -115,7 +115,7 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
// Creates a SID=... protection descriptor string for the current user. // Creates a SID=... protection descriptor string for the current user.
// Reminder: DPAPI:NG provides only encryption, not authentication. // Reminder: DPAPI:NG provides only encryption, not authentication.
using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent()) using (var currentIdentity = WindowsIdentity.GetCurrent())
{ {
// use the SID to create an SDDL string // use the SID to create an SDDL string
return Invariant($"SID={currentIdentity.User.Value}"); return Invariant($"SID={currentIdentity.User.Value}");

View File

@ -56,8 +56,8 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
// <value>{base64}</value> // <value>{base64}</value>
// </encryptedKey> // </encryptedKey>
byte[] protectedSecret = Convert.FromBase64String((string)encryptedElement.Element("value")); var protectedSecret = Convert.FromBase64String((string)encryptedElement.Element("value"));
using (Secret secret = DpapiSecretSerializerHelper.UnprotectWithDpapi(protectedSecret)) using (var secret = DpapiSecretSerializerHelper.UnprotectWithDpapi(protectedSecret))
{ {
return secret.ToXElement(); return secret.ToXElement();
} }

View File

@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
byte[] dpapiEncryptedData; byte[] dpapiEncryptedData;
try try
{ {
using (Secret plaintextElementAsSecret = plaintextElement.ToSecret()) using (var plaintextElementAsSecret = plaintextElement.ToSecret())
{ {
dpapiEncryptedData = DpapiSecretSerializerHelper.ProtectWithDpapi(plaintextElementAsSecret, protectToLocalMachine: _protectToLocalMachine); dpapiEncryptedData = DpapiSecretSerializerHelper.ProtectWithDpapi(plaintextElementAsSecret, protectToLocalMachine: _protectToLocalMachine);
} }

View File

@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
element.Save(memoryStream); element.Save(memoryStream);
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
byte[] underlyingBuffer = memoryStream.GetBuffer(); var underlyingBuffer = memoryStream.GetBuffer();
fixed (byte* __unused__ = underlyingBuffer) // try to limit this moving around in memory while we allocate fixed (byte* __unused__ = underlyingBuffer) // try to limit this moving around in memory while we allocate
{ {
try try
@ -168,13 +168,13 @@ namespace Microsoft.AspNetCore.DataProtection.XmlEncryption
/// </summary> /// </summary>
public static XElement ToXElement(this Secret secret) public static XElement ToXElement(this Secret secret)
{ {
byte[] plaintextSecret = new byte[secret.Length]; var plaintextSecret = new byte[secret.Length];
fixed (byte* __unused__ = plaintextSecret) // try to keep the GC from moving it around fixed (byte* __unused__ = plaintextSecret) // try to keep the GC from moving it around
{ {
try try
{ {
secret.WriteSecretIntoBuffer(new ArraySegment<byte>(plaintextSecret)); secret.WriteSecretIntoBuffer(new ArraySegment<byte>(plaintextSecret));
MemoryStream memoryStream = new MemoryStream(plaintextSecret, writable: false); var memoryStream = new MemoryStream(plaintextSecret, writable: false);
return XElement.Load(memoryStream); return XElement.Load(memoryStream);
} }
finally finally