internal static extern int NCryptVerifySignature( SafeNCryptKeyHandle hKey,
                                                        [In] ref NCRYPT_PKCS1_PADDING_INFO pPaddingInfo,
                                                        [In, MarshalAs( UnmanagedType.LPArray )] byte[] pbHashValue,
                                                        int cbHashValue,
                                                        [In, MarshalAs( UnmanagedType.LPArray )] byte[] pbSignature,
                                                        int cbSignature,
                                                        AsymmetricPaddingMode dwFlags );
Exemple #2
0
            private void ImportKeyBlob(byte[] rsaBlob, bool includePrivate)
            {
                // Use generic blob type for multiple version support
                string blobType = includePrivate ?
                    Interop.BCrypt.KeyBlobType.BCRYPT_PRIVATE_KEY_BLOB :
                    Interop.BCrypt.KeyBlobType.BCRYPT_PUBLIC_KEY_BLOB;

                SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, rsaBlob);

                Debug.Assert(!keyHandle.IsInvalid);

                _keyHandle = keyHandle;

                int newKeySize = CngKeyLite.GetKeyLength(keyHandle);

                // Our LegalKeySizes value stores the values that we encoded as being the correct
                // legal key size limitations for this algorithm, as documented on MSDN.
                //
                // But on a new OS version we might not question if our limit is accurate, or MSDN
                // could have been inaccurate to start with.
                //
                // Since the key is already loaded, we know that Windows thought it to be valid;
                // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
                // check.
                ForceSetKeySize(newKeySize);
                _lastKeySize = newKeySize;
            }
Exemple #3
0
            private void ImportKeyBlob(byte[] rsaBlob, bool includePrivate)
            {
                string blobType = includePrivate ?
                    Interop.BCrypt.KeyBlobType.BCRYPT_RSAPRIVATE_BLOB :
                    Interop.BCrypt.KeyBlobType.BCRYPT_PUBLIC_KEY_BLOB;

                SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, rsaBlob);

                Debug.Assert(!keyHandle.IsInvalid);

                _keyHandle = keyHandle;

                int newKeySize = CngKeyLite.GetKeyLength(keyHandle);

                // Our LegalKeySizes value stores the values that we encoded as being the correct
                // legal key size limitations for this algorithm, as documented on MSDN.
                //
                // But on a new OS version we might not question if our limit is accurate, or MSDN
                // could have been inaccurate to start with.
                //
                // Since the key is already loaded, we know that Windows thought it to be valid;
                // therefore we should set KeySizeValue directly to bypass the LegalKeySizes conformance
                // check.
                //
                // For RSA there are known cases where this change matters. RSACryptoServiceProvider can
                // create a 384-bit RSA key, which we consider too small to be legal. It can also create
                // a 1032-bit RSA key, which we consider illegal because it doesn't match our 64-bit
                // alignment requirement. (In both cases Windows loads it just fine)
                ForceSetKeySize(newKeySize);
                _lastKeySize = newKeySize;
            }
Exemple #4
0
 private static extern SafeCertContextHandle CertCreateSelfSignCertificate(SafeNCryptKeyHandle hCryptProvOrNCryptKey,
                                                                            [In] ref CRYPTOAPI_BLOB pSubjectIssuerBlob,
                                                                            X509CertificateCreationOptions dwFlags,
                                                                            [In] ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
                                                                            [In] ref CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
                                                                            [In] ref SYSTEMTIME pStartTime,
                                                                            [In] ref SYSTEMTIME pEndTime,
                                                                            [In] ref CERT_EXTENSIONS pExtensions);
