public void ResolvePolicy_CngGcmEncryption_WithExplicitSettings()
        {
            IServiceCollection serviceCollection = new ServiceCollection();

            RunTestWithRegValues(serviceCollection, new Dictionary <string, object>()
            {
                ["EncryptionType"]              = "cng-gcm",
                ["EncryptionAlgorithm"]         = "enc-alg",
                ["EncryptionAlgorithmKeySize"]  = 2048,
                ["EncryptionAlgorithmProvider"] = "my-enc-alg-provider"
            });

            var services = serviceCollection.BuildServiceProvider();
            var expectedConfiguration = new CngGcmAuthenticatedEncryptorConfiguration(new CngGcmAuthenticatedEncryptionOptions()
            {
                EncryptionAlgorithm         = "enc-alg",
                EncryptionAlgorithmKeySize  = 2048,
                EncryptionAlgorithmProvider = "my-enc-alg-provider"
            });
            var actualConfiguration = (CngGcmAuthenticatedEncryptorConfiguration)services.GetService <IAuthenticatedEncryptorConfiguration>();

            Assert.Equal(expectedConfiguration.Options.EncryptionAlgorithm, actualConfiguration.Options.EncryptionAlgorithm);
            Assert.Equal(expectedConfiguration.Options.EncryptionAlgorithmKeySize, actualConfiguration.Options.EncryptionAlgorithmKeySize);
            Assert.Equal(expectedConfiguration.Options.EncryptionAlgorithmProvider, actualConfiguration.Options.EncryptionAlgorithmProvider);
        }
    /// <summary>
    /// Imports the <see cref="CngCbcAuthenticatedEncryptorDescriptor"/> from serialized XML.
    /// </summary>
    public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element)
    {
        if (element == null)
        {
            throw new ArgumentNullException(nameof(element));
        }

        // <descriptor>
        //   <!-- Windows CNG-GCM -->
        //   <encryption algorithm="..." keyLength="..." [provider="..."] />
        //   <masterKey>...</masterKey>
        // </descriptor>

        var configuration = new CngGcmAuthenticatedEncryptorConfiguration();

        var encryptionElement = element.Element("encryption") !;

        configuration.EncryptionAlgorithm         = (string)encryptionElement.Attribute("algorithm") !;
        configuration.EncryptionAlgorithmKeySize  = (int)encryptionElement.Attribute("keyLength") !;
        configuration.EncryptionAlgorithmProvider = (string?)encryptionElement.Attribute("provider"); // could be null

        Secret masterKey = ((string)element.Element("masterKey") !).ToSecret();

        return(new CngGcmAuthenticatedEncryptorDescriptor(configuration, masterKey));
    }
        public void ResolvePolicy_CngGcmEncryption_WithExplicitSettings()
        {
            // Arrange
            var registryEntries = new Dictionary <string, object>()
            {
                ["EncryptionType"]              = "cng-gcm",
                ["EncryptionAlgorithm"]         = "enc-alg",
                ["EncryptionAlgorithmKeySize"]  = 2048,
                ["EncryptionAlgorithmProvider"] = "my-enc-alg-provider"
            };
            var expectedConfiguration = new CngGcmAuthenticatedEncryptorConfiguration()
            {
                EncryptionAlgorithm         = "enc-alg",
                EncryptionAlgorithmKeySize  = 2048,
                EncryptionAlgorithmProvider = "my-enc-alg-provider"
            };

            // Act
            var context = RunTestWithRegValues(registryEntries);

            // Assert
            var actualConfiguration = (CngGcmAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration;

            Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm);
            Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize);
            Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider);
        }
    internal IAuthenticatedEncryptor?CreateAuthenticatedEncryptorInstance(
        ISecret secret,
        AuthenticatedEncryptorConfiguration?authenticatedConfiguration)
    {
        if (authenticatedConfiguration == null)
        {
            return(null);
        }

        if (IsGcmAlgorithm(authenticatedConfiguration.EncryptionAlgorithm))
        {
#if NETCOREAPP
            return(new AesGcmAuthenticatedEncryptor(secret, GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm) / 8));
#else
            // GCM requires CNG, and CNG is only supported on Windows.
            if (!OSVersionUtil.IsWindows())
            {
                throw new PlatformNotSupportedException(Resources.Platform_WindowsRequiredForGcm);
            }

            Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));

            var configuration = new CngGcmAuthenticatedEncryptorConfiguration()
            {
                EncryptionAlgorithm        = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm),
                EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm)
            };

            return(new CngGcmAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration));
