Пример #1
0
        private T GetPrivateKey <T>(X509Certificate2 certificate, bool silent, bool preferNCrypt) where T : AsymmetricAlgorithm
        {
            if (!certificate.HasPrivateKey)
            {
                return(null);
            }

            SafeProvOrNCryptKeyHandle handle = GetCertificatePrivateKey(
                certificate,
                silent,
                preferNCrypt,
                out CryptKeySpec keySpec,
                out Exception exception);

            using (handle)
            {
                if (handle == null || handle.IsInvalid)
                {
                    if (exception != null)
                    {
                        throw exception;
                    }

                    return(null);
                }

                if (keySpec == CryptKeySpec.CERT_NCRYPT_KEY_SPEC)
                {
                    using (SafeNCryptKeyHandle keyHandle = new SafeNCryptKeyHandle(handle.DangerousGetHandle(), handle))
                        using (CngKey cngKey = CngKey.Open(keyHandle, CngKeyHandleOpenOptions.None))
                        {
                            if (typeof(T) == typeof(RSA))
                            {
                                return((T)(object)new RSACng(cngKey));
                            }
                            if (typeof(T) == typeof(ECDsa))
                            {
                                return((T)(object)new ECDsaCng(cngKey));
                            }
                            if (typeof(T) == typeof(DSA))
                            {
                                return((T)(object)new DSACng(cngKey));
                            }

                            Debug.Fail($"Unknown CNG key type request: {typeof(T).FullName}");
                            return(null);
                        }
                }

                // The key handle is for CAPI.
                // Our CAPI types don't allow usage from a handle, so we have a few choices:
                // 1) Extract the information we need to re-open the key handle.
                // 2) Re-implement {R|D}SACryptoServiceProvider
                // 3) PNSE.
                // 4) Defer to cert.Get{R|D}SAPrivateKey if not silent, throw otherwise.
                CspParameters cspParams = handle.GetProvParameters();
                Debug.Assert((cspParams.Flags & CspProviderFlags.UseExistingKey) != 0);
                cspParams.KeyNumber = (int)keySpec;

                if (silent)
                {
                    cspParams.Flags |= CspProviderFlags.NoPrompt;
                }

                if (typeof(T) == typeof(RSA))
                {
                    return((T)(object)new RSACryptoServiceProvider(cspParams));
                }
                if (typeof(T) == typeof(DSA))
                {
                    return((T)(object)new DSACryptoServiceProvider(cspParams));
                }

                Debug.Fail($"Unknown CAPI key type request: {typeof(T).FullName}");
                return(null);
            }
        }
Пример #2
0
 internal static extern bool CryptAcquireCertificatePrivateKey(SafeCertContextHandle pCert,
                                                               AcquireCertificateKeyOptions dwFlags,
                                                               IntPtr pvReserved,        // void *
                                                               [Out] out SafeNCryptKeyHandle phCryptProvOrNCryptKey,
                                                               [Out] out int dwKeySpec,
                                                               [Out, MarshalAs(UnmanagedType.Bool)] out bool pfCallerFreeProvOrNCryptKey);
Пример #3
0
 internal static unsafe ErrorCode NCryptSignHash(SafeNCryptKeyHandle hKey, void *pPaddingInfo, ReadOnlySpan <byte> pbHashValue, int cbHashValue, Span <byte> pbSignature, int cbSignature, out int pcbResult, AsymmetricPaddingMode dwFlags) =>
 NCryptSignHash(hKey, pPaddingInfo, ref MemoryMarshal.GetReference(pbHashValue), cbHashValue, ref MemoryMarshal.GetReference(pbSignature), cbSignature, out pcbResult, dwFlags);
Пример #4
0
 internal static extern ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, ref NCryptBufferDesc pParameterList, ref byte pbOutput, int cbOutput, [Out] out int pcbResult, int dwFlags);
Пример #5
0
 internal static extern ErrorCode NCryptFinalizeKey(SafeNCryptKeyHandle hKey, int dwFlags);
Пример #6
0
        public static unsafe bool VerifyHash(this SafeNCryptKeyHandle keyHandle, ReadOnlySpan <byte> hash, ReadOnlySpan <byte> signature, AsymmetricPaddingMode paddingMode, void *pPaddingInfo)
        {
            ErrorCode errorCode = Interop.NCrypt.NCryptVerifySignature(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, paddingMode);

            return(errorCode == ErrorCode.ERROR_SUCCESS);  // For consistency with other AsymmetricAlgorithm-derived classes, return "false" for any error code rather than making the caller catch an exception.
        }