Exemple #5
0
        private CngKey(SafeNCryptProviderHandle providerHandle, SafeNCryptKeyHandle keyHandle)
        {
            Debug.Assert(keyHandle != null && !keyHandle.IsInvalid && !keyHandle.IsClosed);
            Debug.Assert(providerHandle != null && !providerHandle.IsInvalid && !providerHandle.IsClosed);

            _providerHandle = providerHandle;
            _keyHandle = keyHandle;
        }
 internal static extern int NCryptImportKey( SafeNCryptProviderHandle hProvider,
                                                     IntPtr hImportKey,
                                                     [MarshalAs( UnmanagedType.LPWStr )] string pszBlobType,
                                                     [In, MarshalAs( UnmanagedType.LPArray )] byte[] pParameterList,
                                                     out SafeNCryptKeyHandle phKey,
                                                     [In, MarshalAs( UnmanagedType.LPArray )] byte[] pbData,
                                                     int cbData,
                                                     int dwFlags );
        /// <summary>
        ///     Wrap an existing key handle with a CngKey object
        /// </summary>
        public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions)
        {
            if (keyHandle == null)
                throw new ArgumentNullException("keyHandle");
            if (keyHandle.IsClosed || keyHandle.IsInvalid)
                throw new ArgumentException(SR.Cryptography_OpenInvalidHandle, "keyHandle");

            SafeNCryptKeyHandle keyHandleCopy = keyHandle.Duplicate();

            // Get a handle to the key's provider.
            SafeNCryptProviderHandle providerHandle = new SafeNCryptProviderHandle();
            IntPtr rawProviderHandle = keyHandle.GetPropertyAsIntPtr(KeyPropertyName.ProviderHandle, CngPropertyOptions.None);
            providerHandle.SetHandleValue(rawProviderHandle);

            // Set up a key object wrapping the handle
            CngKey key = null;
            try
            {
                key = new CngKey(providerHandle, keyHandleCopy);
                bool openingEphemeralKey = (keyHandleOpenOptions & CngKeyHandleOpenOptions.EphemeralKey) == CngKeyHandleOpenOptions.EphemeralKey;

                //
                // If we're wrapping a handle to an ephemeral key, we need to make sure that IsEphemeral is
                // set up to return true.  In the case that the handle is for an ephemeral key that was created
                // by the CLR, then we don't have anything to do as the IsEphemeral CLR property will already
                // be setup.  However, if the key was created outside of the CLR we will need to setup our
                // ephemeral detection property.
                // 
                // This enables consumers of CngKey objects to always be able to rely on the result of
                // calling IsEphemeral, and also allows them to safely access the Name property.
                // 
                // Finally, if we detect that this is an ephemeral key that the CLR created but we were not
                // told that it was an ephemeral key we'll throw an exception.  This prevents us from having
                // to decide who to believe -- the key property or the caller of the API.  Since other code
                // relies on the ephemeral flag being set properly to avoid tripping over bugs in CNG, we
                // need to reject the case that we suspect that the flag is incorrect.
                // 

                if (!key.IsEphemeral && openingEphemeralKey)
                {
                    key.IsEphemeral = true;
                }
                else if (key.IsEphemeral && !openingEphemeralKey)
                {
                    throw new ArgumentException(SR.Cryptography_OpenEphemeralKeyHandleWithoutEphemeralFlag, "keyHandleOpenOptions");
                }
            }
            catch
            {
                // Make sure that we don't leak the handle the CngKey duplicated
                if (key != null)
                    key.Dispose();

                throw;
            }

            return key;
        }
        private CngKey(SafeNCryptProviderHandle kspHandle, SafeNCryptKeyHandle keyHandle) {
            Contract.Requires(keyHandle != null && !keyHandle.IsInvalid && !keyHandle.IsClosed);
            Contract.Requires(kspHandle != null && !kspHandle.IsInvalid && !kspHandle.IsClosed);
            Contract.Ensures(m_keyHandle != null && !m_keyHandle.IsInvalid && !m_keyHandle.IsClosed);
            Contract.Ensures(kspHandle != null && !kspHandle.IsInvalid && !kspHandle.IsClosed);

            m_keyHandle = keyHandle;
            m_kspHandle = kspHandle;
        }