#endif
        }
        else
        {
            if (OSVersionUtil.IsWindows())
            {
                Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
                // CNG preferred over managed implementations if running on Windows
                var configuration = new CngCbcAuthenticatedEncryptorConfiguration()
                {
                    EncryptionAlgorithm        = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm),
                    EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm),
                    HashAlgorithm = GetBCryptAlgorithmNameFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm)
                };

                return(new CngCbcAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration));
            }
            else
            {
                // Use managed implementations as a fallback
                var configuration = new ManagedAuthenticatedEncryptorConfiguration()
                {
                    EncryptionAlgorithmType    = GetManagedTypeFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm),
                    EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm),
                    ValidationAlgorithmType    = GetManagedTypeFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm)
                };

                return(new ManagedAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration));
            }
        }
    }
Exemple #5
0
    public void CreateNewDescriptor_PropagatesOptions()
    {
        // Arrange
        var configuration = new CngGcmAuthenticatedEncryptorConfiguration();

        // Act
        var descriptor = (CngGcmAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor();

        // Assert
        Assert.Equal(configuration, descriptor.Configuration);
    }
Exemple #6
0
        internal IAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance(
            ISecret secret,
            AuthenticatedEncryptorConfiguration authenticatedConfiguration)
        {
            if (authenticatedConfiguration == null)
            {
                return(null);
            }

            if (IsGcmAlgorithm(authenticatedConfiguration.EncryptionAlgorithm))
            {
                // GCM requires CNG, and CNG is only supported on Windows.
                if (!OSVersionUtil.IsWindows())
                {
                    throw new PlatformNotSupportedException("GCM algorithms require the Windows platform.");
                }

                var configuration = new CngGcmAuthenticatedEncryptorConfiguration()
                {
                    EncryptionAlgorithm        = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm),
                    EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm)
                };

                return(new CngGcmAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration));
            }
            else
            {
                if (OSVersionUtil.IsWindows())
                {
                    // CNG preferred over managed implementations if running on Windows
                    var configuration = new CngCbcAuthenticatedEncryptorConfiguration()
                    {
                        EncryptionAlgorithm        = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm),
                        EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm),
                        HashAlgorithm = GetBCryptAlgorithmNameFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm)
                    };

                    return(new CngCbcAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration));
                }
                else
                {
                    // Use managed implementations as a fallback
                    var configuration = new ManagedAuthenticatedEncryptorConfiguration()
                    {
                        EncryptionAlgorithmType    = GetManagedTypeFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm),
                        EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm),
                        ValidationAlgorithmType    = GetManagedTypeFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm)
                    };

                    return(new ManagedAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration));
                }
            }
        }
Exemple #7
0
        internal CngGcmAuthenticatedEncryptor?CreateAuthenticatedEncryptorInstance(
            ISecret secret,
            CngGcmAuthenticatedEncryptorConfiguration configuration)
        {
            if (configuration == null)
            {
                return(null);
            }

            return(new CngGcmAuthenticatedEncryptor(
                       keyDerivationKey: new Secret(secret),
                       symmetricAlgorithmHandle: GetSymmetricBlockCipherAlgorithmHandle(configuration),
                       symmetricAlgorithmKeySizeInBytes: (uint)(configuration.EncryptionAlgorithmKeySize / 8)));
        }