Пример #7
0
 internal static extern ErrorCode NCryptOpenKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszKeyName, int dwLegacyKeySpec, CngKeyOpenOptions dwFlags);
 internal static extern NCryptNative.ErrorCode NCryptVerifySignature(SafeNCryptKeyHandle hKey, IntPtr pPaddingInfo, [MarshalAs(UnmanagedType.LPArray)] byte[] pbHashValue, int cbHashValue, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSignature, int cbSignature, int dwFlags);
Пример #9
0
        private T GetPrivateKey <T>(X509Certificate2 certificate, bool silent, bool preferNCrypt) where T : AsymmetricAlgorithm
        {
            if (!certificate.HasPrivateKey)
            {
                return(null);
            }

            SafeProvOrNCryptKeyHandle handle = GetCertificatePrivateKey(
                certificate,
                silent,
                preferNCrypt,
                out CryptKeySpec keySpec,
                out Exception exception);

            using (handle)
            {
                if (handle == null || handle.IsInvalid)
                {
                    if (exception != null)
                    {
                        throw exception;
                    }

                    return(null);
                }

                if (keySpec == CryptKeySpec.CERT_NCRYPT_KEY_SPEC)
                {
                    using (SafeNCryptKeyHandle keyHandle = new SafeNCryptKeyHandle(handle.DangerousGetHandle(), handle))
                    {
                        CngKeyHandleOpenOptions options    = CngKeyHandleOpenOptions.None;
                        byte clrIsEphemeral                = 0;
                        Interop.NCrypt.ErrorCode errorCode = Interop.NCrypt.NCryptGetByteProperty(keyHandle, "CLR IsEphemeral", ref clrIsEphemeral, CngPropertyOptions.CustomProperty);

                        if (errorCode == Interop.NCrypt.ErrorCode.ERROR_SUCCESS && clrIsEphemeral == 1)
                        {
                            options |= CngKeyHandleOpenOptions.EphemeralKey;
                        }

                        using (CngKey cngKey = CngKey.Open(keyHandle, options))
                        {
                            if (typeof(T) == typeof(RSA))
                            {
                                return((T)(object)new RSACng(cngKey));
                            }
                            if (typeof(T) == typeof(ECDsa))
                            {
                                return((T)(object)new ECDsaCng(cngKey));
                            }
                            if (typeof(T) == typeof(DSA))
                            {
                                return((T)(object)new DSACng(cngKey));
                            }

                            Debug.Fail($"Unknown CNG key type request: {typeof(T).FullName}");
                            return(null);
                        }
                    }
                }

                // The key handle is for CAPI.
                // Our CAPI types don't allow usage from a handle, so we have a few choices:
                // 1) Extract the information we need to re-open the key handle.
                // 2) Re-implement {R|D}SACryptoServiceProvider
                // 3) PNSE.
                // 4) Defer to cert.Get{R|D}SAPrivateKey if not silent, throw otherwise.
                CspParameters cspParams;

                try
                {
                    cspParams = handle.GetProvParameters();
                }
                catch (CryptographicException)
                {
                    // begin: gost
                    // - если пытаемся загрузить сертификат в non-persist попадём сюда
                    // зовём функции x509, которые умеют работать с такими ключами
                    if (typeof(T) == typeof(Gost3410))
                    {
                        return((T)(object)certificate.GetGost3410PrivateKey());
                    }
                    if (typeof(T) == typeof(Gost3410_2012_256))
                    {
                        return((T)(object)certificate.GetGost3410_2012_256PrivateKey());
                    }
                    if (typeof(T) == typeof(Gost3410_2012_512))
                    {
                        return((T)(object)certificate.GetGost3410_2012_512PrivateKey());
                    }
                    throw;
                    // end: gost
                }
                Debug.Assert((cspParams.Flags & CspProviderFlags.UseExistingKey) != 0);
                cspParams.KeyNumber = (int)keySpec;

                if (silent)
                {
                    cspParams.Flags |= CspProviderFlags.NoPrompt;
                }

                if (typeof(T) == typeof(RSA))
                {
                    return((T)(object)new RSACryptoServiceProvider(cspParams));
                }
                if (typeof(T) == typeof(DSA))
                {
                    return((T)(object)new DSACryptoServiceProvider(cspParams));
                }
                //begin: gost
                if (typeof(T) == typeof(Gost3410))
                {
                    return((T)(object)new Gost3410CryptoServiceProvider(cspParams));
                }
                if (typeof(T) == typeof(Gost3410_2012_256))
                {
                    return((T)(object)new Gost3410_2012_256CryptoServiceProvider(cspParams));
                }
                if (typeof(T) == typeof(Gost3410_2012_512))
                {
                    return((T)(object)new Gost3410_2012_512CryptoServiceProvider(cspParams));
                }
                //end: gost

                Debug.Fail($"Unknown CAPI key type request: {typeof(T).FullName}");
                return(null);
            }
        }
 internal static extern NCryptNative.ErrorCode NCryptImportKey(SafeNCryptProviderHandle hProvider, IntPtr hImportKey, string pszBlobType, IntPtr pParameterList, out SafeNCryptKeyHandle phKey, [MarshalAs(UnmanagedType.LPArray)] byte[] pbData, int cbData, int dwFlags);
 internal static extern NCryptNative.ErrorCode NCryptSecretAgreement(SafeNCryptKeyHandle hPrivKey, SafeNCryptKeyHandle hPubKey, out SafeNCryptSecretHandle phSecret, int dwFlags);
 internal static extern NCryptNative.ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbOutput, int cbOutput, out int pcbResult, int dwFlags);
 internal static extern NCryptNative.ErrorCode NCryptDeleteKey(SafeNCryptKeyHandle hKey, int flags);
        internal static SafeNCryptSecretHandle DeriveSecretAgreement(SafeNCryptKeyHandle privateKey, SafeNCryptKeyHandle otherPartyPublicKey)
        {
            SafeNCryptSecretHandle handle;
            ErrorCode code = UnsafeNativeMethods.NCryptSecretAgreement(privateKey, otherPartyPublicKey, out handle, 0);

            if (code != ErrorCode.Success)
            {
                throw new CryptographicException((int)code);
            }
            return(handle);
        }