Exemple #9
0
        private T GetPrivateKey <T>(Func <CspParameters, T> createCsp, Func <CngKey, T> createCng, Func <IntPtr, int, T> createNoPersistCsp = null) where T : AsymmetricAlgorithm
        {
            // begin: gost
            if (createCng != null)
            {
                // end: gost
                CngKeyHandleOpenOptions cngHandleOptions;
                SafeNCryptKeyHandle     ncryptKey = TryAcquireCngPrivateKey(CertContext, out cngHandleOptions);
                if (ncryptKey != null)
                {
                    CngKey cngKey = CngKey.Open(ncryptKey, cngHandleOptions);
                    return(createCng(cngKey));
                }
            }

            if (createNoPersistCsp != null)
            {
                var(hProv, keySpec) = GetNonPersistPrivateKeyCsp();
                if (hProv != IntPtr.Zero)
                {
                    return(createNoPersistCsp(hProv, keySpec));
                }
            }

            CspParameters cspParameters = GetPrivateKeyCsp();

            if (cspParameters == null)
            {
                return(null);
            }

            // begin: gost
            if (createCng != null &&
                // end: gost
                cspParameters.ProviderType == 0)
            {
                // ProviderType being 0 signifies that this is actually a CNG key, not a CAPI key. Crypt32.dll stuffs the CNG Key Storage Provider
                // name into CRYPT_KEY_PROV_INFO->ProviderName, and the CNG key name into CRYPT_KEY_PROV_INFO->KeyContainerName.

                string keyStorageProvider = cspParameters.ProviderName;
                string keyName            = cspParameters.KeyContainerName;
                CngKey cngKey             = CngKey.Open(keyName, new CngProvider(keyStorageProvider));
                return(createCng(cngKey));
            }
            else
            {
                // ProviderType being non-zero signifies that this is a CAPI key.
                // We never want to stomp over certificate private keys.
                cspParameters.Flags |= CspProviderFlags.UseExistingKey;
                return(createCsp(cspParameters));
            }
        }
Exemple #10
0
            private void ImportKeyBlob(byte[] rsaBlob, bool includePrivate)
            {
                string blobType = includePrivate ?
                    Interop.BCrypt.KeyBlobType.BCRYPT_RSAPRIVATE_BLOB :
                    Interop.BCrypt.KeyBlobType.BCRYPT_PUBLIC_KEY_BLOB;

                SafeNCryptKeyHandle keyHandle = CngKeyLite.ImportKeyBlob(blobType, rsaBlob);

                Debug.Assert(!keyHandle.IsInvalid);

                _keyHandle = keyHandle;
                int newKeySize = CngKeyLite.GetKeyLength(keyHandle);
                KeySize = _lastKeySize = newKeySize;
            }
Exemple #11
0
        public static void SafeNCryptKeyHandle_InvalidKey_ParentHandle_NotKeptAlive()
        {
            using (SafeHandle parentHandle = new StateInformingSafeHandle())
            using (var keyHandle = new SafeNCryptKeyHandle(IntPtr.Zero, parentHandle))
            {
                Assert.False(parentHandle.IsInvalid, "After ctor, parentHandle.IsInvalid");
                Assert.False(parentHandle.IsClosed, "After ctor, parentHandle.IsClosed");

                parentHandle.Dispose();

                Assert.True(parentHandle.IsInvalid, "After parentHandle.Dispose, parentHandle.IsInvalid");
                Assert.True(parentHandle.IsClosed, "After parentHandle.Dispose, parentHandle.IsClosed");
            }
        }
Exemple #12
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();
                    }
                }
            }
        }
Exemple #13
0
            private SafeNCryptKeyHandle GetDuplicatedKeyHandle()
            {
                int keySize = KeySize;

                if (_lastKeySize != keySize)
                {
                    if (_keyHandle != null)
                    {
                        _keyHandle.Dispose();
                    }

                    const string BCRYPT_RSA_ALGORITHM = "RSA";

                    _keyHandle = CngKeyLite.GenerateNewExportableKey(BCRYPT_RSA_ALGORITHM, keySize);
                    _lastKeySize = keySize;
                }

                return new DuplicateSafeNCryptKeyHandle(_keyHandle);
            }
Exemple #14
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;
        }