Exemple #8
0
    public void CreateNewDescriptor_CreatesUniqueCorrectlySizedMasterKey()
    {
        // Arrange
        var configuration = new CngGcmAuthenticatedEncryptorConfiguration();

        // Act
        var masterKey1 = ((CngGcmAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey;
        var masterKey2 = ((CngGcmAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey;

        // Assert
        SecretAssert.NotEqual(masterKey1, masterKey2);
        SecretAssert.LengthIs(512 /* bits */, masterKey1);
        SecretAssert.LengthIs(512 /* bits */, masterKey2);
    }
Exemple #9
0
    /// <summary>
    /// Initializes a new instance of <see cref="CngGcmAuthenticatedEncryptorDescriptor"/>.
    /// </summary>
    /// <param name="configuration">The <see cref="CngCbcAuthenticatedEncryptorConfiguration"/>.</param>
    /// <param name="masterKey">The master key.</param>
    public CngGcmAuthenticatedEncryptorDescriptor(CngGcmAuthenticatedEncryptorConfiguration configuration, ISecret masterKey)
    {
        if (configuration == null)
        {
            throw new ArgumentNullException(nameof(configuration));
        }

        if (masterKey == null)
        {
            throw new ArgumentNullException(nameof(masterKey));
        }

        Configuration = configuration;
        MasterKey     = masterKey;
    }
Exemple #10
0
        public void CreateEncrptorInstance_ExpectedDescriptorType_ReturnsEncryptor()
        {
            // Arrange
            var descriptor = new CngGcmAuthenticatedEncryptorConfiguration().CreateNewDescriptor();
            var key        = new Mock <IKey>();

            key.Setup(k => k.Descriptor).Returns(descriptor);

            var factory = new CngGcmAuthenticatedEncryptorFactory(NullLoggerFactory.Instance);

            // Act
            var encryptor = factory.CreateEncryptorInstance(key.Object);

            // Assert
            Assert.NotNull(encryptor);
            Assert.IsType <CngGcmAuthenticatedEncryptor>(encryptor);
        }
Exemple #11
0
        private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle(CngGcmAuthenticatedEncryptorConfiguration configuration)
        {
            // basic argument checking
            if (String.IsNullOrEmpty(configuration.EncryptionAlgorithm))
            {
                throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(EncryptionAlgorithm));
            }
            if (configuration.EncryptionAlgorithmKeySize < 0)
            {
                throw Error.Common_PropertyMustBeNonNegative(nameof(configuration.EncryptionAlgorithmKeySize));
            }

            BCryptAlgorithmHandle?algorithmHandle = null;

            _logger.OpeningCNGAlgorithmFromProviderWithChainingModeGCM(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider);
            // Special-case cached providers
            if (configuration.EncryptionAlgorithmProvider == null)
            {
                if (configuration.EncryptionAlgorithm == Constants.BCRYPT_AES_ALGORITHM)
                {
                    algorithmHandle = CachedAlgorithmHandles.AES_GCM;
                }
            }

            // Look up the provider dynamically if we couldn't fetch a cached instance
            if (algorithmHandle == null)
            {
                algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider);
                algorithmHandle.SetChainingMode(Constants.BCRYPT_CHAIN_MODE_GCM);
            }

            // make sure we're using a block cipher with an appropriate key size & block size
            CryptoUtil.Assert(algorithmHandle.GetCipherBlockLength() == 128 / 8, "GCM requires a block cipher algorithm with a 128-bit block size.");
            AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked ((uint)configuration.EncryptionAlgorithmKeySize));

            // make sure the provided key length is valid
            algorithmHandle.GetSupportedKeyLengths().EnsureValidKeyLength((uint)configuration.EncryptionAlgorithmKeySize);

            // all good!
            return(algorithmHandle);
        }
        private RegistryPolicy?ResolvePolicyCore(RegistryKey?policyRegKey)
        {
            if (policyRegKey == null)
            {
                return(null);
            }

            // Read the encryption options type: CNG-CBC, CNG-GCM, Managed
            AlgorithmConfiguration?configuration = null;

            var encryptionType = (string?)policyRegKey.GetValue("EncryptionType");

            if (String.Equals(encryptionType, "CNG-CBC", StringComparison.OrdinalIgnoreCase))
            {
                configuration = new CngCbcAuthenticatedEncryptorConfiguration();
            }
            else if (String.Equals(encryptionType, "CNG-GCM", StringComparison.OrdinalIgnoreCase))
            {
                configuration = new CngGcmAuthenticatedEncryptorConfiguration();
            }
            else if (String.Equals(encryptionType, "Managed", StringComparison.OrdinalIgnoreCase))
            {
                configuration = new ManagedAuthenticatedEncryptorConfiguration();
            }
            else if (!String.IsNullOrEmpty(encryptionType))
            {
                throw CryptoUtil.Fail("Unrecognized EncryptionType: " + encryptionType);
            }
            if (configuration != null)
            {
                PopulateOptions(configuration, policyRegKey);
            }

            // Read ancillary data

            var defaultKeyLifetime = (int?)policyRegKey.GetValue("DefaultKeyLifetime");

            var keyEscrowSinks = ReadKeyEscrowSinks(policyRegKey).Select(item => _activator.CreateInstance <IKeyEscrowSink>(item));

            return(new RegistryPolicy(configuration, keyEscrowSinks, defaultKeyLifetime));
        }
    private static CngGcmAuthenticatedEncryptorConfiguration GetCngGcmAuthenticatedEncryptorConfiguration(RegistryKey key)
    {
        var options           = new CngGcmAuthenticatedEncryptorConfiguration();
        var valueFromRegistry = key.GetValue(nameof(CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithm));

        if (valueFromRegistry != null)
        {
            options.EncryptionAlgorithm = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture) !;
        }

        valueFromRegistry = key.GetValue(nameof(CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider));
        if (valueFromRegistry != null)
        {
            options.EncryptionAlgorithmProvider = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture) !;
        }

        valueFromRegistry = key.GetValue(nameof(CngGcmAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize));
        if (valueFromRegistry != null)
        {
            options.EncryptionAlgorithmKeySize = Convert.ToInt32(valueFromRegistry, CultureInfo.InvariantCulture);
        }

        return(options);
    }
Exemple #14
0
    public static IDataProtectionBuilder UseCustomCryptographicAlgorithms(this IDataProtectionBuilder builder, CngGcmAuthenticatedEncryptorConfiguration configuration)
    {
        if (builder == null)
        {
            throw new ArgumentNullException(nameof(builder));
        }

        if (configuration == null)
        {
            throw new ArgumentNullException(nameof(configuration));
        }

        return(UseCryptographicAlgorithmsCore(builder, configuration));
    }