Пример #15
0
 public static extern uint NCryptSecretAgreement(SafeNCryptKeyHandle hPrivKey, SafeNCryptKeyHandle hPublicKey, out SafeNCryptSecretHandle phSecret, uint flags);
Пример #16
0
        public byte[] DeriveKeyMaterial(CngKey otherPartyPublicKey)
        {
            Contract.Ensures(Contract.Result <byte[]>() != null);
            Contract.Assert(m_kdf >= ECDiffieHellmanKeyDerivationFunction.Hash &&
                            m_kdf <= ECDiffieHellmanKeyDerivationFunction.Tls);

            if (otherPartyPublicKey == null)
            {
                throw new ArgumentNullException("otherPartyPublicKey");
            }
            if (otherPartyPublicKey.AlgorithmGroup != CngAlgorithmGroup.ECDiffieHellman)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHRequiresECDHKey), "otherPartyPublicKey");
            }
            if (otherPartyPublicKey.KeySize != KeySize)
            {
                throw new ArgumentException(SR.GetString(SR.Cryptography_ArgECDHKeySizeMismatch), "otherPartyPublicKey");
            }

            NCryptNative.SecretAgreementFlags flags =
                UseSecretAgreementAsHmacKey ? NCryptNative.SecretAgreementFlags.UseSecretAsHmacKey : NCryptNative.SecretAgreementFlags.None;

            // We require access to the handles for generating key material. This is safe since we will never
            // expose these handles to user code
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();

            // This looks horribly wrong - but accessing the handle property actually returns a duplicate handle, which
            // we need to dispose of - otherwise, we're stuck keepign the resource alive until the GC runs.  This explicitly
            // is not disposing of the handle underlying the key dispite what the syntax looks like.
            using (SafeNCryptKeyHandle localKey = Key.Handle)
                using (SafeNCryptKeyHandle otherKey = otherPartyPublicKey.Handle) {
                    CodeAccessPermission.RevertAssert();

                    //
                    // Generating key material is a two phase process.
                    //   1. Generate the secret agreement
                    //   2. Pass the secret agreement through a KDF to get key material
                    //

                    using (SafeNCryptSecretHandle secretAgreement = NCryptNative.DeriveSecretAgreement(localKey, otherKey)) {
                        if (KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Hash)
                        {
                            byte[] secretAppend  = SecretAppend == null ? null : SecretAppend.Clone() as byte[];
                            byte[] secretPrepend = SecretPrepend == null ? null : SecretPrepend.Clone() as byte[];

                            return(NCryptNative.DeriveKeyMaterialHash(secretAgreement,
                                                                      HashAlgorithm.Algorithm,
                                                                      secretPrepend,
                                                                      secretAppend,
                                                                      flags));
                        }
                        else if (KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Hmac)
                        {
                            byte[] hmacKey       = HmacKey == null ? null : HmacKey.Clone() as byte[];
                            byte[] secretAppend  = SecretAppend == null ? null : SecretAppend.Clone() as byte[];
                            byte[] secretPrepend = SecretPrepend == null ? null : SecretPrepend.Clone() as byte[];

                            return(NCryptNative.DeriveKeyMaterialHmac(secretAgreement,
                                                                      HashAlgorithm.Algorithm,
                                                                      hmacKey,
                                                                      secretPrepend,
                                                                      secretAppend,
                                                                      flags));
                        }
                        else
                        {
                            Debug.Assert(KeyDerivationFunction == ECDiffieHellmanKeyDerivationFunction.Tls, "Unknown KDF");

                            byte[] label = Label == null ? null : Label.Clone() as byte[];
                            byte[] seed  = Seed == null ? null : Seed.Clone() as byte[];

                            if (label == null || seed == null)
                            {
                                throw new InvalidOperationException(SR.GetString(SR.Cryptography_TlsRequiresLabelAndSeed));
                            }

                            return(NCryptNative.DeriveKeyMaterialTls(secretAgreement, label, seed, flags));
                        }
                    }
                }
        }