Exemple #15
0
        private ICertificatePal CopyWithEphemeralKey(CngKey cngKey)
        {
            Debug.Assert(string.IsNullOrEmpty(cngKey.KeyName));

            SafeNCryptKeyHandle handle = cngKey.Handle;

            // Make a new pal from bytes.
            CertificatePal pal = (CertificatePal)FromBlob(RawData, SafePasswordHandle.InvalidHandle, X509KeyStorageFlags.PersistKeySet);

            if (!Interop.crypt32.CertSetCertificateContextProperty(
                    pal._certContext,
                    CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID,
                    CertSetPropertyFlags.CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
                    handle))
            {
                pal.Dispose();
                throw Marshal.GetLastWin32Error().ToCryptographicException();
            }

            // The value was transferred to the certificate.
            handle.SetHandleAsInvalid();
            return(pal);
        }
Exemple #16
0
            private SafeNCryptKeyHandle GetDuplicatedKeyHandle()
            {
                if (IsECNamedCurve(_lastAlgorithm))
                {
                    // Curve was previously created, so use that
                    return new DuplicateSafeNCryptKeyHandle(_keyHandle);
                }
                else
                {
                    string algorithm = null;

                    int keySize = KeySize;
                    if (_lastKeySize != keySize)
                    {
                        // Map the current key size to a CNG algorithm name
                        switch (keySize)
                        {
                            case 256: algorithm = AlgorithmName.ECDsaP256; break;
                            case 384: algorithm = AlgorithmName.ECDsaP384; break;
                            case 521: algorithm = AlgorithmName.ECDsaP521; break;
                            default:
                                Debug.Fail("Should not have invalid key size");
                                throw new ArgumentException(SR.Cryptography_InvalidKeySize);
                        }
                        if (_keyHandle != null)
                        {
                            DisposeKey();
                        }
                        _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, keySize);
                        _lastKeySize = keySize;
                        _lastAlgorithm = algorithm;
                        ForceSetKeySize(keySize);
                    }
                    return new DuplicateSafeNCryptKeyHandle(_keyHandle);
                }
            }
        //
        // 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, EncryptOrDecryptAction encryptOrDecrypt)
        {
            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, input.Length, paddingInfo, output, output.Length, out numBytesNeeded, paddingMode);
            if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL)
            {
                output = new byte[numBytesNeeded];
                errorCode = encryptOrDecrypt(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;
        }
Exemple #18
0
 private void DisposeKey()
 {
     if (_keyHandle != null)
     {
         _keyHandle.Dispose();
         _keyHandle = null;
     }
     _lastAlgorithm = null;
     _lastKeySize = 0;
 }
Exemple #19
0
 public static extern bool CryptAcquireCertificatePrivateKey(SafeCertContextHandle pCert, CryptAcquireFlags dwFlags, IntPtr pvParameters, out SafeNCryptKeyHandle phCryptProvOrNCryptKey, out int pdwKeySpec, out bool pfCallerFreeProvOrNCryptKey);
Exemple #20
0
 internal static unsafe extern ErrorCode NCryptVerifySignature(SafeNCryptKeyHandle hKey, void *pPaddingInfo, [In] byte[] pbHashValue, int cbHashValue, [In] byte[] pbSignature, int cbSignature, AsymmetricPaddingMode dwFlags);
Exemple #21
0
            public override void GenerateKey(ECCurve curve)
            {
                curve.Validate();

                if (_keyHandle != null)
                {
                    DisposeKey();
                }

                string algorithm = null;
                int keySize = 0;

                if (curve.IsNamed)
                {
                    // Map curve name to algorithm to support pre-Win10 curves
                    algorithm = ECCng.EcdsaCurveNameToAlgorithm(curve.Oid.FriendlyName);
                    if (IsECNamedCurve(algorithm))
                    {
                        try
                        {
                            _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, curve.Oid.FriendlyName);
                            keySize = CngKeyLite.GetKeyLength(_keyHandle);
                        }
                        catch (CryptographicException e)
                        {
                            // Map to PlatformNotSupportedException if appropriate
                            ErrorCode errorCode = (ErrorCode)e.HResult;

                            if (curve.IsNamed &&
                                errorCode == ErrorCode.NTE_INVALID_PARAMETER || errorCode == ErrorCode.NTE_NOT_SUPPORTED)
                            {
                                throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.Oid.FriendlyName), e);
                            }
                            throw;
                        }
                    }
                    else
                    {
                        // Get the proper KeySize from algorithm name
                        if (algorithm == AlgorithmName.ECDsaP256)
                            keySize = 256;
                        else if (algorithm == AlgorithmName.ECDsaP384)
                            keySize = 384;
                        else if (algorithm == AlgorithmName.ECDsaP521)
                            keySize = 521;
                        else
                        {
                            Debug.Fail(string.Format("Unknown algorithm {0}", algorithm.ToString()));
                            throw new ArgumentException(SR.Cryptography_InvalidKeySize);
                        }
                        _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, keySize);
                    }
                }
                else if (curve.IsExplicit)
                {
                    algorithm = AlgorithmName.ECDsa;
                    _keyHandle = CngKeyLite.GenerateNewExportableKey(algorithm, ref curve);
                    keySize = CngKeyLite.GetKeyLength(_keyHandle);
                }
                else
                {
                    throw new PlatformNotSupportedException(string.Format(SR.Cryptography_CurveNotSupported, curve.CurveType.ToString()));
                }

                _lastAlgorithm = algorithm;
                _lastKeySize = keySize;
                ForceSetKeySize(keySize);
            }
