diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptionOptions.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptionOptions.cs index da90f3b5b5..8f5bba8e00 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptionOptions.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/AuthenticatedEncryptionOptions.cs @@ -6,6 +6,7 @@ using System.Security.Cryptography; using Microsoft.AspNet.Cryptography; using Microsoft.AspNet.Cryptography.Cng; using Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption { @@ -54,15 +55,15 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption * HELPER ROUTINES */ - internal IAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(ISecret secret) + internal IAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(ISecret secret, IServiceProvider services = null) { return CreateImplementationOptions() - .ToConfiguration() + .ToConfiguration(services) .CreateDescriptorFromSecret(secret) .CreateEncryptorInstance(); } - internal IInternalAuthenticatedEncryptionOptions CreateImplementationOptions() + private IInternalAuthenticatedEncryptionOptions CreateImplementationOptions() { if (IsGcmAlgorithm(EncryptionAlgorithm)) { @@ -192,9 +193,9 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption return (EncryptionAlgorithm.AES_128_GCM <= algorithm && algorithm <= EncryptionAlgorithm.AES_256_GCM); } - IInternalAuthenticatedEncryptorConfiguration IInternalAuthenticatedEncryptionOptions.ToConfiguration() + IInternalAuthenticatedEncryptorConfiguration IInternalAuthenticatedEncryptionOptions.ToConfiguration(IServiceProvider services) { - return new AuthenticatedEncryptorConfiguration(this); + return new AuthenticatedEncryptorConfiguration(this, services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptionOptions.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptionOptions.cs index feacc7996b..baa2ca43c0 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptionOptions.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/CngCbcAuthenticatedEncryptionOptions.cs @@ -7,6 +7,7 @@ using Microsoft.AspNet.Cryptography.Cng; using Microsoft.AspNet.Cryptography.SafeHandles; using Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Microsoft.AspNet.DataProtection.Cng; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption { @@ -93,16 +94,16 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption * HELPER ROUTINES */ - internal CbcAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(ISecret secret) + internal CbcAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(ISecret secret, ILogger logger = null) { return new CbcAuthenticatedEncryptor( keyDerivationKey: new Secret(secret), - symmetricAlgorithmHandle: GetSymmetricBlockCipherAlgorithmHandle(), + symmetricAlgorithmHandle: GetSymmetricBlockCipherAlgorithmHandle(logger), symmetricAlgorithmKeySizeInBytes: (uint)(EncryptionAlgorithmKeySize / 8), - hmacAlgorithmHandle: GetHmacAlgorithmHandle()); + hmacAlgorithmHandle: GetHmacAlgorithmHandle(logger)); } - private BCryptAlgorithmHandle GetHmacAlgorithmHandle() + private BCryptAlgorithmHandle GetHmacAlgorithmHandle(ILogger logger) { // basic argument checking if (String.IsNullOrEmpty(HashAlgorithm)) @@ -110,6 +111,11 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(HashAlgorithm)); } + if (logger.IsVerboseLevelEnabled()) + { + logger.LogVerbose("Opening CNG algorithm '{0}' from provider '{1}' with HMAC.", HashAlgorithm, HashAlgorithmProvider); + } + BCryptAlgorithmHandle algorithmHandle = null; // Special-case cached providers @@ -134,7 +140,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption return algorithmHandle; } - private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle() + private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle(ILogger logger) { // basic argument checking if (String.IsNullOrEmpty(EncryptionAlgorithm)) @@ -146,6 +152,11 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption throw Error.Common_PropertyMustBeNonNegative(nameof(EncryptionAlgorithmKeySize)); } + if (logger.IsVerboseLevelEnabled()) + { + logger.LogVerbose("Opening CNG algorithm '{0}' from provider '{1}' with chaining mode CBC.", EncryptionAlgorithm, EncryptionAlgorithmProvider); + } + BCryptAlgorithmHandle algorithmHandle = null; // Special-case cached providers @@ -172,9 +183,9 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption return algorithmHandle; } - IInternalAuthenticatedEncryptorConfiguration IInternalAuthenticatedEncryptionOptions.ToConfiguration() + IInternalAuthenticatedEncryptorConfiguration IInternalAuthenticatedEncryptionOptions.ToConfiguration(IServiceProvider services) { - return new CngCbcAuthenticatedEncryptorConfiguration(this); + return new CngCbcAuthenticatedEncryptorConfiguration(this, services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptionOptions.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptionOptions.cs index c9b1f38b84..0213fb1598 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptionOptions.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/CngGcmAuthenticatedEncryptionOptions.cs @@ -7,6 +7,7 @@ using Microsoft.AspNet.Cryptography.Cng; using Microsoft.AspNet.Cryptography.SafeHandles; using Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Microsoft.AspNet.DataProtection.Cng; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption { @@ -69,15 +70,15 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption * HELPER ROUTINES */ - internal GcmAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(ISecret secret) + internal GcmAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(ISecret secret, ILogger logger = null) { return new GcmAuthenticatedEncryptor( keyDerivationKey: new Secret(secret), - symmetricAlgorithmHandle: GetSymmetricBlockCipherAlgorithmHandle(), + symmetricAlgorithmHandle: GetSymmetricBlockCipherAlgorithmHandle(logger), symmetricAlgorithmKeySizeInBytes: (uint)(EncryptionAlgorithmKeySize / 8)); } - private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle() + private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle(ILogger logger) { // basic argument checking if (String.IsNullOrEmpty(EncryptionAlgorithm)) @@ -91,6 +92,11 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption BCryptAlgorithmHandle algorithmHandle = null; + if (logger.IsVerboseLevelEnabled()) + { + logger.LogVerbose("Opening CNG algorithm '{0}' from provider '{1}' with chaining mode GCM.", EncryptionAlgorithm, EncryptionAlgorithmProvider); + } + // Special-case cached providers if (EncryptionAlgorithmProvider == null) { @@ -115,9 +121,9 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption return algorithmHandle; } - IInternalAuthenticatedEncryptorConfiguration IInternalAuthenticatedEncryptionOptions.ToConfiguration() + IInternalAuthenticatedEncryptorConfiguration IInternalAuthenticatedEncryptionOptions.ToConfiguration(IServiceProvider services) { - return new CngGcmAuthenticatedEncryptorConfiguration(this); + return new CngGcmAuthenticatedEncryptorConfiguration(this, services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorConfiguration.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorConfiguration.cs index 7b39b10715..ec3c0102fc 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorConfiguration.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorConfiguration.cs @@ -9,26 +9,31 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// /// Represents a generalized authenticated encryption mechanism. /// - public unsafe sealed class AuthenticatedEncryptorConfiguration : IAuthenticatedEncryptorConfiguration, IInternalAuthenticatedEncryptorConfiguration + public sealed class AuthenticatedEncryptorConfiguration : IAuthenticatedEncryptorConfiguration, IInternalAuthenticatedEncryptorConfiguration { + private readonly IServiceProvider _services; + public AuthenticatedEncryptorConfiguration([NotNull] AuthenticatedEncryptionOptions options) + : this(options, services: null) + { + } + + public AuthenticatedEncryptorConfiguration([NotNull] AuthenticatedEncryptionOptions options, IServiceProvider services) { Options = options; + _services = services; } public AuthenticatedEncryptionOptions Options { get; } public IAuthenticatedEncryptorDescriptor CreateNewDescriptor() { - // generate a 512-bit secret randomly - const int KDK_SIZE_IN_BYTES = 512 / 8; - var secret = Secret.Random(KDK_SIZE_IN_BYTES); - return ((IInternalAuthenticatedEncryptorConfiguration)this).CreateDescriptorFromSecret(secret); + return this.CreateNewDescriptorCore(); } - + IAuthenticatedEncryptorDescriptor IInternalAuthenticatedEncryptorConfiguration.CreateDescriptorFromSecret(ISecret secret) { - return new AuthenticatedEncryptorDescriptor(Options, secret); + return new AuthenticatedEncryptorDescriptor(Options, secret, _services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptor.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptor.cs index c5ca78573d..43387d779c 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptor.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptor.cs @@ -13,18 +13,27 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class AuthenticatedEncryptorDescriptor : IAuthenticatedEncryptorDescriptor { - private readonly ISecret _masterKey; - private readonly AuthenticatedEncryptionOptions _options; + private readonly IServiceProvider _services; public AuthenticatedEncryptorDescriptor([NotNull] AuthenticatedEncryptionOptions options, [NotNull] ISecret masterKey) + : this(options, masterKey, services: null) { - _options = options; - _masterKey = masterKey; } + public AuthenticatedEncryptorDescriptor([NotNull] AuthenticatedEncryptionOptions options, [NotNull] ISecret masterKey, IServiceProvider services) + { + Options = options; + MasterKey = masterKey; + _services = services; + } + + internal ISecret MasterKey { get; } + + internal AuthenticatedEncryptionOptions Options { get; } + public IAuthenticatedEncryptor CreateEncryptorInstance() { - return _options.CreateAuthenticatedEncryptorInstance(_masterKey); + return Options.CreateAuthenticatedEncryptorInstance(MasterKey, _services); } public XmlSerializedDescriptorInfo ExportToXml() @@ -36,17 +45,17 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM // var encryptionElement = new XElement("encryption", - new XAttribute("algorithm", _options.EncryptionAlgorithm)); + new XAttribute("algorithm", Options.EncryptionAlgorithm)); - var validationElement = (AuthenticatedEncryptionOptions.IsGcmAlgorithm(_options.EncryptionAlgorithm)) + var validationElement = (AuthenticatedEncryptionOptions.IsGcmAlgorithm(Options.EncryptionAlgorithm)) ? (object)new XComment(" AES-GCM includes a 128-bit authentication tag, no extra validation algorithm required. ") : (object)new XElement("validation", - new XAttribute("algorithm", _options.ValidationAlgorithm)); + new XAttribute("algorithm", Options.ValidationAlgorithm)); var outerElement = new XElement("descriptor", encryptionElement, validationElement, - _masterKey.ToMasterKeyElement()); + MasterKey.ToMasterKeyElement()); return new XmlSerializedDescriptorInfo(outerElement, typeof(AuthenticatedEncryptorDescriptorDeserializer)); } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs index 7908b98748..947282cd5a 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/AuthenticatedEncryptorDescriptorDeserializer.cs @@ -14,6 +14,18 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class AuthenticatedEncryptorDescriptorDeserializer : IAuthenticatedEncryptorDescriptorDeserializer { + private readonly IServiceProvider _services; + + public AuthenticatedEncryptorDescriptorDeserializer() + : this(services: null) + { + } + + public AuthenticatedEncryptorDescriptorDeserializer(IServiceProvider services) + { + _services = services; + } + /// /// Imports the from serialized XML. /// @@ -24,7 +36,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM // // ... // - + var options = new AuthenticatedEncryptionOptions(); var encryptionElement = element.Element("encryption"); @@ -38,7 +50,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM } Secret masterKey = ((string)element.Elements("masterKey").Single()).ToSecret(); - return new AuthenticatedEncryptorDescriptor(options, masterKey); + return new AuthenticatedEncryptorDescriptor(options, masterKey, _services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfiguration.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfiguration.cs index b5dd186849..bb11fabe42 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfiguration.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorConfiguration.cs @@ -10,26 +10,31 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// Represents a configured authenticated encryption mechanism which uses /// Windows CNG algorithms in CBC encryption + HMAC authentication modes. /// - public unsafe sealed class CngCbcAuthenticatedEncryptorConfiguration : IAuthenticatedEncryptorConfiguration, IInternalAuthenticatedEncryptorConfiguration + public sealed class CngCbcAuthenticatedEncryptorConfiguration : IAuthenticatedEncryptorConfiguration, IInternalAuthenticatedEncryptorConfiguration { + private readonly IServiceProvider _services; + public CngCbcAuthenticatedEncryptorConfiguration([NotNull] CngCbcAuthenticatedEncryptionOptions options) + : this(options, services: null) + { + } + + public CngCbcAuthenticatedEncryptorConfiguration([NotNull] CngCbcAuthenticatedEncryptionOptions options, IServiceProvider services) { Options = options; + _services = services; } public CngCbcAuthenticatedEncryptionOptions Options { get; } public IAuthenticatedEncryptorDescriptor CreateNewDescriptor() { - // generate a 512-bit secret randomly - const int KDK_SIZE_IN_BYTES = 512 / 8; - var secret = Secret.Random(KDK_SIZE_IN_BYTES); - return ((IInternalAuthenticatedEncryptorConfiguration)this).CreateDescriptorFromSecret(secret); + return this.CreateNewDescriptorCore(); } IAuthenticatedEncryptorDescriptor IInternalAuthenticatedEncryptorConfiguration.CreateDescriptorFromSecret(ISecret secret) { - return new CngCbcAuthenticatedEncryptorDescriptor(Options, secret); + return new CngCbcAuthenticatedEncryptorDescriptor(Options, secret, _services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptor.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptor.cs index 536dd573b4..d298ae719e 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptor.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptor.cs @@ -4,6 +4,7 @@ using System; using System.Xml.Linq; using Microsoft.Framework.Internal; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel { @@ -13,10 +14,18 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class CngCbcAuthenticatedEncryptorDescriptor : IAuthenticatedEncryptorDescriptor { + private readonly ILogger _log; + public CngCbcAuthenticatedEncryptorDescriptor([NotNull] CngCbcAuthenticatedEncryptionOptions options, [NotNull] ISecret masterKey) + : this(options, masterKey, services: null) + { + } + + public CngCbcAuthenticatedEncryptorDescriptor([NotNull] CngCbcAuthenticatedEncryptionOptions options, [NotNull] ISecret masterKey, IServiceProvider services) { Options = options; MasterKey = masterKey; + _log = services.GetLogger(); } internal ISecret MasterKey { get; } @@ -25,7 +34,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM public IAuthenticatedEncryptor CreateEncryptorInstance() { - return Options.CreateAuthenticatedEncryptorInstance(MasterKey); + return Options.CreateAuthenticatedEncryptorInstance(MasterKey, _log); } public XmlSerializedDescriptorInfo ExportToXml() @@ -51,7 +60,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM { hashElement.SetAttributeValue("provider", Options.HashAlgorithmProvider); } - + var rootElement = new XElement("descriptor", new XComment(" Algorithms provided by Windows CNG, using CBC-mode encryption with HMAC validation "), encryptionElement, diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs index 86f5c5a162..3120c31ba8 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngCbcAuthenticatedEncryptorDescriptorDeserializer.cs @@ -13,6 +13,18 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class CngCbcAuthenticatedEncryptorDescriptorDeserializer : IAuthenticatedEncryptorDescriptorDeserializer { + private readonly IServiceProvider _services; + + public CngCbcAuthenticatedEncryptorDescriptorDeserializer() + : this(services: null) + { + } + + public CngCbcAuthenticatedEncryptorDescriptorDeserializer(IServiceProvider services) + { + _services = services; + } + /// /// Imports the from serialized XML. /// @@ -24,7 +36,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM // // ... // - + var options = new CngCbcAuthenticatedEncryptionOptions(); var encryptionElement = element.Element("encryption"); @@ -38,7 +50,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM Secret masterKey = ((string)element.Element("masterKey")).ToSecret(); - return new CngCbcAuthenticatedEncryptorDescriptor(options, masterKey); + return new CngCbcAuthenticatedEncryptorDescriptor(options, masterKey, _services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfiguration.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfiguration.cs index 4dc914bb70..9ebc51ea7f 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfiguration.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorConfiguration.cs @@ -10,26 +10,31 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// Represents a configured authenticated encryption mechanism which uses /// Windows CNG algorithms in GCM encryption + authentication modes. /// - public unsafe sealed class CngGcmAuthenticatedEncryptorConfiguration : IAuthenticatedEncryptorConfiguration, IInternalAuthenticatedEncryptorConfiguration + public sealed class CngGcmAuthenticatedEncryptorConfiguration : IAuthenticatedEncryptorConfiguration, IInternalAuthenticatedEncryptorConfiguration { + private readonly IServiceProvider _services; + public CngGcmAuthenticatedEncryptorConfiguration([NotNull] CngGcmAuthenticatedEncryptionOptions options) + : this(options, services: null) + { + } + + public CngGcmAuthenticatedEncryptorConfiguration([NotNull] CngGcmAuthenticatedEncryptionOptions options, IServiceProvider services) { Options = options; + _services = services; } public CngGcmAuthenticatedEncryptionOptions Options { get; } public IAuthenticatedEncryptorDescriptor CreateNewDescriptor() { - // generate a 512-bit secret randomly - const int KDK_SIZE_IN_BYTES = 512 / 8; - var secret = Secret.Random(KDK_SIZE_IN_BYTES); - return ((IInternalAuthenticatedEncryptorConfiguration)this).CreateDescriptorFromSecret(secret); + return this.CreateNewDescriptorCore(); } IAuthenticatedEncryptorDescriptor IInternalAuthenticatedEncryptorConfiguration.CreateDescriptorFromSecret(ISecret secret) { - return new CngGcmAuthenticatedEncryptorDescriptor(Options, secret); + return new CngGcmAuthenticatedEncryptorDescriptor(Options, secret, _services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptor.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptor.cs index c70a2a3c90..51c10f5d31 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptor.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptor.cs @@ -4,6 +4,7 @@ using System; using System.Xml.Linq; using Microsoft.Framework.Internal; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel { @@ -13,10 +14,18 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class CngGcmAuthenticatedEncryptorDescriptor : IAuthenticatedEncryptorDescriptor { + private readonly ILogger _log; + public CngGcmAuthenticatedEncryptorDescriptor([NotNull] CngGcmAuthenticatedEncryptionOptions options, [NotNull] ISecret masterKey) + : this(options, masterKey, services: null) + { + } + + public CngGcmAuthenticatedEncryptorDescriptor([NotNull] CngGcmAuthenticatedEncryptionOptions options, [NotNull] ISecret masterKey, IServiceProvider services) { Options = options; MasterKey = masterKey; + _log = services.GetLogger(); } internal ISecret MasterKey { get; } @@ -25,7 +34,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM public IAuthenticatedEncryptor CreateEncryptorInstance() { - return Options.CreateAuthenticatedEncryptorInstance(MasterKey); + return Options.CreateAuthenticatedEncryptorInstance(MasterKey, _log); } public XmlSerializedDescriptorInfo ExportToXml() @@ -43,7 +52,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM { encryptionElement.SetAttributeValue("provider", Options.EncryptionAlgorithmProvider); } - + var rootElement = new XElement("descriptor", new XComment(" Algorithms provided by Windows CNG, using Galois/Counter Mode encryption and validation "), encryptionElement, diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs index 6da12b3b23..801b1e31ef 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/CngGcmAuthenticatedEncryptorDescriptorDeserializer.cs @@ -13,6 +13,18 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class CngGcmAuthenticatedEncryptorDescriptorDeserializer : IAuthenticatedEncryptorDescriptorDeserializer { + private readonly IServiceProvider _services; + + public CngGcmAuthenticatedEncryptorDescriptorDeserializer() + : this(services: null) + { + } + + public CngGcmAuthenticatedEncryptorDescriptorDeserializer(IServiceProvider services) + { + _services = services; + } + /// /// Imports the from serialized XML. /// @@ -33,7 +45,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM Secret masterKey = ((string)element.Element("masterKey")).ToSecret(); - return new CngGcmAuthenticatedEncryptorDescriptor(options, masterKey); + return new CngGcmAuthenticatedEncryptorDescriptor(options, masterKey, _services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ConfigurationCommon.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ConfigurationCommon.cs new file mode 100644 index 0000000000..4d42acca16 --- /dev/null +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ConfigurationCommon.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; + +namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel +{ + internal static class ConfigurationCommon + { + /// + /// Creates an from this + /// using a random 512-bit master key generated from a secure PRNG. + /// + public static IAuthenticatedEncryptorDescriptor CreateNewDescriptorCore(this IInternalAuthenticatedEncryptorConfiguration configuration) + { + const int KDK_SIZE_IN_BYTES = 512 / 8; + return configuration.CreateDescriptorFromSecret(Secret.Random(KDK_SIZE_IN_BYTES)); + } + } +} diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/IInternalAuthenticatedEncryptorConfiguration.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/IInternalAuthenticatedEncryptorConfiguration.cs index f05c33fb4f..46a9068513 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/IInternalAuthenticatedEncryptorConfiguration.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/IInternalAuthenticatedEncryptorConfiguration.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel { @@ -18,7 +19,6 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// Creates a new instance from this /// configuration given specific secret key material. /// - /// IAuthenticatedEncryptorDescriptor CreateDescriptorFromSecret(ISecret secret); } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfiguration.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfiguration.cs index 3bdc2e2f96..f4f8aa3410 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfiguration.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorConfiguration.cs @@ -13,24 +13,29 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class ManagedAuthenticatedEncryptorConfiguration : IAuthenticatedEncryptorConfiguration, IInternalAuthenticatedEncryptorConfiguration { + private readonly IServiceProvider _services; + public ManagedAuthenticatedEncryptorConfiguration([NotNull] ManagedAuthenticatedEncryptionOptions options) + : this(options, services: null) + { + } + + public ManagedAuthenticatedEncryptorConfiguration([NotNull] ManagedAuthenticatedEncryptionOptions options, IServiceProvider services) { Options = options; + _services = services; } public ManagedAuthenticatedEncryptionOptions Options { get; } public IAuthenticatedEncryptorDescriptor CreateNewDescriptor() { - // generate a 512-bit secret randomly - const int KDK_SIZE_IN_BYTES = 512 / 8; - var secret = Secret.Random(KDK_SIZE_IN_BYTES); - return ((IInternalAuthenticatedEncryptorConfiguration)this).CreateDescriptorFromSecret(secret); + return this.CreateNewDescriptorCore(); } IAuthenticatedEncryptorDescriptor IInternalAuthenticatedEncryptorConfiguration.CreateDescriptorFromSecret(ISecret secret) { - return new ManagedAuthenticatedEncryptorDescriptor(Options, secret); + return new ManagedAuthenticatedEncryptorDescriptor(Options, secret, _services); } } } diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptor.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptor.cs index 0d0642b1f1..258fb64db7 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptor.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptor.cs @@ -5,6 +5,7 @@ using System; using System.Security.Cryptography; using System.Xml.Linq; using Microsoft.Framework.Internal; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel { @@ -14,10 +15,18 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class ManagedAuthenticatedEncryptorDescriptor : IAuthenticatedEncryptorDescriptor { + private readonly ILogger _log; + public ManagedAuthenticatedEncryptorDescriptor([NotNull] ManagedAuthenticatedEncryptionOptions options, [NotNull] ISecret masterKey) + : this(options, masterKey, services: null) + { + } + + public ManagedAuthenticatedEncryptorDescriptor([NotNull] ManagedAuthenticatedEncryptionOptions options, [NotNull] ISecret masterKey, IServiceProvider services) { Options = options; MasterKey = masterKey; + _log = services.GetLogger(); } internal ISecret MasterKey { get; } @@ -26,7 +35,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM public IAuthenticatedEncryptor CreateEncryptorInstance() { - return Options.CreateAuthenticatedEncryptorInstance(MasterKey); + return Options.CreateAuthenticatedEncryptorInstance(MasterKey, _log); } public XmlSerializedDescriptorInfo ExportToXml() diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs index 59878538f3..be28842cf2 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ConfigurationModel/ManagedAuthenticatedEncryptorDescriptorDeserializer.cs @@ -14,6 +14,18 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM /// public sealed class ManagedAuthenticatedEncryptorDescriptorDeserializer : IAuthenticatedEncryptorDescriptorDeserializer { + private readonly IServiceProvider _services; + + public ManagedAuthenticatedEncryptorDescriptorDeserializer() + : this(services: null) + { + } + + public ManagedAuthenticatedEncryptorDescriptorDeserializer(IServiceProvider services) + { + _services = services; + } + /// /// Imports the from serialized XML. /// @@ -37,7 +49,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationM Secret masterKey = ((string)element.Element("masterKey")).ToSecret(); - return new ManagedAuthenticatedEncryptorDescriptor(options, masterKey); + return new ManagedAuthenticatedEncryptorDescriptor(options, masterKey, _services); } // Any changes to this method should also be be reflected diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/IInternalAuthenticatedEncryptionOptions.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/IInternalAuthenticatedEncryptionOptions.cs index 444990a3ba..7718c6a18b 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/IInternalAuthenticatedEncryptionOptions.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/IInternalAuthenticatedEncryptionOptions.cs @@ -15,7 +15,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption /// Creates a object /// from the given options. /// - IInternalAuthenticatedEncryptorConfiguration ToConfiguration(); + IInternalAuthenticatedEncryptorConfiguration ToConfiguration(IServiceProvider services); /// /// Performs a self-test of the algorithm specified by the options object. diff --git a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptionOptions.cs b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptionOptions.cs index cb71ca58bc..944b5b9721 100644 --- a/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptionOptions.cs +++ b/src/Microsoft.AspNet.DataProtection/AuthenticatedEncryption/ManagedAuthenticatedEncryptionOptions.cs @@ -6,6 +6,7 @@ using System.Security.Cryptography; using Microsoft.AspNet.Cryptography.Cng; using Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Microsoft.AspNet.DataProtection.Managed; +using Microsoft.Framework.Logging; namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption { @@ -68,16 +69,16 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption * HELPER ROUTINES */ - internal ManagedAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(ISecret secret) + internal ManagedAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(ISecret secret, ILogger logger = null) { return new ManagedAuthenticatedEncryptor( keyDerivationKey: new Secret(secret), - symmetricAlgorithmFactory: GetSymmetricBlockCipherAlgorithmFactory(), + symmetricAlgorithmFactory: GetSymmetricBlockCipherAlgorithmFactory(logger), symmetricAlgorithmKeySizeInBytes: EncryptionAlgorithmKeySize / 8, - validationAlgorithmFactory: GetKeyedHashAlgorithmFactory()); + validationAlgorithmFactory: GetKeyedHashAlgorithmFactory(logger)); } - private Func GetKeyedHashAlgorithmFactory() + private Func GetKeyedHashAlgorithmFactory(ILogger logger) { // basic argument checking if (ValidationAlgorithmType == null) @@ -85,6 +86,11 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(ValidationAlgorithmType)); } + if (logger.IsVerboseLevelEnabled()) + { + logger.LogVerbose("Using managed keyed hash algorithm '{0}'.", ValidationAlgorithmType.FullName); + } + if (ValidationAlgorithmType == typeof(HMACSHA256)) { return () => new HMACSHA256(); @@ -99,7 +105,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption } } - private Func GetSymmetricBlockCipherAlgorithmFactory() + private Func GetSymmetricBlockCipherAlgorithmFactory(ILogger logger) { // basic argument checking if (EncryptionAlgorithmType == null) @@ -112,6 +118,11 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption throw Error.Common_PropertyMustBeNonNegative(nameof(EncryptionAlgorithmKeySize)); } + if (logger.IsVerboseLevelEnabled()) + { + logger.LogVerbose("Using managed symmetric algorithm '{0}'.", EncryptionAlgorithmType.FullName); + } + if (EncryptionAlgorithmType == typeof(Aes)) { Func factory = null; @@ -130,9 +141,9 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption } } - IInternalAuthenticatedEncryptorConfiguration IInternalAuthenticatedEncryptionOptions.ToConfiguration() + IInternalAuthenticatedEncryptorConfiguration IInternalAuthenticatedEncryptionOptions.ToConfiguration(IServiceProvider services) { - return new ManagedAuthenticatedEncryptorConfiguration(this); + return new ManagedAuthenticatedEncryptorConfiguration(this, services); } /// diff --git a/src/Microsoft.AspNet.DataProtection/DataProtectionServiceDescriptors.cs b/src/Microsoft.AspNet.DataProtection/DataProtectionServiceDescriptors.cs index 43b94d65a5..3276c76575 100644 --- a/src/Microsoft.AspNet.DataProtection/DataProtectionServiceDescriptors.cs +++ b/src/Microsoft.AspNet.DataProtection/DataProtectionServiceDescriptors.cs @@ -66,8 +66,7 @@ namespace Microsoft.Framework.DependencyInjection /// public static ServiceDescriptor IAuthenticatedEncryptorConfiguration_FromOptions(IInternalAuthenticatedEncryptionOptions options) { - // We don't flow services since there's nothing interesting to flow. - return ServiceDescriptor.Singleton(services => options.ToConfiguration()); + return ServiceDescriptor.Singleton(options.ToConfiguration); } #if !DNXCORE50 // [[ISSUE60]] Remove this #ifdef when Core CLR gets support for EncryptedXml diff --git a/src/Microsoft.AspNet.DataProtection/EphemeralDataProtectionProvider.cs b/src/Microsoft.AspNet.DataProtection/EphemeralDataProtectionProvider.cs index 262d978e0d..f0d9fbf856 100644 --- a/src/Microsoft.AspNet.DataProtection/EphemeralDataProtectionProvider.cs +++ b/src/Microsoft.AspNet.DataProtection/EphemeralDataProtectionProvider.cs @@ -69,7 +69,7 @@ namespace Microsoft.AspNet.DataProtection // Currently hardcoded to a 512-bit KDK. private const int NUM_BYTES_IN_KDK = 512 / 8; - public IAuthenticatedEncryptor DefaultAuthenticatedEncryptor { get; } = new T().ToConfiguration().CreateNewDescriptor().CreateEncryptorInstance(); + public IAuthenticatedEncryptor DefaultAuthenticatedEncryptor { get; } = new T().ToConfiguration(services: null).CreateNewDescriptor().CreateEncryptorInstance(); public Guid DefaultKeyId { get; } = default(Guid);