Пример #17
0
        internal static unsafe bool ExportPkcs8KeyBlob(
            bool allocate,
            SafeNCryptKeyHandle keyHandle,
            ReadOnlySpan <char> password,
            int kdfCount,
            Span <byte> destination,
            out int bytesWritten,
            out byte[] allocated)
        {
            using (SafeUnicodeStringHandle stringHandle = new SafeUnicodeStringHandle(password))
            {
                fixed(byte *oidPtr = s_pkcs12TripleDesOidBytes)
                {
                    Interop.NCrypt.NCryptBuffer *buffers = stackalloc Interop.NCrypt.NCryptBuffer[3];

                    Interop.NCrypt.PBE_PARAMS pbeParams = default;
                    Span <byte> salt = new Span <byte>(pbeParams.rgbSalt, Interop.NCrypt.PBE_PARAMS.RgbSaltSize);

                    RandomNumberGenerator.Fill(salt);
                    pbeParams.Params.cbSalt      = salt.Length;
                    pbeParams.Params.iIterations = kdfCount;

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

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

                    buffers[1] = new Interop.NCrypt.NCryptBuffer
                    {
                        BufferType = Interop.NCrypt.BufferType.PkcsAlgOid,
                        cbBuffer   = s_pkcs12TripleDesOidBytes.Length,
                        pvBuffer   = (IntPtr)oidPtr,
                    };

                    buffers[2] = new Interop.NCrypt.NCryptBuffer
                    {
                        BufferType = Interop.NCrypt.BufferType.PkcsAlgParam,
                        cbBuffer   = sizeof(Interop.NCrypt.PBE_PARAMS),
                        pvBuffer   = (IntPtr)(&pbeParams),
                    };

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

                    Span <byte> empty = default;

                    ErrorCode errorCode = Interop.NCrypt.NCryptExportKey(
                        keyHandle,
                        IntPtr.Zero,
                        Interop.NCrypt.NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
                        ref desc,
                        ref MemoryMarshal.GetReference(empty),
                        0,
                        out int numBytesNeeded,
                        0);

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

                    allocated = null;

                    if (allocate)
                    {
                        allocated   = new byte[numBytesNeeded];
                        destination = allocated;
                    }
                    else if (numBytesNeeded > destination.Length)
                    {
                        bytesWritten = 0;
                        return(false);
                    }

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

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

                    if (allocate && numBytesNeeded != destination.Length)
                    {
                        byte[] trimmed = new byte[numBytesNeeded];
                        destination.Slice(0, numBytesNeeded).CopyTo(trimmed);
                        Array.Clear(allocated, 0, numBytesNeeded);
                        allocated = trimmed;
                    }

                    bytesWritten = numBytesNeeded;
                    return(true);
                }
            }
        }