Exemple #22
0
 public static unsafe partial bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, SafeNCryptKeyHandle keyHandle);
Exemple #23
0
 public static extern unsafe bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, [In] SafeNCryptKeyHandle keyHandle);
Exemple #24
0
 internal static extern ErrorCode NCryptCreatePersistedKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszAlgId, string pszKeyName, int dwLegacyKeySpec, CngKeyCreationOptions dwFlags);
Exemple #25
0
        public static bool CryptAcquireCertificatePrivateKey(SafeCertContextHandle pCert, Interop.Crypt32.CryptAcquireCertificatePrivateKeyFlags dwFlags, IntPtr pvParameters, out SafeNCryptKeyHandle phCryptProvOrNCryptKey, out int pdwKeySpec, out bool pfCallerFreeProvOrNCryptKey)
        {
            bool result = Interop.Crypt32.CryptAcquireCertificatePrivateKey(pCert, dwFlags, pvParameters, out phCryptProvOrNCryptKey, out Interop.Crypt32.CryptKeySpec pdwKeySpecEnum, out pfCallerFreeProvOrNCryptKey);

            pdwKeySpec = (int)pdwKeySpecEnum;
            return(result);
        }
Exemple #26
0
 internal static extern ErrorCode NCryptOpenKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszKeyName, int dwLegacyKeySpec, CngKeyOpenOptions dwFlags);
Exemple #27
0
        private static void SetKeyProperties(SafeNCryptKeyHandle keyHandle,
                                             CngKeyCreationParameters creationParameters) {
            Contract.Requires(keyHandle != null && !keyHandle.IsInvalid && !keyHandle.IsClosed);
            Contract.Requires(creationParameters != null);

            //
            // Setup the well-known properties.
            //

            if (creationParameters.ExportPolicy.HasValue) {
                NCryptNative.SetProperty(keyHandle,
                                         NCryptNative.KeyPropertyName.ExportPolicy,
                                         (int)creationParameters.ExportPolicy.Value,
                                         CngPropertyOptions.Persist);
            }

            if (creationParameters.KeyUsage.HasValue) {
                NCryptNative.SetProperty(keyHandle,
                                         NCryptNative.KeyPropertyName.KeyUsage,
                                         (int)creationParameters.KeyUsage.Value,
                                         CngPropertyOptions.Persist);
            }

            if (creationParameters.ParentWindowHandle != IntPtr.Zero) {
                NCryptNative.SetProperty(keyHandle,
                                         NCryptNative.KeyPropertyName.ParentWindowHandle,
                                         creationParameters.ParentWindowHandle,
                                         CngPropertyOptions.None);
            }

            if (creationParameters.UIPolicy != null) {
                NCryptNative.NCRYPT_UI_POLICY uiPolicy = new NCryptNative.NCRYPT_UI_POLICY();
                uiPolicy.dwVersion = 1;
                uiPolicy.dwFlags = creationParameters.UIPolicy.ProtectionLevel;
                uiPolicy.pszCreationTitle = creationParameters.UIPolicy.CreationTitle;
                uiPolicy.pszFriendlyName = creationParameters.UIPolicy.FriendlyName;
                uiPolicy.pszDescription = creationParameters.UIPolicy.Description;

                NCryptNative.SetProperty(keyHandle,
                                         NCryptNative.KeyPropertyName.UIPolicy,
                                         uiPolicy,
                                         CngPropertyOptions.Persist);

                // The use context is a seperate property from the standard UI context
                if (creationParameters.UIPolicy.UseContext != null) {
                    NCryptNative.SetProperty(keyHandle,
                                             NCryptNative.KeyPropertyName.UseContext,
                                             creationParameters.UIPolicy.UseContext,
                                             CngPropertyOptions.Persist);
                }
            }

            // Iterate over the custom properties, setting those as well.
            foreach (CngProperty property in creationParameters.ParametersNoDemand) {
                NCryptNative.SetProperty(keyHandle, property.Name, property.Value, property.Options);
            }
        }
