Ejemplo n.º 1
0
        /// <summary>
        ///     Computes the signature of a hash that was produced by the hash algorithm specified by "hashAlgorithm."
        /// </summary>
        public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
        {
            if (hash == null)
            {
                throw new ArgumentNullException("hash");
            }

            unsafe
            {
                byte[] signature = null;
                SignOrVerify(padding, hashAlgorithm, hash,
                             delegate(AsymmetricPaddingMode paddingMode, void *pPaddingInfo)
                {
                    SafeNCryptKeyHandle keyHandle = Key.Handle;
                    int numBytesNeeded;
                    ErrorCode errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, null, 0, out numBytesNeeded, paddingMode);
                    if (errorCode != ErrorCode.ERROR_SUCCESS)
                    {
                        throw errorCode.ToCryptographicException();
                    }

                    signature = new byte[numBytesNeeded];
                    errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
                    if (errorCode != ErrorCode.ERROR_SUCCESS)
                    {
                        throw errorCode.ToCryptographicException();
                    }
                }
                             );
                return(signature);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        ///     Export the key out of the KSP
        /// </summary>
        public byte[] Export(CngKeyBlobFormat format)
        {
            if (format == null)
            {
                throw new ArgumentNullException(nameof(format));
            }

            int       numBytesNeeded;
            ErrorCode errorCode = Interop.NCrypt.NCryptExportKey(_keyHandle, IntPtr.Zero, format.Format, IntPtr.Zero, null, 0, out numBytesNeeded, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            byte[] buffer = new byte[numBytesNeeded];
            errorCode = Interop.NCrypt.NCryptExportKey(_keyHandle, IntPtr.Zero, format.Format, IntPtr.Zero, buffer, buffer.Length, out numBytesNeeded, 0);
            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Array.Resize(ref buffer, numBytesNeeded);
            return(buffer);
        }
Ejemplo n.º 3
0
        internal static bool TryExportKeyBlob(
            SafeNCryptKeyHandle keyHandle,
            string blobType,
            Span <byte> destination,
            out int bytesWritten)
        {
            if (destination.IsEmpty)
            {
                bytesWritten = 0;
                return(false);
            }

            // Sanity check the current bounds
            Span <byte> empty = default;

            ErrorCode errorCode = Interop.NCrypt.NCryptExportKey(
                keyHandle,
                IntPtr.Zero,
                blobType,
                IntPtr.Zero,
                ref MemoryMarshal.GetReference(empty),
                empty.Length,
                out int written,
                0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            if (written > destination.Length)
            {
                bytesWritten = 0;
                return(false);
            }

            if (written == 0)
            {
                bytesWritten = 0;
                return(true);
            }

            errorCode = Interop.NCrypt.NCryptExportKey(
                keyHandle,
                IntPtr.Zero,
                blobType,
                IntPtr.Zero,
                ref MemoryMarshal.GetReference(destination),
                destination.Length,
                out written,
                0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            bytesWritten = written;
            return(true);
        }
Ejemplo n.º 4
0
        public static CngKey Create(CngAlgorithm algorithm, string?keyName, CngKeyCreationParameters?creationParameters)
        {
            ArgumentNullException.ThrowIfNull(algorithm);

            creationParameters ??= new CngKeyCreationParameters();

            SafeNCryptProviderHandle providerHandle = creationParameters.Provider !.OpenStorageProvider();
            SafeNCryptKeyHandle      keyHandle;
            ErrorCode errorCode = Interop.NCrypt.NCryptCreatePersistedKey(providerHandle, out keyHandle, algorithm.Algorithm, keyName, 0, creationParameters.KeyCreationOptions);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                // For ecc, the exception may be caught and re-thrown as PlatformNotSupportedException
                throw errorCode.ToCryptographicException();
            }

            InitializeKeyProperties(keyHandle, creationParameters);

            errorCode = Interop.NCrypt.NCryptFinalizeKey(keyHandle, 0);
            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                // For ecc, the exception may be caught and re-thrown as PlatformNotSupportedException
                throw errorCode.ToCryptographicException();
            }

            CngKey key = new CngKey(providerHandle, keyHandle);

            // No name translates to an ephemeral key
            if (keyName == null)
            {
                key.IsEphemeral = true;
            }

            return(key);
        }
Ejemplo n.º 5
0
        internal static SafeNCryptKeyHandle GenerateNewExportableKey(string algorithm, ref ECCurve explicitCurve)
        {
            // Despite the function being create "persisted" key, since we pass a null name it's
            // actually ephemeral.
            SafeNCryptKeyHandle keyHandle;
            ErrorCode           errorCode = Interop.NCrypt.NCryptCreatePersistedKey(
                s_microsoftSoftwareProviderHandle,
                out keyHandle,
                algorithm,
                null,
                0,
                CngKeyCreationOptions.None);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Debug.Assert(!keyHandle.IsInvalid);

            SetExportable(keyHandle);
            byte[] parametersBlob = ECCng.GetPrimeCurveParameterBlob(ref explicitCurve);
            SetProperty(keyHandle, KeyPropertyName.ECCParameters, parametersBlob);

            errorCode = Interop.NCrypt.NCryptFinalizeKey(keyHandle, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            return(keyHandle);
        }
Ejemplo n.º 6
0
        internal static SafeNCryptKeyHandle GenerateNewExportableKey(string algorithm, int keySize)
        {
            // Despite the function being create "persisted" key, since we pass a null name it's
            // actually ephemeral.
            SafeNCryptKeyHandle keyHandle;
            ErrorCode           errorCode = Interop.NCrypt.NCryptCreatePersistedKey(
                s_microsoftSoftwareProviderHandle,
                out keyHandle,
                algorithm,
                null,
                0,
                CngKeyCreationOptions.None);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Debug.Assert(!keyHandle.IsInvalid);

            SetExportable(keyHandle);
            SetKeyLength(keyHandle, keySize);

            errorCode = Interop.NCrypt.NCryptFinalizeKey(keyHandle, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            return(keyHandle);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Returns a CNG key property.
        /// </summary>
        /// <returns>
        /// null - if property not defined on key.
        /// throws - for any other type of error.
        /// </returns>
        private static byte[]? GetProperty(SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options)
        {
            Debug.Assert(!ncryptHandle.IsInvalid);
            unsafe
            {
                int       numBytesNeeded;
                ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, null, 0, out numBytesNeeded, options);
                if (errorCode == ErrorCode.NTE_NOT_FOUND)
                {
                    return(null);
                }
                if (errorCode != ErrorCode.ERROR_SUCCESS)
                {
                    throw errorCode.ToCryptographicException();
                }

                byte[] propertyValue = new byte[numBytesNeeded];
                fixed(byte *pPropertyValue = propertyValue)
                {
                    errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, pPropertyValue, propertyValue.Length, out numBytesNeeded, options);
                }

                if (errorCode == ErrorCode.NTE_NOT_FOUND)
                {
                    return(null);
                }
                if (errorCode != ErrorCode.ERROR_SUCCESS)
                {
                    throw errorCode.ToCryptographicException();
                }

                Array.Resize(ref propertyValue, numBytesNeeded);
                return(propertyValue);
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Returns a CNG key property.
        /// </summary>
        /// <returns>
        /// null - if property not defined on key.
        /// throws - for any other type of error.
        /// </returns>
        public static byte[] GetProperty(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options)
        {
            unsafe
            {
                int       numBytesNeeded;
                ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, null, 0, out numBytesNeeded, options);
                if (errorCode == ErrorCode.NTE_NOT_FOUND)
                {
                    return(null);
                }
                if (errorCode != ErrorCode.ERROR_SUCCESS)
                {
                    throw errorCode.ToCryptographicException();
                }

                byte[] propertyValue = new byte[numBytesNeeded];
                fixed(byte *pPropertyValue = propertyValue)
                {
                    errorCode = Interop.NCrypt.NCryptGetProperty(ncryptHandle, propertyName, pPropertyValue, numBytesNeeded, out numBytesNeeded, options);
                }

                if (errorCode == ErrorCode.NTE_NOT_FOUND)
                {
                    return(null);
                }
                if (errorCode != ErrorCode.ERROR_SUCCESS)
                {
                    throw errorCode.ToCryptographicException();
                }

                return(propertyValue);
            }
        }
Ejemplo n.º 9
0
        internal static byte[] ExportKeyBlob(SafeNCryptKeyHandle keyHandle, string blobType)
        {
            Debug.Assert(!keyHandle.IsInvalid);

            int numBytesNeeded;

            ErrorCode errorCode = Interop.NCrypt.NCryptExportKey(
                keyHandle,
                IntPtr.Zero,
                blobType,
                IntPtr.Zero,
                null,
                0,
                out numBytesNeeded,
                0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            if (numBytesNeeded == 0)
            {
                // This is rather unlikely, but prevents an error from ref buffer[0].
                return(Array.Empty <byte>());
            }

            byte[] buffer = new byte[numBytesNeeded];

            errorCode = Interop.NCrypt.NCryptExportKey(
                keyHandle,
                IntPtr.Zero,
                blobType,
                IntPtr.Zero,
                ref buffer[0],
                buffer.Length,
                out numBytesNeeded,
                0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            if (buffer.Length != numBytesNeeded)
            {
                Span <byte> writtenPortion = buffer.AsSpan(0, numBytesNeeded);
                byte[]      tmp            = writtenPortion.ToArray();
                CryptographicOperations.ZeroMemory(writtenPortion);
                return(tmp);
            }

            return(buffer);
        }
Ejemplo n.º 10
0
        public static unsafe byte[] SignHash(this SafeNCryptKeyHandle keyHandle, ReadOnlySpan <byte> hash, AsymmetricPaddingMode paddingMode, void *pPaddingInfo, int estimatedSize)
        {
#if DEBUG
            estimatedSize = 2;  // Make sure the NTE_BUFFER_TOO_SMALL scenario gets exercised.
#endif
            byte[]    signature = new byte[estimatedSize];
            int       numBytesNeeded;
            ErrorCode errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);

            if (errorCode == ErrorCode.STATUS_UNSUCCESSFUL)
            {
                errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
            }

            if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL)
            {
                signature = new byte[numBytesNeeded];
                errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
            }

            if (errorCode == ErrorCode.STATUS_UNSUCCESSFUL)
            {
                errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
            }

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Array.Resize(ref signature, numBytesNeeded);
            return(signature);
        }
Ejemplo n.º 11
0
        public static CngKey Import(byte[] keyBlob, CngKeyBlobFormat format, CngProvider provider)
        {
            if (keyBlob == null)
            {
                throw new ArgumentNullException(nameof(keyBlob));
            }
            if (format == null)
            {
                throw new ArgumentNullException(nameof(format));
            }
            if (provider == null)
            {
                throw new ArgumentNullException(nameof(provider));
            }

            SafeNCryptProviderHandle providerHandle = provider.OpenStorageProvider();
            SafeNCryptKeyHandle      keyHandle;
            ErrorCode errorCode = Interop.NCrypt.NCryptImportKey(providerHandle, IntPtr.Zero, format.Format, IntPtr.Zero, out keyHandle, keyBlob, keyBlob.Length, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            CngKey key = new CngKey(providerHandle, keyHandle);

            // We can't tell directly if an OpaqueTransport blob imported as an ephemeral key or not
            key.IsEphemeral = format != CngKeyBlobFormat.OpaqueTransportBlob;

            return(key);
        }
Ejemplo n.º 12
0
        // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption.
        private unsafe byte[] EncryptOrDecrypt(SafeNCryptKeyHandle key, byte[] input, AsymmetricPaddingMode paddingMode, void *paddingInfo, bool encrypt)
        {
            int estimatedSize = KeySize / 8;

#if DEBUG
            estimatedSize = 2;  // Make sure the NTE_BUFFER_TOO_SMALL scenario gets exercised.
#endif

            byte[]    output = new byte[estimatedSize];
            int       numBytesNeeded;
            ErrorCode errorCode = encrypt ?
                                  Interop.NCrypt.NCryptEncrypt(key, input, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode) :
                                  Interop.NCrypt.NCryptDecrypt(key, input, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode);

            if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL)
            {
                output    = new byte[numBytesNeeded];
                errorCode = encrypt ?
                            Interop.NCrypt.NCryptEncrypt(key, input, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode) :
                            Interop.NCrypt.NCryptDecrypt(key, input, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode);
            }
            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Array.Resize(ref output, numBytesNeeded);
            return(output);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Retrieve a well-known CNG pointer property. (Note: .NET Framework compat: this helper likes to return special values
        /// rather than throw exceptions for missing or ill-formatted property values. Only use it for well-known properties that
        /// are unlikely to be ill-formatted.)
        /// </summary>
        internal static IntPtr GetPropertyAsIntPtr(this SafeNCryptHandle ncryptHandle, string propertyName, CngPropertyOptions options)
        {
            unsafe
            {
                IntPtr value;

                ErrorCode errorCode = Interop.NCrypt.NCryptGetProperty(
                    ncryptHandle,
                    propertyName,
                    &value,
                    IntPtr.Size,
                    out _,
                    options);

                if (errorCode == ErrorCode.NTE_NOT_FOUND)
                {
                    return(IntPtr.Zero);
                }

                if (errorCode != ErrorCode.ERROR_SUCCESS)
                {
                    throw errorCode.ToCryptographicException();
                }

                return(value);
            }
        }
Ejemplo n.º 14
0
        // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption.
        private unsafe byte[] EncryptOrDecrypt(SafeNCryptKeyHandle key, ReadOnlySpan <byte> input, AsymmetricPaddingMode paddingMode, void *paddingInfo, bool encrypt)
        {
            int estimatedSize = KeySize / 8;

#if DEBUG
            estimatedSize = 2;  // Make sure the NTE_BUFFER_TOO_SMALL scenario gets exercised.
#endif

            byte[]    output = new byte[estimatedSize];
            int       numBytesNeeded;
            ErrorCode errorCode =
                EncryptOrDecrypt(key, input, output, paddingMode, paddingInfo, encrypt, out numBytesNeeded);

            if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL)
            {
                CryptographicOperations.ZeroMemory(output);
                output    = new byte[numBytesNeeded];
                errorCode =
                    EncryptOrDecrypt(key, input, output, paddingMode, paddingInfo, encrypt, out numBytesNeeded);
            }

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            if (numBytesNeeded != output.Length)
            {
                byte[] ret = output.AsSpan(0, numBytesNeeded).ToArray();
                CryptographicOperations.ZeroMemory(output);
                output = ret;
            }

            return(output);
        }
Ejemplo n.º 15
0
        internal static unsafe int GetKeyLength(SafeNCryptKeyHandle keyHandle)
        {
            Debug.Assert(!keyHandle.IsInvalid);
            int keySize = 0;

            // Attempt to use PublicKeyLength first as it returns the correct value for ECC keys
            ErrorCode errorCode = Interop.NCrypt.NCryptGetIntProperty(
                keyHandle,
                KeyPropertyName.PublicKeyLength,
                ref keySize);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                // Fall back to Length (< Windows 10)
                errorCode = Interop.NCrypt.NCryptGetIntProperty(
                    keyHandle,
                    KeyPropertyName.Length,
                    ref keySize);
            }

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            return(keySize);
        }
Ejemplo n.º 16
0
        public static bool Exists(string keyName, CngProvider provider, CngKeyOpenOptions options)
        {
            ArgumentNullException.ThrowIfNull(keyName);
            ArgumentNullException.ThrowIfNull(provider);

            using (SafeNCryptProviderHandle providerHandle = provider.OpenStorageProvider())
            {
                SafeNCryptKeyHandle?keyHandle = null;
                try
                {
                    ErrorCode errorCode = Interop.NCrypt.NCryptOpenKey(providerHandle, out keyHandle, keyName, 0, options);
                    if (errorCode == ErrorCode.NTE_BAD_KEYSET)
                    {
                        return(false);
                    }
                    if (errorCode != ErrorCode.ERROR_SUCCESS)
                    {
                        throw errorCode.ToCryptographicException();
                    }
                    return(true);
                }
                finally
                {
                    if (keyHandle != null)
                    {
                        keyHandle.Dispose();
                    }
                }
            }
        }
Ejemplo n.º 17
0
        // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption.
        private unsafe bool TryEncryptOrDecrypt(SafeNCryptKeyHandle key, ReadOnlySpan <byte> input, Span <byte> output, AsymmetricPaddingMode paddingMode, void *paddingInfo, bool encrypt, out int bytesWritten)
        {
            for (int i = 0; i <= StatusUnsuccessfulRetryCount; i++)
            {
                int       numBytesNeeded;
                ErrorCode errorCode =
                    EncryptOrDecrypt(key, input, output, paddingMode, paddingInfo, encrypt, out numBytesNeeded);

                switch (errorCode)
                {
                case ErrorCode.ERROR_SUCCESS:
                    bytesWritten = numBytesNeeded;
                    return(true);

                case ErrorCode.NTE_BUFFER_TOO_SMALL:
                    bytesWritten = 0;
                    return(false);

                case ErrorCode.STATUS_UNSUCCESSFUL:
                    break;

                default:
                    throw errorCode.ToCryptographicException();
                }
            }

            throw ErrorCode.STATUS_UNSUCCESSFUL.ToCryptographicException();
        }
Ejemplo n.º 18
0
        public static unsafe bool TrySignHash(this SafeNCryptKeyHandle keyHandle, ReadOnlySpan <byte> hash, Span <byte> signature, AsymmetricPaddingMode paddingMode, void *pPaddingInfo, out int bytesWritten)
        {
            for (int i = 0; i <= StatusUnsuccessfulRetryCount; i++)
            {
                ErrorCode error = Interop.NCrypt.NCryptSignHash(
                    keyHandle,
                    pPaddingInfo,
                    hash,
                    hash.Length,
                    signature,
                    signature.Length,
                    out int numBytesNeeded,
                    paddingMode);

                switch (error)
                {
                case ErrorCode.ERROR_SUCCESS:
                    bytesWritten = numBytesNeeded;
                    return(true);

                case ErrorCode.NTE_BUFFER_TOO_SMALL:
                    bytesWritten = 0;
                    return(false);

                case ErrorCode.STATUS_UNSUCCESSFUL:
                    // Retry
                    break;

                default:
                    throw error.ToCryptographicException();
                }
            }

            throw ErrorCode.STATUS_UNSUCCESSFUL.ToCryptographicException();
        }
Ejemplo n.º 19
0
        //
        // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption.
        //
        private static unsafe byte[] EncryptOrDecrypt(SafeNCryptKeyHandle key, byte[] input, AsymmetricPaddingMode paddingMode, void *paddingInfo, EncryptOrDecryptAction encryptOrDecrypt)
        {
            int       numBytesNeeded;
            ErrorCode errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, null, 0, out numBytesNeeded, paddingMode);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            byte[] output = new byte[numBytesNeeded];
            errorCode = encryptOrDecrypt(key, input, input.Length, paddingInfo, output, numBytesNeeded, out numBytesNeeded, paddingMode);
            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            return(output);
        }
Ejemplo n.º 20
0
 /// <summary>
 ///     Modify a CNG key's export policy.
 /// </summary>
 public static void SetExportPolicy(this SafeNCryptKeyHandle keyHandle, CngExportPolicies exportPolicy)
 {
     unsafe
     {
         ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.ExportPolicy, &exportPolicy, sizeof(CngExportPolicies), CngPropertyOptions.Persist);
         if (errorCode != ErrorCode.ERROR_SUCCESS)
         {
             throw errorCode.ToCryptographicException();
         }
     }
 }
Ejemplo n.º 21
0
        internal static unsafe CngKey ImportEncryptedPkcs8(
            ReadOnlySpan <byte> keyBlob,
            ReadOnlySpan <char> password,
            CngProvider provider)
        {
            SafeNCryptProviderHandle providerHandle = provider.OpenStorageProvider();
            SafeNCryptKeyHandle      keyHandle;

            using (SafeUnicodeStringHandle passwordHandle = new SafeUnicodeStringHandle(password))
            {
                Interop.NCrypt.NCryptBuffer *buffers = stackalloc Interop.NCrypt.NCryptBuffer[1];

                buffers[0] = new Interop.NCrypt.NCryptBuffer
                {
                    BufferType = Interop.NCrypt.BufferType.PkcsSecret,
                    cbBuffer   = checked (2 * (password.Length + 1)),
                    pvBuffer   = passwordHandle.DangerousGetHandle(),
                };

                if (buffers[0].pvBuffer == IntPtr.Zero)
                {
                    buffers[0].cbBuffer = 0;
                }

                Interop.NCrypt.NCryptBufferDesc desc = new Interop.NCrypt.NCryptBufferDesc
                {
                    cBuffers  = 1,
                    pBuffers  = (IntPtr)buffers,
                    ulVersion = 0,
                };

                ErrorCode errorCode = Interop.NCrypt.NCryptImportKey(
                    providerHandle,
                    IntPtr.Zero,
                    Interop.NCrypt.NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
                    ref desc,
                    out keyHandle,
                    ref MemoryMarshal.GetReference(keyBlob),
                    keyBlob.Length,
                    0);

                if (errorCode != ErrorCode.ERROR_SUCCESS)
                {
                    keyHandle.Dispose();
                    providerHandle.Dispose();
                    throw errorCode.ToCryptographicException();
                }
            }

            CngKey key = new CngKey(providerHandle, keyHandle);

            key.IsEphemeral = true;
            return(key);
        }
Ejemplo n.º 22
0
        internal static byte[] ExportKeyBlob(SafeNCryptKeyHandle keyHandle, string blobType)
        {
            Debug.Assert(!keyHandle.IsInvalid);

            int numBytesNeeded;

            ErrorCode errorCode = Interop.NCrypt.NCryptExportKey(
                keyHandle,
                IntPtr.Zero,
                blobType,
                IntPtr.Zero,
                null,
                0,
                out numBytesNeeded,
                0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            byte[] buffer = new byte[numBytesNeeded];

            errorCode = Interop.NCrypt.NCryptExportKey(
                keyHandle,
                IntPtr.Zero,
                blobType,
                IntPtr.Zero,
                buffer,
                buffer.Length,
                out numBytesNeeded,
                0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Array.Resize(ref buffer, numBytesNeeded);
            return(buffer);
        }
Ejemplo n.º 23
0
        /// <summary>
        ///     Setup the key properties specified in the key creation parameters
        /// </summary>
        private static void InitializeKeyProperties(SafeNCryptKeyHandle keyHandle, CngKeyCreationParameters creationParameters)
        {
            unsafe
            {
                if (creationParameters.ExportPolicy.HasValue)
                {
                    CngExportPolicies exportPolicy = creationParameters.ExportPolicy.Value;
                    keyHandle.SetExportPolicy(exportPolicy);
                }

                if (creationParameters.KeyUsage.HasValue)
                {
                    CngKeyUsages keyUsage  = creationParameters.KeyUsage.Value;
                    ErrorCode    errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.KeyUsage, &keyUsage, sizeof(CngKeyUsages), CngPropertyOptions.Persist);
                    if (errorCode != ErrorCode.ERROR_SUCCESS)
                    {
                        throw errorCode.ToCryptographicException();
                    }
                }

                if (creationParameters.ParentWindowHandle != IntPtr.Zero)
                {
                    IntPtr    parentWindowHandle = creationParameters.ParentWindowHandle;
                    ErrorCode errorCode          = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.ParentWindowHandle, &parentWindowHandle, sizeof(IntPtr), CngPropertyOptions.None);
                    if (errorCode != ErrorCode.ERROR_SUCCESS)
                    {
                        throw errorCode.ToCryptographicException();
                    }
                }

                CngUIPolicy uiPolicy = creationParameters.UIPolicy;
                if (uiPolicy != null)
                {
                    InitializeKeyUiPolicyProperties(keyHandle, uiPolicy);
                }

                // Iterate over the custom properties, setting those as well.
                foreach (CngProperty property in creationParameters.Parameters)
                {
                    byte[] value       = property.GetValueWithoutCopying();
                    int    valueLength = (value == null) ? 0 : value.Length;
                    fixed(byte *pValue = value.MapZeroLengthArrayToNonNullPointer())
                    {
                        ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, property.Name, pValue, valueLength, property.Options);

                        if (errorCode != ErrorCode.ERROR_SUCCESS)
                        {
                            throw errorCode.ToCryptographicException();
                        }
                    }
                }
            }
        }
Ejemplo n.º 24
0
        public static SafeNCryptProviderHandle OpenStorageProvider(this CngProvider provider)
        {
            string providerName = provider.Provider;
            SafeNCryptProviderHandle providerHandle;
            ErrorCode errorCode = Interop.NCrypt.NCryptOpenStorageProvider(out providerHandle, providerName, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }
            return(providerHandle);
        }
Ejemplo n.º 25
0
        public static CngKey Create(CngAlgorithm algorithm, string keyName, CngKeyCreationParameters creationParameters)
        {
            if (algorithm == null)
            {
                throw new ArgumentNullException(nameof(algorithm));
            }

            if (creationParameters == null)
            {
                creationParameters = new CngKeyCreationParameters();
            }

            SafeNCryptProviderHandle providerHandle = creationParameters.Provider.OpenStorageProvider();
            SafeNCryptKeyHandle      keyHandle;
            ErrorCode errorCode = Interop.NCrypt.NCryptCreatePersistedKey(providerHandle, out keyHandle, algorithm.Algorithm, keyName, 0, creationParameters.KeyCreationOptions);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            InitializeKeyProperties(keyHandle, creationParameters);

            errorCode = Interop.NCrypt.NCryptFinalizeKey(keyHandle, 0);
            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            CngKey key = new CngKey(providerHandle, keyHandle);

            // No name translates to an ephemeral key
            if (keyName == null)
            {
                key.IsEphemeral = true;
            }

            return(key);
        }
Ejemplo n.º 26
0
        private static SafeNCryptProviderHandle OpenNCryptProvider(string providerName)
        {
            SafeNCryptProviderHandle providerHandle;
            ErrorCode errorCode = Interop.NCrypt.NCryptOpenStorageProvider(out providerHandle, providerName, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Debug.Assert(!providerHandle.IsInvalid);
            return(providerHandle);
        }
Ejemplo n.º 27
0
        /// <summary>
        ///     Delete this key
        /// </summary>
        public void Delete()
        {
            ErrorCode errorCode = Interop.NCrypt.NCryptDeleteKey(_keyHandle, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }
            _keyHandle.SetHandleAsInvalid();

            // Once the key is deleted, the handles are no longer valid so dispose of this instance
            Dispose();
        }
Ejemplo n.º 28
0
        /// <summary>
        ///     Export the key out of the KSP
        /// </summary>
        public byte[] Export(CngKeyBlobFormat format)
        {
            if (format == null)
            {
                throw new ArgumentNullException("format");
            }

            int       numBytesRequired;
            ErrorCode errorCode = Interop.NCrypt.NCryptExportKey(_keyHandle, IntPtr.Zero, format.Format, IntPtr.Zero, null, 0, out numBytesRequired, 0);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            byte[] buffer = new byte[numBytesRequired];
            errorCode = Interop.NCrypt.NCryptExportKey(_keyHandle, IntPtr.Zero, format.Format, IntPtr.Zero, buffer, numBytesRequired, out numBytesRequired, 0);
            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            return(buffer);
        }
Ejemplo n.º 29
0
        // Now that the padding mode and information have been marshaled to their native counterparts, perform the encryption or decryption.
        private unsafe byte[] EncryptOrDecrypt(SafeNCryptKeyHandle key, ReadOnlySpan <byte> input, AsymmetricPaddingMode paddingMode, void *paddingInfo, bool encrypt)
        {
            int estimatedSize = KeySize / 8;

#if DEBUG
            estimatedSize = 2;  // Make sure the NTE_BUFFER_TOO_SMALL scenario gets exercised.
#endif

            byte[] output         = new byte[estimatedSize];
            int    numBytesNeeded = 0;

            ErrorCode errorCode = 0;

            for (int i = 0; i <= StatusUnsuccessfulRetryCount; i++)
            {
                errorCode =
                    EncryptOrDecrypt(key, input, output, paddingMode, paddingInfo, encrypt, out numBytesNeeded);

                if (errorCode != ErrorCode.STATUS_UNSUCCESSFUL)
                {
                    break;
                }
            }

            if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL)
            {
                output = new byte[numBytesNeeded];

                for (int i = 0; i <= StatusUnsuccessfulRetryCount; i++)
                {
                    errorCode =
                        EncryptOrDecrypt(key, input, output, paddingMode, paddingInfo, encrypt, out numBytesNeeded);

                    if (errorCode != ErrorCode.STATUS_UNSUCCESSFUL)
                    {
                        break;
                    }
                }
            }

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            Array.Resize(ref output, numBytesNeeded);
            return(output);
        }
Ejemplo n.º 30
0
        public static CngKey Open(string keyName, CngProvider provider, CngKeyOpenOptions openOptions)
        {
            ArgumentNullException.ThrowIfNull(keyName);
            ArgumentNullException.ThrowIfNull(provider);

            SafeNCryptProviderHandle providerHandle = provider.OpenStorageProvider();
            SafeNCryptKeyHandle      keyHandle;
            ErrorCode errorCode = Interop.NCrypt.NCryptOpenKey(providerHandle, out keyHandle, keyName, 0, openOptions);

            if (errorCode != ErrorCode.ERROR_SUCCESS)
            {
                throw errorCode.ToCryptographicException();
            }

            return(new CngKey(providerHandle, keyHandle));
        }