Пример #18
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 without a key prov info, return the
            // ephemeral key
            if (!certificateContext.HasPersistedPrivateKey)
            {
                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();
                }

                throw;
            }
        }
 internal static unsafe partial bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, SafeNCryptKeyHandle keyHandle);
Пример #20
0
 public static CngKey Open(SafeNCryptKeyHandle keyHandle !!, CngKeyHandleOpenOptions keyHandleOpenOptions)
Пример #21
0
 internal static extern ErrorCode NCryptImportKey(SafeNCryptProviderHandle hProvider, IntPtr hImportKey, string pszBlobType, ref NCryptBufferDesc pParameterList, [Out] out SafeNCryptKeyHandle phKey, ref byte pbData, int cbData, int dwFlags);
Пример #22
0
        /// <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);
        }
Пример #23
0
 internal static extern ErrorCode NCryptCreatePersistedKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszAlgId, string?pszKeyName, int dwLegacyKeySpec, CngKeyCreationOptions dwFlags);
Пример #24
0
 internal static partial ErrorCode NCryptImportKey(SafeNCryptProviderHandle hProvider, IntPtr hImportKey, string pszBlobType, IntPtr pParameterList, out SafeNCryptKeyHandle phKey, ref byte pbData, int cbData, int dwFlags);
Пример #25
0
 internal static extern SafeCertContextHandle CertCreateSelfSignCertificate(SafeNCryptKeyHandle hCryptProvOrNCryptKey,
                                                                            [In] ref CapiNative.CRYPTOAPI_BLOB pSubjectIssuerBlob,
                                                                            X509CertificateCreationOptions dwFlags,
                                                                            [In] ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
                                                                            [In] ref CapiNative.CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
                                                                            [In] ref Win32Native.SYSTEMTIME pStartTime,
                                                                            [In] ref Win32Native.SYSTEMTIME pEndTime,
                                                                            [In] ref CERT_EXTENSIONS pExtensions);
Пример #26
0
 internal static partial ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, ref byte pbOutput, int cbOutput, out int pcbResult, int dwFlags);