Exemple #28
0
 public static CngKey Open(SafeNCryptKeyHandle keyHandle, CngKeyHandleOpenOptions keyHandleOpenOptions) {
     throw new NotImplementedException ();
 }
Exemple #29
0
        public static void SafeNCryptKeyHandle_ValidKey_ParentHandle_KeptAlive()
        {
            // NCryptFreeObject will check dwMagic values to determine what kind of object
            // it was given.  Since we don't really want to leak a key in this test we'll
            // track a test-local buffer.
            IntPtr fakeKeyPtr = Marshal.AllocHGlobal(512);
            try
            {
                Marshal.WriteInt32(fakeKeyPtr, 0);

                using (SafeHandle parentHandle = new StateInformingSafeHandle())
                {
                    using (var keyHandle = new SafeNCryptKeyHandle(fakeKeyPtr, parentHandle))
                    {
                        Assert.False(parentHandle.IsInvalid, "After ctor, parentHandle.IsInvalid");
                        Assert.False(parentHandle.IsClosed, "After ctor, parentHandle.IsClosed");

                        parentHandle.Dispose();

                        Assert.False(parentHandle.IsInvalid, "After parentHandle.Dispose, parentHandle.IsInvalid");
                        Assert.False(parentHandle.IsClosed, "After parentHandle.Dispose, parentHandle.IsClosed");
                    }

                    Assert.True(parentHandle.IsInvalid, "After keyHandle.Dispose, parentHandle.IsInvalid");
                    Assert.True(parentHandle.IsClosed, "After keyHandle.Dispose, parentHandle.IsClosed");
                }
            }
            finally
            {
                Marshal.FreeHGlobal(fakeKeyPtr);
            }
        }
Exemple #30
0
        private static SafeNCryptKeyHandle TryAcquireCngPrivateKey(
            SafeCertContextHandle certificateContext,
            out CngKeyHandleOpenOptions handleOptions)
        {
            Debug.Assert(certificateContext != null, "certificateContext != null");
            Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid,
                         "!certificateContext.IsClosed && !certificateContext.IsInvalid");

            IntPtr privateKeyPtr;

            // If the certificate has a key handle instead of a key prov info, return the
            // ephemeral key
            {
                int cbData = IntPtr.Size;

                if (Interop.crypt32.CertGetCertificateContextProperty(
                        certificateContext,
                        CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID,
                        out privateKeyPtr,
                        ref cbData))
                {
                    handleOptions = CngKeyHandleOpenOptions.EphemeralKey;
                    return(new SafeNCryptKeyHandle(privateKeyPtr, certificateContext));
                }
            }

            bool freeKey = true;
            SafeNCryptKeyHandle privateKey = null;

            handleOptions = CngKeyHandleOpenOptions.None;
            try
            {
                int keySpec = 0;
                if (!Interop.crypt32.CryptAcquireCertificatePrivateKey(
                        certificateContext,
                        CryptAcquireFlags.CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG,
                        IntPtr.Zero,
                        out privateKey,
                        out keySpec,
                        out freeKey))
                {
                    int dwErrorCode = Marshal.GetLastWin32Error();

                    // The documentation for CryptAcquireCertificatePrivateKey says that freeKey
                    // should already be false if "key acquisition fails", and it can be presumed
                    // that privateKey was set to 0.  But, just in case:
                    freeKey = false;
                    privateKey?.SetHandleAsInvalid();
                    return(null);
                }

                // It is very unlikely that Windows will tell us !freeKey other than when reporting failure,
                // because we set neither CRYPT_ACQUIRE_CACHE_FLAG nor CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, which are
                // currently the only two success situations documented. However, any !freeKey response means the
                // key's lifetime is tied to that of the certificate, so re-register the handle as a child handle
                // of the certificate.
                if (!freeKey && privateKey != null && !privateKey.IsInvalid)
                {
                    var newKeyHandle = new SafeNCryptKeyHandle(privateKey.DangerousGetHandle(), certificateContext);
                    privateKey.SetHandleAsInvalid();
                    privateKey = newKeyHandle;
                    freeKey    = true;
                }

                return(privateKey);
            }
            catch
            {
                // If we aren't supposed to free the key, and we're not returning it,
                // just tell the SafeHandle to not free itself.
                if (privateKey != null && !freeKey)
                {
                    privateKey.SetHandleAsInvalid();
                }

                return(null);
            }
        }
        //
        // 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;
        }
