Esempio n. 1
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);
        }
Esempio n. 2
0
            OpenNCryptProvider("Microsoft Software Key Storage Provider"); // MS_KEY_STORAGE_PROVIDER

        internal static unsafe SafeNCryptKeyHandle ImportKeyBlob(
            string blobType,
            ReadOnlySpan <byte> keyBlob,
            bool encrypted = false,
            ReadOnlySpan <char> password = default)
        {
            SafeNCryptKeyHandle keyHandle;
            ErrorCode           errorCode;

            if (encrypted)
            {
                using (var stringHandle = 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   = stringHandle.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 = Interop.NCrypt.NCryptImportKey(
                        s_microsoftSoftwareProviderHandle,
                        IntPtr.Zero,
                        blobType,
                        ref desc,
                        out keyHandle,
                        ref MemoryMarshal.GetReference(keyBlob),
                        keyBlob.Length,
                        0);
                }
            }
            else
            {
                errorCode = Interop.NCrypt.NCryptImportKey(
                    s_microsoftSoftwareProviderHandle,
                    IntPtr.Zero,
                    blobType,
                    IntPtr.Zero,
                    out keyHandle,
                    ref MemoryMarshal.GetReference(keyBlob),
                    keyBlob.Length,
                    0);
            }

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

            Debug.Assert(keyHandle != null);

            SetExportable(keyHandle);
            return(keyHandle);
        }
Esempio n. 3
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);
                        CryptographicOperations.ZeroMemory(allocated.AsSpan(0, numBytesNeeded));
                        allocated = trimmed;
                    }

                    bytesWritten = numBytesNeeded;
                    return(true);
                }
            }
        }