Пример #27
0
        internal static SafeCertContextHandle CreateSelfSignedCertificate(CngKey key,
                                                                          bool takeOwnershipOfKey,
                                                                          byte[] subjectName,
                                                                          X509CertificateCreationOptions creationOptions,
                                                                          string signatureAlgorithmOid,
                                                                          DateTime startTime,
                                                                          DateTime endTime,
                                                                          X509ExtensionCollection extensions)
        {
            Debug.Assert(key != null, "key != null");
            Debug.Assert(subjectName != null, "subjectName != null");
            Debug.Assert(!String.IsNullOrEmpty(signatureAlgorithmOid), "!String.IsNullOrEmpty(signatureAlgorithmOid)");
            Debug.Assert(extensions != null, "extensions != null");

            // Create an algorithm identifier structure for the signature algorithm
            CapiNative.CRYPT_ALGORITHM_IDENTIFIER nativeSignatureAlgorithm = new CapiNative.CRYPT_ALGORITHM_IDENTIFIER();
            nativeSignatureAlgorithm.pszObjId          = signatureAlgorithmOid;
            nativeSignatureAlgorithm.Parameters        = new CapiNative.CRYPTOAPI_BLOB();
            nativeSignatureAlgorithm.Parameters.cbData = 0;
            nativeSignatureAlgorithm.Parameters.pbData = IntPtr.Zero;

            // Convert the begin and expire dates to system time structures
            Win32Native.SYSTEMTIME nativeStartTime = new Win32Native.SYSTEMTIME(startTime);
            Win32Native.SYSTEMTIME nativeEndTime   = new Win32Native.SYSTEMTIME(endTime);

            // Map the extensions into CERT_EXTENSIONS.  This involves several steps to get the
            // CERT_EXTENSIONS ready for interop with the native APIs.
            //   1. Build up the CERT_EXTENSIONS structure in managed code
            //   2. For each extension, create a managed CERT_EXTENSION structure; this requires allocating
            //      native memory for the blob pointer in the CERT_EXTENSION. These extensions are stored in
            //      the nativeExtensionArray variable.
            //   3. Get a block of native memory that can hold a native array of CERT_EXTENSION structures.
            //      This is the block referenced by the CERT_EXTENSIONS structure.
            //   4. For each of the extension structures created in step 2, marshal the extension into the
            //      native buffer allocated in step 3.
            CERT_EXTENSIONS nativeExtensions = new CERT_EXTENSIONS();

            nativeExtensions.cExtension = extensions.Count;
            CERT_EXTENSION[] nativeExtensionArray = new CERT_EXTENSION[extensions.Count];

            // Run this in a CER to ensure that we release any native memory allocated for the certificate
            // extensions.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                // Copy over each extension into a native extension structure, including allocating native
                // memory for its blob if necessary.
                for (int i = 0; i < extensions.Count; ++i)
                {
                    nativeExtensionArray[i]           = new CERT_EXTENSION();
                    nativeExtensionArray[i].pszObjId  = extensions[i].Oid.Value;
                    nativeExtensionArray[i].fCritical = extensions[i].Critical;

                    nativeExtensionArray[i].Value        = new CapiNative.CRYPTOAPI_BLOB();
                    nativeExtensionArray[i].Value.cbData = extensions[i].RawData.Length;
                    if (nativeExtensionArray[i].Value.cbData > 0)
                    {
                        nativeExtensionArray[i].Value.pbData =
                            Marshal.AllocCoTaskMem(nativeExtensionArray[i].Value.cbData);
                        Marshal.Copy(extensions[i].RawData,
                                     0,
                                     nativeExtensionArray[i].Value.pbData,
                                     nativeExtensionArray[i].Value.cbData);
                    }
                }

                // Now that we've built up the extension array, create a block of native memory to marshal
                // them into.
                if (nativeExtensionArray.Length > 0)
                {
                    checked
                    {
                        // CERT_EXTENSION structures end with a pointer field, which means on all supported
                        // platforms they won't require any padding between elements of the array.
                        nativeExtensions.rgExtension =
                            Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(CERT_EXTENSION)) * nativeExtensionArray.Length);

                        for (int i = 0; i < nativeExtensionArray.Length; ++i)
                        {
                            ulong  offset            = (uint)i * (uint)Marshal.SizeOf(typeof(CERT_EXTENSION));
                            ulong  next              = offset + (ulong)nativeExtensions.rgExtension.ToInt64();
                            IntPtr nextExtensionAddr = new IntPtr((long)next);

                            Marshal.StructureToPtr(nativeExtensionArray[i], nextExtensionAddr, false);
                        }
                    }
                }

                // Setup a CRYPT_KEY_PROV_INFO for the key
                CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();
                keyProvInfo.pwszContainerName = key.UniqueName;
                keyProvInfo.pwszProvName      = key.Provider.Provider;
                keyProvInfo.dwProvType        = 0; // NCRYPT
                keyProvInfo.dwFlags           = 0;
                keyProvInfo.cProvParam        = 0;
                keyProvInfo.rgProvParam       = IntPtr.Zero;
                keyProvInfo.dwKeySpec         = 0;

                //
                // Now that all of the needed data structures are setup, we can create the certificate
                //

                SafeCertContextHandle selfSignedCertHandle = null;
                unsafe
                {
                    fixed(byte *pSubjectName = &subjectName[0])
                    {
                        // Create a CRYPTOAPI_BLOB for the subject of the cert
                        CapiNative.CRYPTOAPI_BLOB nativeSubjectName = new CapiNative.CRYPTOAPI_BLOB();
                        nativeSubjectName.cbData = subjectName.Length;
                        nativeSubjectName.pbData = new IntPtr(pSubjectName);

                        // Now that we've converted all the inputs to native data structures, we can generate
                        // the self signed certificate for the input key.
                        using (SafeNCryptKeyHandle keyHandle = key.Handle)
                        {
                            selfSignedCertHandle =
                                UnsafeNativeMethods.CertCreateSelfSignCertificate(keyHandle,
                                                                                  ref nativeSubjectName,
                                                                                  creationOptions,
                                                                                  ref keyProvInfo,
                                                                                  ref nativeSignatureAlgorithm,
                                                                                  ref nativeStartTime,
                                                                                  ref nativeEndTime,
                                                                                  ref nativeExtensions);
                            if (selfSignedCertHandle.IsInvalid)
                            {
                                throw new CryptographicException(Marshal.GetLastWin32Error());
                            }
                        }
                    }
                }

                Debug.Assert(selfSignedCertHandle != null, "selfSignedCertHandle != null");

                // Attach a key context to the certificate which will allow Windows to find the private key
                // associated with the certificate if the NCRYPT_KEY_HANDLE is ephemeral.
                // is done.
                using (SafeNCryptKeyHandle keyHandle = key.Handle)
                {
                    CERT_KEY_CONTEXT keyContext = new CERT_KEY_CONTEXT();
                    keyContext.cbSize     = Marshal.SizeOf(typeof(CERT_KEY_CONTEXT));
                    keyContext.hNCryptKey = keyHandle.DangerousGetHandle();
                    keyContext.dwKeySpec  = KeySpec.NCryptKey;

                    bool attachedProperty = false;
                    int  setContextError  = 0;

                    // Run in a CER to ensure accurate tracking of the transfer of handle ownership
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try { }
                    finally
                    {
                        CertificatePropertySetFlags flags = CertificatePropertySetFlags.None;
                        if (!takeOwnershipOfKey)
                        {
                            // If the certificate is not taking ownership of the key handle, then it should
                            // not release the handle when the context is released.
                            flags |= CertificatePropertySetFlags.NoCryptRelease;
                        }

                        attachedProperty =
                            UnsafeNativeMethods.CertSetCertificateContextProperty(selfSignedCertHandle,
                                                                                  CertificateProperty.KeyContext,
                                                                                  flags,
                                                                                  ref keyContext);
                        setContextError = Marshal.GetLastWin32Error();

                        // If we succesfully transferred ownership of the key to the certificate,
                        // then we need to ensure that we no longer release its handle.
                        if (attachedProperty && takeOwnershipOfKey)
                        {
                            keyHandle.SetHandleAsInvalid();
                        }
                    }

                    if (!attachedProperty)
                    {
                        throw new CryptographicException(setContextError);
                    }
                }

                return(selfSignedCertHandle);
            }
            finally
            {
                //
                // In order to release all resources held by the CERT_EXTENSIONS we need to do three things
                //   1. Destroy each structure marshaled into the native CERT_EXTENSION array
                //   2. Release the memory used for the CERT_EXTENSION array
                //   3. Release the memory used in each individual CERT_EXTENSION
                //

                // Release each extension marshaled into the native buffer as well
                if (nativeExtensions.rgExtension != IntPtr.Zero)
                {
                    for (int i = 0; i < nativeExtensionArray.Length; ++i)
                    {
                        ulong  offset            = (uint)i * (uint)Marshal.SizeOf(typeof(CERT_EXTENSION));
                        ulong  next              = offset + (ulong)nativeExtensions.rgExtension.ToInt64();
                        IntPtr nextExtensionAddr = new IntPtr((long)next);

                        Marshal.DestroyStructure(nextExtensionAddr, typeof(CERT_EXTENSION));
                    }

                    Marshal.FreeCoTaskMem(nativeExtensions.rgExtension);
                }

                // If we allocated memory for any extensions, make sure to free it now
                for (int i = 0; i < nativeExtensionArray.Length; ++i)
                {
                    if (nativeExtensionArray[i].Value.pbData != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(nativeExtensionArray[i].Value.pbData);
                    }
                }
            }
        }
Пример #28
0
 internal static partial ErrorCode NCryptDeleteKey(SafeNCryptKeyHandle hKey, int dwFlags);
Пример #29
0
 private static unsafe partial ErrorCode NCryptSignHash(SafeNCryptKeyHandle hKey, void *pPaddingInfo, ref byte pbHashValue, int cbHashValue, ref byte pbSignature, int cbSignature, out int pcbResult, AsymmetricPaddingMode dwFlags);
Пример #30
0
 private static extern ErrorCode NCryptSecretAgreement(
     SafeNCryptKeyHandle hPrivKey,
     SafeNCryptKeyHandle hPubKey,
     [Out] out SafeNCryptSecretHandle phSecret,
     int dwFlags);