Exemple #32
0
        /// <summary>
        ///     Setup the UIPolicy key properties specified in the key creation parameters
        /// </summary>
        private static void InitializeKeyUiPolicyProperties(SafeNCryptKeyHandle keyHandle, CngUIPolicy uiPolicy)
        {
            unsafe
            {
                fixed (char* pinnedCreationTitle = uiPolicy.CreationTitle, 
                             pinnedFriendlyName = uiPolicy.FriendlyName,
                             pinnedDescription = uiPolicy.Description)
                {
                    NCRYPT_UI_POLICY ncryptUiPolicy = new NCRYPT_UI_POLICY()
                    {
                        dwVersion = 1,
                        dwFlags = uiPolicy.ProtectionLevel,
                        pszCreationTitle = new IntPtr(pinnedCreationTitle),
                        pszFriendlyName = new IntPtr(pinnedFriendlyName),
                        pszDescription = new IntPtr(pinnedDescription),
                    };

                    ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.UIPolicy, &ncryptUiPolicy, sizeof(NCRYPT_UI_POLICY), CngPropertyOptions.Persist);
                    if (errorCode != ErrorCode.ERROR_SUCCESS)
                        throw errorCode.ToCryptographicException();
                }

                string useContext = uiPolicy.UseContext;
                if (useContext != null)
                {
                    int useContextByteLength = checked((useContext.Length + 1) * sizeof(char));
                    fixed (char* pinnedUseContext = useContext)
                    {
                        ErrorCode errorCode = Interop.NCrypt.NCryptSetProperty(keyHandle, KeyPropertyName.UseContext, pinnedUseContext, useContextByteLength, CngPropertyOptions.Persist);
                        if (errorCode != ErrorCode.ERROR_SUCCESS)
                            throw errorCode.ToCryptographicException();
                    }
                }
            }
        }
Exemple #33
0
 internal static extern ErrorCode NCryptFinalizeKey(SafeNCryptKeyHandle hKey, int dwFlags);
Exemple #34
0
 public static partial bool CryptAcquireCertificatePrivateKey(SafeCertContextHandle pCert, CryptAcquireFlags dwFlags, IntPtr pvParameters, out SafeNCryptKeyHandle phCryptProvOrNCryptKey, out int pdwKeySpec, out bool pfCallerFreeProvOrNCryptKey);
Exemple #35
0
 internal static unsafe extern ErrorCode NCryptDecrypt(SafeNCryptKeyHandle hKey, [In] byte[] pbInput, int cbInput, void* pPaddingInfo, [Out] byte[] pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags);
Exemple #36
0
 internal static extern ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, [Out] byte[] pbOutput, int cbOutput, [Out] out int pcbResult, int dwFlags);
Exemple #37
0
 internal static unsafe extern ErrorCode NCryptSignHash(SafeNCryptKeyHandle hKey, void* pPaddingInfo, [In] byte[] pbHashValue, int cbHashValue, [Out] byte[] pbSignature, int cbSignature, out int pcbResult, AsymmetricPaddingMode dwFlags);