summaryrefslogtreecommitdiff
path: root/src/classlibnative/cryptography
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2016-03-16 16:04:10 -0700
committerJan Kotas <jkotas@microsoft.com>2016-03-16 16:04:10 -0700
commitba19076843e369ac6be89e634bcaf5947b6a94c7 (patch)
tree986f1397a726d1e2f8f9cdc62342562d7ddf005c /src/classlibnative/cryptography
parent414126e0c0e9d1681b2fe3f71789ef1bbc743a76 (diff)
downloadcoreclr-ba19076843e369ac6be89e634bcaf5947b6a94c7.tar.gz
coreclr-ba19076843e369ac6be89e634bcaf5947b6a94c7.tar.bz2
coreclr-ba19076843e369ac6be89e634bcaf5947b6a94c7.zip
Remove unused files from CoreCLR
[tfs-changeset: 1586532]
Diffstat (limited to 'src/classlibnative/cryptography')
-rw-r--r--src/classlibnative/cryptography/.gitmirror1
-rw-r--r--src/classlibnative/cryptography/CMakeLists.txt6
-rw-r--r--src/classlibnative/cryptography/cryptography.cpp3370
-rw-r--r--src/classlibnative/cryptography/cryptography.h521
-rw-r--r--src/classlibnative/cryptography/cryptography.nativeproj36
-rw-r--r--src/classlibnative/cryptography/x509certificate.cpp1340
-rw-r--r--src/classlibnative/cryptography/x509certificate.h165
7 files changed, 0 insertions, 5439 deletions
diff --git a/src/classlibnative/cryptography/.gitmirror b/src/classlibnative/cryptography/.gitmirror
deleted file mode 100644
index f507630f94..0000000000
--- a/src/classlibnative/cryptography/.gitmirror
+++ /dev/null
@@ -1 +0,0 @@
-Only contents of this folder, excluding subfolders, will be mirrored by the Git-TFS Mirror. \ No newline at end of file
diff --git a/src/classlibnative/cryptography/CMakeLists.txt b/src/classlibnative/cryptography/CMakeLists.txt
deleted file mode 100644
index 10c899f7f8..0000000000
--- a/src/classlibnative/cryptography/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-set( COMCRYPT_WKS_SOURCES
- Cryptography.cpp
- X509Certificate.cpp
-)
-
-add_library_clr( comcrypt_wks ${COMCRYPT_WKS_SOURCES})
diff --git a/src/classlibnative/cryptography/cryptography.cpp b/src/classlibnative/cryptography/cryptography.cpp
deleted file mode 100644
index 7851496d52..0000000000
--- a/src/classlibnative/cryptography/cryptography.cpp
+++ /dev/null
@@ -1,3370 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-//
-// File: Cryptography.cpp
-//
-
-//
-// Native method implementations and helper code for supporting CAPI based operations
-//---------------------------------------------------------------------------
-
-
-
-#include "common.h"
-
-#include "field.h"
-#include "cryptography.h"
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-const BYTE g_rgbPrivKey[] =
-{
- 0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00,
- 0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0xAB, 0xEF, 0xFA, 0xC6,
- 0x7D, 0xE8, 0xDE, 0xFB, 0x68, 0x38, 0x09, 0x92,
- 0xD9, 0x42, 0x7E, 0x6B, 0x89, 0x9E, 0x21, 0xD7,
- 0x52, 0x1C, 0x99, 0x3C, 0x17, 0x48, 0x4E, 0x3A,
- 0x44, 0x02, 0xF2, 0xFA, 0x74, 0x57, 0xDA, 0xE4,
- 0xD3, 0xC0, 0x35, 0x67, 0xFA, 0x6E, 0xDF, 0x78,
- 0x4C, 0x75, 0x35, 0x1C, 0xA0, 0x74, 0x49, 0xE3,
- 0x20, 0x13, 0x71, 0x35, 0x65, 0xDF, 0x12, 0x20,
- 0xF5, 0xF5, 0xF5, 0xC1, 0xED, 0x5C, 0x91, 0x36,
- 0x75, 0xB0, 0xA9, 0x9C, 0x04, 0xDB, 0x0C, 0x8C,
- 0xBF, 0x99, 0x75, 0x13, 0x7E, 0x87, 0x80, 0x4B,
- 0x71, 0x94, 0xB8, 0x00, 0xA0, 0x7D, 0xB7, 0x53,
- 0xDD, 0x20, 0x63, 0xEE, 0xF7, 0x83, 0x41, 0xFE,
- 0x16, 0xA7, 0x6E, 0xDF, 0x21, 0x7D, 0x76, 0xC0,
- 0x85, 0xD5, 0x65, 0x7F, 0x00, 0x23, 0x57, 0x45,
- 0x52, 0x02, 0x9D, 0xEA, 0x69, 0xAC, 0x1F, 0xFD,
- 0x3F, 0x8C, 0x4A, 0xD0,
-
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
- 0x64, 0xD5, 0xAA, 0xB1,
- 0xA6, 0x03, 0x18, 0x92, 0x03, 0xAA, 0x31, 0x2E,
- 0x48, 0x4B, 0x65, 0x20, 0x99, 0xCD, 0xC6, 0x0C,
- 0x15, 0x0C, 0xBF, 0x3E, 0xFF, 0x78, 0x95, 0x67,
- 0xB1, 0x74, 0x5B, 0x60,
-
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-const BYTE g_rgbSymKey[] =
-{
- 0x01, 0x02, 0x00, 0x00, 0x02, 0x66, 0x00, 0x00,
- 0x00, 0xA4, 0x00, 0x00, 0xAD, 0x89, 0x5D, 0xDA,
- 0x82, 0x00, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
- 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
- 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
- 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
- 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
- 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
- 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
- 0x12, 0x12, 0x02, 0x00
-};
-
-const BYTE g_rgbPubKey[] =
-{
- 0x06, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
- 0x52, 0x53, 0x41, 0x31, 0x00, 0x02, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0xab, 0xef, 0xfa, 0xc6,
- 0x7d, 0xe8, 0xde, 0xfb, 0x68, 0x38, 0x09, 0x92,
- 0xd9, 0x42, 0x7e, 0x6b, 0x89, 0x9e, 0x21, 0xd7,
- 0x52, 0x1c, 0x99, 0x3c, 0x17, 0x48, 0x4e, 0x3a,
- 0x44, 0x02, 0xf2, 0xfa, 0x74, 0x57, 0xda, 0xe4,
- 0xd3, 0xc0, 0x35, 0x67, 0xfa, 0x6e, 0xdf, 0x78,
- 0x4c, 0x75, 0x35, 0x1c, 0xa0, 0x74, 0x49, 0xe3,
- 0x20, 0x13, 0x71, 0x35, 0x65, 0xdf, 0x12, 0x20,
- 0xf5, 0xf5, 0xf5, 0xc1
-};
-
-
-ProviderCache *ProviderCache::s_pCache = NULL;
-
-//---------------------------------------------------------------------------------------
-//
-// Associate a default CSP name with a CSP type
-//
-// Arguments:
-// dwType - type of CSP to associate the default name with
-// pwzProvider - name of the default CSP for dwType
-//
-// Notes:
-// Can throw an OOM if this is the first call into the method and
-// the underlying cache has yet to be allocated. See ProviderCache::InternalCacheProvider
-// for other details.
-
-// static
-void ProviderCache::CacheProvider(DWORD dwType, __in_z LPWSTR pwzProvider)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(pwzProvider != NULL);
- }
- CONTRACTL_END;
-
- if (s_pCache == NULL)
- {
- NewHolder<ProviderCache> cacheHolder(new ProviderCache());
- LPVOID pvExchange = InterlockedCompareExchangeT(&s_pCache,
- cacheHolder.GetValue(),
- NULL);
- if (pvExchange == NULL)
- cacheHolder.SuppressRelease();
- }
-
- s_pCache->InternalCacheProvider(dwType, pwzProvider);
-}
-
-//---------------------------------------------------------------------------------------
-//
-// Get the CSP name associated with the CSP type
-//
-// Arguments:
-// dwType - type of CSP to lookup the name of
-//
-// Return Value:
-// Name of the CSP if it is cached, NULL if there is no association yet
-
-// static
-LPCWSTR ProviderCache::GetProvider(DWORD dwType)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- if (s_pCache != NULL)
- return s_pCache->InternalGetProvider(dwType);
- else
- return NULL;
-}
-
-//---------------------------------------------------------------------------------------
-//
-// Initialize the CSP cache
-//
-// Notes:
-// Can throw an OOM the hashtable could not be setup properly
-//
-
-ProviderCache::ProviderCache()
- : m_crstCache(CrstCSPCache)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- LockOwner lockOwner = { &m_crstCache, IsOwnerOfCrst };
- if (!m_htCache.Init(MaxWindowsProviderType, &lockOwner))
- COMPlusThrowOM();
-}
-
-//---------------------------------------------------------------------------------------
-//
-// Associate a default CSP name with a CSP type
-//
-// Arguments:
-// dwType - type of CSP to associate the default name with
-// pwzProvider - name of the default CSP for dwType
-//
-
-void ProviderCache::InternalCacheProvider(DWORD dwType, __in_z LPWSTR pwzProvider)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- CAN_TAKE_LOCK;
- PRECONDITION(pwzProvider != NULL);
- }
- CONTRACTL_END;
-
- CrstHolder lockHolder(&m_crstCache);
- if (GetProvider(dwType) == NULL)
- m_htCache.InsertValue(dwType, reinterpret_cast<HashDatum>(pwzProvider));
-}
-
-//---------------------------------------------------------------------------------------
-//
-// Get the CSP name associated with the CSP type
-//
-// Arguments:
-// dwType - type of CSP to lookup the name of
-//
-// Return Value:
-// Name of the CSP if it is cached, NULL if there is no association yet
-
-LPCWSTR ProviderCache::InternalGetProvider(DWORD dwType)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- HashDatum datum;
- if (!m_htCache.GetValue(dwType, &datum))
- return NULL;
-
- _ASSERTE(datum != NULL);
- return reinterpret_cast<LPCWSTR>(datum);
-}
-#endif // FEATURE_CRYPTO
-
-#if defined(FEATURE_X509) || defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-//
-// Throw a runtime exception based on the HRESULT passed in.
-//
-
-void CryptoHelper::COMPlusThrowCrypto(HRESULT hr) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GCX_COOP();
-
- MethodDescCallSite throwMethod(METHOD__CRYPTO_EXCEPTION__THROW);
-
- ARG_SLOT args[] = {
- (ARG_SLOT) hr
- };
- throwMethod.Call(args);
-}
-
-BOOL CryptoHelper::WszCryptAcquireContext_SO_TOLERANT (HCRYPTPROV *phProv, LPCWSTR pwszContainer, LPCWSTR pwszProvider, DWORD dwProvType, DWORD dwFlags)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_NOTRIGGER;
- STATIC_CONTRACT_MODE_PREEMPTIVE;
- STATIC_CONTRACT_SO_INTOLERANT;
-
- BOOL fResult = FALSE;
- DWORD dwLastError = 0;
-
-#ifdef FEATURE_CRYPTO
- // Specifying both verify context (for an ephemeral key) and machine keyset (for a persisted machine key)
- // does not make sense. Additionally, Widows is beginning to lock down against uses of MACHINE_KEYSET
- // (for instance in the app container), even if verify context is present. Therefore, if we're using
- // an ephemeral key, strip out MACHINE_KEYSET from the flags.
- if ((dwFlags & CRYPT_VERIFYCONTEXT) && (dwFlags & CRYPT_MACHINE_KEYSET))
- {
- dwFlags &= ~CRYPT_MACHINE_KEYSET;
- }
-#endif // FEATURE_CRYPTO
-
- BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread())
-
- {
- LeaveRuntimeHolder lrh((size_t)::CryptAcquireContextW);
- fResult = WszCryptAcquireContext (phProv, pwszContainer, pwszProvider, dwProvType, dwFlags);
- if (!fResult)
- dwLastError = ::GetLastError();
- }
-
- END_SO_TOLERANT_CODE_CALLING_HOST;
-
- // END_SO_TOLERANT_CODE overwrites lasterror. Let's reset it.
- ::SetLastError(dwLastError);
- return fResult;
-}
-
-//
-// Helper method to get a Unicode copy of a managed string object. The Unicode string has to be freed with delete [].
-//
-
-WCHAR* CryptoHelper::STRINGREFToUnicode (STRINGREF s) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(s != NULL);
- } CONTRACTL_END;
-
- int cchUnicodeChar = s->GetStringLength();
- WCHAR* pwszUnicode = new WCHAR[cchUnicodeChar + 1];
- memcpy (pwszUnicode, s->GetBuffer(), cchUnicodeChar * sizeof(WCHAR));
- pwszUnicode[cchUnicodeChar] = W('\0');
-
- return pwszUnicode;
-}
-#endif // FEATURE_X509 || FEATURE_CRYPTO
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-//
-// Helper method to generate a random key container name.
-// The caller is responsible for freeing the memory allocated.
-//
-
-WCHAR* CryptoHelper::GetRandomKeyContainer() {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GUID guid;
- HRESULT hr = CoCreateGuid(&guid);
- if (hr != S_OK)
- COMPlusThrowHR(hr);
-
- WCHAR* pwszKeyContainerName = new WCHAR[50];
- memcpy(pwszKeyContainerName, W("CLR"), 4 * sizeof(WCHAR));
-
- if (GuidToLPWSTR(guid, &pwszKeyContainerName[3], 45) == 0) {
- DWORD lastError = GetLastError();
- delete [] pwszKeyContainerName;
- COMPlusThrowHR(HRESULT_FROM_WIN32(lastError));
- }
-
- return pwszKeyContainerName;
-}
-#endif // FEATURE_CRYPTO
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO) || defined(FEATURE_X509)
-//
-// Helper method to get a Unicode string from an ANSI string. The Unicode string has to be freed with delete [].
-//
-
-WCHAR* CryptoHelper::AnsiToUnicode (__in_z char* pszAnsi) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- int cchUnicodeChar = WszMultiByteToWideChar(CP_ACP,
- 0,
- pszAnsi,
- -1,
- NULL,
- 0);
- if (cchUnicodeChar == 0)
- COMPlusThrowWin32();
-
- WCHAR* pwszUnicode = new WCHAR[cchUnicodeChar];
- cchUnicodeChar = WszMultiByteToWideChar(CP_ACP,
- 0,
- pszAnsi,
- -1,
- pwszUnicode,
- cchUnicodeChar);
- if (cchUnicodeChar == 0) {
- DWORD lastError = GetLastError();
- delete [] pwszUnicode;
- COMPlusThrowHR(HRESULT_FROM_WIN32(lastError));
- }
-
- return pwszUnicode;
-}
-
-//
-// Helper method to construct a managed array from an unamanged byte array. The array ref has to be protected.
-//
-
-void CryptoHelper::ByteArrayToU1ARRAYREF (LPBYTE pb, DWORD cb, U1ARRAYREF* u1) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(CheckPointer(pb));
- } CONTRACTL_END;
-
- OBJECTREF array = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb);
- SetObjectReference((OBJECTREF*) u1, array, NULL);
- memcpyNoGCRefs((*u1)->GetDirectPointerToNonObjectElements(), pb, cb);
-}
-#endif // FEATURE_CRYPTO || FEATURE_X509
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-//
-// memrev
-//
-
-inline void CryptoHelper::memrev(LPBYTE pb, DWORD cb) {
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- } CONTRACTL_END;
-
- BYTE b;
- LPBYTE pbEnd = pb+cb-1;
- LPBYTE pbStart = pb;
-
- for (DWORD i=0; i<cb/2; i++, pbStart++, pbEnd--) {
- b = *pbStart;
- *pbStart = *pbEnd;
- *pbEnd = b;
- }
-}
-#endif // FEATURE_CRYPTO
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO) || defined(FEATURE_X509)
-//
-// Helper method to construct a byte array from a managed array ref. The unmanaged byte array pointer has to freed with delete [].
-//
-
-BYTE* CryptoHelper::U1ARRAYREFToByteArray (U1ARRAYREF u1) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- PRECONDITION(u1 != NULL);
- } CONTRACTL_END;
-
- BYTE* pb = new BYTE[u1->GetNumComponents()];
- memcpy(pb, (LPBYTE) u1->GetDirectPointerToNonObjectElements(), u1->GetNumComponents());
-
- return pb;
-}
-
-//
-// Helper method to get an ANSI string from a Unicode string. The ANSI string has to be freed with delete [].
-//
-
-char* CryptoHelper::UnicodeToAnsi (__in_z WCHAR* pwszUnicode) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- int cchAnsiChar;
- cchAnsiChar = WszWideCharToMultiByte(CP_ACP,
- 0,
- pwszUnicode,
- -1,
- NULL,
- 0,
- NULL,
- NULL);
- if (cchAnsiChar == 0)
- COMPlusThrowWin32();
-
- char* pszAnsi = new char[cchAnsiChar];
- cchAnsiChar = WszWideCharToMultiByte(CP_ACP,
- 0,
- pwszUnicode,
- -1,
- pszAnsi,
- cchAnsiChar,
- NULL,
- NULL);
- if (cchAnsiChar == 0) {
- DWORD lastError = GetLastError();
- delete [] pszAnsi;
- COMPlusThrowHR(HRESULT_FROM_WIN32(lastError));
- }
-
- return pszAnsi;
-}
-#endif // FEATURE_CRYPTO || FEATURE_X509
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-BOOL CryptoHelper::CryptGenKey_SO_TOLERANT (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY* phKey)
-{
- STATIC_CONTRACT_THROWS;
- STATIC_CONTRACT_GC_NOTRIGGER;
- STATIC_CONTRACT_MODE_PREEMPTIVE;
- STATIC_CONTRACT_SO_INTOLERANT;
-
- BOOL fResult = FALSE;
- DWORD dwLastError = 0;
-
- BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread())
-
- fResult = CryptGenKey (hProv, Algid, dwFlags, phKey);
- if (!fResult)
- dwLastError = ::GetLastError();
-
- END_SO_TOLERANT_CODE_CALLING_HOST;
-
- // END_SO_TOLERANT_CODE overwrites lasterror. Let's reset it.
- ::SetLastError(dwLastError);
- return fResult;
-}
-
-//
-// Check to see if a better CSP than the one requested is available
-// DSS providers are supersets of each other in the following order:
-// 1. MS_ENH_DSS_DH_PROV
-// 2. MS_DEF_DSS_DH_PROV
-//
-// This will return the best provider which is a superset of wszProvider,
-// or NULL if there is no upgrade available on the machine.
-//
-LPCWSTR CryptoHelper::UpgradeDSS(DWORD dwProvType, __in_z LPCWSTR wszProvider)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(dwProvType == PROV_DSS_DH);
- PRECONDITION(wszProvider != NULL);
- }
- CONTRACTL_END;
-
- LPCWSTR wszUpgrade = NULL;
- HandleCSPHolder hProv = NULL;
-
- if (wcscmp(wszProvider, MS_DEF_DSS_DH_PROV_W) == 0)
- {
- // If this is the base DSS/DH provider, see if we can use the enhanced provider instead.
- if (CryptoHelper::WszCryptAcquireContext_SO_TOLERANT(&hProv, NULL, MS_ENH_DSS_DH_PROV_W, dwProvType, CRYPT_VERIFYCONTEXT))
- wszUpgrade = MS_ENH_DSS_DH_PROV_W;
- }
-
- return wszUpgrade;
-}
-
-//
-// Check to see if a better CSP than the one requested is available
-// RSA providers are supersets of each other in the following order:
-// 1. MS_ENH_RSA_AES_PROV
-// 2. MS_ENHANCED_PROV
-// 3. MS_DEF_PROV
-//
-// This will return the best provider which is a superset of wszProvider,
-// or NULL if there is no upgrade available on the machine.
-//
-LPCWSTR CryptoHelper::UpgradeRSA(DWORD dwProvType, __in_z LPCWSTR wszProvider)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- PRECONDITION(dwProvType == PROV_RSA_FULL);
- PRECONDITION(wszProvider != NULL);
- }
- CONTRACTL_END;
-
- bool requestedEnhanced = wcscmp(wszProvider, MS_ENHANCED_PROV_W) == 0;
- bool requestedBase = wcscmp(wszProvider, MS_DEF_PROV_W) == 0;
-
- LPCWSTR wszUpgrade = NULL;
- HandleCSPHolder hProv = NULL;
-
- if (requestedBase || requestedEnhanced)
- {
- // attempt to use the AES provider
- if (CryptoHelper::WszCryptAcquireContext_SO_TOLERANT(&hProv, NULL, MS_ENH_RSA_AES_PROV_W, dwProvType, CRYPT_VERIFYCONTEXT))
- wszUpgrade = MS_ENH_RSA_AES_PROV_W;
- }
- else if (wszUpgrade == NULL && requestedBase)
- {
- // if AES wasn't available and we requested the base CSP, try the enhanced one
- if (CryptoHelper::WszCryptAcquireContext_SO_TOLERANT(&hProv, NULL, MS_ENHANCED_PROV_W, dwProvType, CRYPT_VERIFYCONTEXT))
- wszUpgrade = MS_ENHANCED_PROV_W;
- }
-
- return wszUpgrade;
-}
-
-//
-// WARNING: This function side-effects its first argument (hProv)
-// MSProviderCryptImportKey does an "exponent-of-one" import of specified
-// symmetric key material into a CSP. However, it clobbers any exchange key pair
-// already in hProv.
-//
-
-HRESULT COMCryptography::ExponentOfOneImport (HCRYPTPROV hProv,
- LPBYTE rgbKeyMaterial,
- DWORD cbKeyMaterial,
- DWORD dwKeyAlg,
- DWORD dwFlags,
- HCRYPTKEY* phKey) {
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- } CONTRACTL_END;
-
- HRESULT hr = S_OK;
-
- LPBYTE pb = NULL;
- BLOBHEADER * pbhdr = NULL;
- BYTE rgb[sizeof(g_rgbSymKey)];
-
- // Do this check here as a sanity check to avoid buffer overruns
- // variable bufSize used to allow for overflow.
- DWORD bufSize= cbKeyMaterial + sizeof(ALG_ID) + sizeof(BLOBHEADER);
- if (bufSize < cbKeyMaterial || bufSize >= sizeof(g_rgbSymKey))
- return E_FAIL;
-
- memcpy(rgb, g_rgbSymKey, sizeof(g_rgbSymKey));
-
- pbhdr = (BLOBHEADER *) rgb;
- pbhdr->aiKeyAlg = dwKeyAlg;
- pb = &rgb[sizeof(*pbhdr)];
- *((ALG_ID *) pb) = CALG_RSA_KEYX;
-
- pb += sizeof(ALG_ID);
- for (DWORD i=0; i<cbKeyMaterial; i++)
- pb[cbKeyMaterial-i-1] = rgbKeyMaterial[i];
- pb[cbKeyMaterial] = 0;
-
- HandleKeyHolder hPrivKey(NULL);
- if (!CryptImportKey(hProv, g_rgbPrivKey, sizeof(g_rgbPrivKey), 0, 0, &hPrivKey)) {
- hr = HRESULT_FROM_GetLastError();
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::ExponentOfOneImport --> CryptImportKey failed.\n", hr));
- }
-
- if (!CryptImportKey(hProv, rgb, sizeof(rgb), hPrivKey, dwFlags, phKey)) {
- hr = HRESULT_FROM_GetLastError();
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::ExponentOfOneImport --> CryptImportKey failed.\n", hr));
- }
-
- return hr;
-}
-
-HRESULT COMCryptography::PlainTextKeyBlobImport (HCRYPTPROV hProv,
- LPBYTE rgbKeyMaterial,
- DWORD cbKeyMaterial,
- DWORD dwKeyAlg,
- DWORD dwFlags,
- HCRYPTKEY* phKey) {
- CONTRACTL {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- } CONTRACTL_END;
-
- HRESULT hr = S_OK;
-
- DWORD cb = cbKeyMaterial + sizeof(DWORD) + sizeof(BLOBHEADER);
- NewArrayHolder<BYTE> pbHolder(new BYTE[cb]);
- LPBYTE pb = (LPBYTE) pbHolder.GetValue();
-
- BLOBHEADER * pbhdr = (BLOBHEADER *) pb;
- pbhdr->bType = PLAINTEXTKEYBLOB;
- pbhdr->bVersion = CUR_BLOB_VERSION;
- pbhdr->reserved = 0x0000;
- pbhdr->aiKeyAlg = dwKeyAlg;
-
- pb += sizeof(*pbhdr);
- *((DWORD *) pb) = cbKeyMaterial;
- pb += sizeof(DWORD);
- memcpy(pb, rgbKeyMaterial, cbKeyMaterial);
-
- if (!CryptImportKey(hProv, pbHolder, cb, 0, dwFlags, phKey)) {
- hr = HRESULT_FROM_GetLastError();
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::PlainTextKeyBlobImport --> CryptImportKey failed.\n", hr));
- }
-
- return hr;
-}
-
-HRESULT COMCryptography::LoadKey (LPBYTE rgbKeyMaterial,
- DWORD cbKeyMaterial,
- HCRYPTPROV hprov,
- DWORD dwCalg,
- DWORD dwFlags,
- HCRYPTKEY* phkey) {
- WRAPPER_NO_CONTRACT;
-
- HRESULT hr = PlainTextKeyBlobImport(hprov, rgbKeyMaterial, cbKeyMaterial, dwCalg, dwFlags, phkey);
- if (FAILED(hr))
- hr = ExponentOfOneImport(hprov, rgbKeyMaterial, cbKeyMaterial, dwCalg, dwFlags, phkey);
- return hr;
-}
-
-//
-// WARNING: This function side-effects its first argument (hProv)
-//
-
-HRESULT COMCryptography::UnloadKey(HCRYPTPROV hprov,
- HCRYPTKEY hkey,
- LPBYTE* ppb,
- DWORD* pcb) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- DWORD cbOut = 0;
- HandleKeyHolder hPubKey(NULL);
-
- HRESULT hr = S_OK;
- if (!CryptImportKey(hprov, g_rgbPubKey, sizeof(g_rgbPubKey), 0, 0, &hPubKey)) {
- hr = HRESULT_FROM_GetLastError();
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::UnloadKey --> CryptImportKey failed.\n", hr));
- return hr;
- }
-
- if (!CryptExportKey(hkey, hPubKey, SIMPLEBLOB, 0, NULL, &cbOut)) {
- hr = HRESULT_FROM_GetLastError();
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::UnloadKey --> CryptExportKey failed.\n", hr));
- return hr;
- }
-
- NewArrayHolder<BYTE> pbOut(new BYTE[cbOut]);
- if (!CryptExportKey(hkey, hPubKey, SIMPLEBLOB, 0, pbOut, &cbOut)) {
- hr = HRESULT_FROM_GetLastError();
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::UnloadKey --> CryptExportKey failed.\n", hr));
- return hr;
- }
-
- // Get size of the item
- LPBYTE pb2 = pbOut + sizeof(BLOBHEADER) + sizeof(DWORD);
- DWORD i= cbOut - sizeof(BLOBHEADER) - sizeof(DWORD) - 2;
- if (i >= cbOut) {
- // integer overflow
- return E_FAIL;
- }
- while (i > 0) {
- if (pb2[i] == 0)
- break;
- i--;
- }
-
- // Now allocate the return buffer
- *ppb = new BYTE[i];
-
- memcpy(*ppb, pb2, i);
- CryptoHelper::memrev(*ppb, i);
- *pcb = i;
-
- return hr;
-}
-
-//
-// GetDefaultProvider
-//
-// Description:
-// Find the default provider name to be used in the case that we
-// were not actually passed in a provider name. The main purpose
-// of this code is really to deal with the enhanched/default provider
-// problems given to us by CAPI.
-//
-// Returns:
-// name of the provider to be used.
-//
-
-LPCWSTR COMCryptography::GetDefaultProvider(DWORD dwType)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // If we have already gotten a name for this provider type, then just return it.
- LPCWSTR pwszCached = ProviderCache::GetProvider(dwType);
- if (pwszCached != NULL)
- return pwszCached;
-
- // figure out how big the provider name is
- DWORD cbProviderName = 0;
- if (!WszCryptGetDefaultProvider(dwType, NULL, CRYPT_MACHINE_DEFAULT, NULL, &cbProviderName))
- {
- DWORD dwLastError = GetLastError();
- LOG((LF_SECURITY, LL_INFO10, "Error [%#x]: CryptGetDefaultProvider(%d)", dwLastError, dwType));
- return NULL;
- }
-
- // get the CSP name from CAPI
- NewArrayHolder<WCHAR> pwszProviderName(new WCHAR[cbProviderName]);
- if (!WszCryptGetDefaultProvider(dwType, NULL, CRYPT_MACHINE_DEFAULT, pwszProviderName, &cbProviderName))
- {
- DWORD dwLastError = GetLastError();
- LOG((LF_SECURITY, LL_INFO10, "Error [%#x]: CryptGetDefaultProvider(%d)", dwLastError, dwType));
- return NULL;
- }
-
- {
- GCX_PREEMP();
-
- // check to see if there are upgrades available for the requested CSP
- LPCWSTR wszUpgrade = NULL;
- if (dwType == PROV_RSA_FULL)
- wszUpgrade = CryptoHelper::UpgradeRSA(dwType, pwszProviderName);
- else if (dwType == PROV_DSS_DH)
- wszUpgrade = CryptoHelper::UpgradeDSS(dwType, pwszProviderName);
-
- if (wszUpgrade != NULL)
- {
- LOG((LF_SECURITY, LL_INFO10, "Upgrading from CSP %s to CSP %s", pwszProviderName, wszUpgrade));
-
- pwszProviderName.Release();
- const size_t cchProvider = wcslen(wszUpgrade) + 1;
- pwszProviderName = new WCHAR[cchProvider];
- wcscpy_s(pwszProviderName, cchProvider, wszUpgrade);
- }
- }
-
- ProviderCache::CacheProvider(dwType, pwszProviderName);
- pwszProviderName.SuppressRelease();
-
- LOG((LF_SECURITY, LL_INFO100, "Using CSP %s as default for CSP type %d", pwszProviderName, dwType));
- return pwszProviderName;
-}
-
-// converts a big-endian byte array to a DWORD value
-inline DWORD COMCryptography::ConvertByteArrayToDWORD (LPBYTE pb, DWORD cb) {
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION((cb <= 4 && cb >= 0));
- } CONTRACTL_END;
-
- DWORD dwOutput = 0;
- for (DWORD i = 0; i < cb; i++) {
- dwOutput = dwOutput << 8;
- dwOutput += pb[i];
- }
- return dwOutput;
-}
-
-// output of this routine is always big endian
-inline void COMCryptography::ConvertIntToByteArray(DWORD dwInput, LPBYTE * ppb, DWORD * pcb) {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- SO_INTOLERANT;
- } CONTRACTL_END;
-
- if (dwInput == 0) {
- *ppb = new BYTE[1];
- (*ppb)[0] = 0;
- return;
- }
-
- *ppb = new BYTE[4];
-
- DWORD t1 = dwInput; // t1 is remaining value to account for
- DWORD t2; // t2 is (t1 % 256) & 0xFF
- DWORD i = 0;
-
- while (t1 > 0) {
- t2 = (t1 % 256) & 0xFF;
- (*ppb)[i] = static_cast<BYTE>(t2);
- t1 = (t1 - t2) >> 8;
- i++;
- }
-
- *pcb = i;
- CryptoHelper::memrev(*ppb, i);
-}
-
-// Maps CspProviderFlags enumeration into CAPI flags.
-DWORD COMCryptography::MapCspKeyFlags (DWORD dwFlags) {
- DWORD dwCapiFlags = 0;
- if ((dwFlags & CSP_PROVIDER_FLAGS_USE_NON_EXPORTABLE_KEY) == 0)
- dwCapiFlags |= CRYPT_EXPORTABLE;
- if (dwFlags & CSP_PROVIDER_FLAGS_USE_ARCHIVABLE_KEY)
- dwCapiFlags |= CRYPT_ARCHIVABLE;
- if (dwFlags & CSP_PROVIDER_FLAGS_USE_USER_PROTECTED_KEY)
- dwCapiFlags |= CRYPT_USER_PROTECTED;
-
- return dwCapiFlags;
-}
-
-// Maps CspProviderFlags enumeration into CAPI flags.
-DWORD COMCryptography::MapCspProviderFlags (DWORD dwFlags) {
- DWORD dwCapiFlags = 0;
- if (dwFlags & CSP_PROVIDER_FLAGS_USE_MACHINE_KEYSTORE)
- dwCapiFlags |= CRYPT_MACHINE_KEYSET;
- if (dwFlags & CSP_PROVIDER_FLAGS_USE_CRYPT_SILENT)
- dwCapiFlags |= CRYPT_SILENT;
- if (dwFlags & CSP_PROVIDER_FLAGS_CREATE_EPHEMERAL_KEY)
- dwCapiFlags |= CRYPT_VERIFYCONTEXT;
-
- return dwCapiFlags;
-}
-
-//
-// OpenCSP
-//
-// Description:
-// OpenCSP performs the core work of opening and creating CSPs and
-// containers in CSPs.
-//
-
-HRESULT COMCryptography::OpenCSP(OBJECTREF * pSafeThis, DWORD dwFlags, CRYPT_PROV_CTX * pProvCtx) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- } CONTRACTL_END;
-
- NewArrayHolder<WCHAR> pwszProviderHolder = NULL; // if we need to allocate the CSP name ourselves
- // store it here so it can be released
- LPCWSTR pwszProvider = NULL; // location where the CSP name will be read
- // regardless of where we loaded it from
-
- NewArrayHolder<WCHAR> pwszContainer = NULL;
-
- //
- // Look for the provider type
- //
-
- FieldDesc * pFD = MscorlibBinder::GetField(FIELD__CSP_PARAMETERS__PROVIDER_TYPE);
- DWORD dwType = pFD->GetValue32(*pSafeThis);
-
- //
- // Look for the provider name
- //
-
- pFD = MscorlibBinder::GetField(FIELD__CSP_PARAMETERS__PROVIDER_NAME);
-
- OBJECTREF objref = pFD->GetRefValue(*pSafeThis);
- STRINGREF strProvider = ObjectToSTRINGREF(*(StringObject **) &objref);
- if (strProvider != NULL) {
- LPCWSTR pwsz = strProvider->GetBuffer();
- if ((pwsz != NULL) && (*pwsz != 0)) {
- pwszProviderHolder = CryptoHelper::STRINGREFToUnicode(strProvider);
- pProvCtx->m_fReleaseProvider = TRUE;
- pwszProvider = pwszProviderHolder;
- }
- else {
- pwszProvider = GetDefaultProvider(dwType);
- pProvCtx->m_fReleaseProvider = FALSE;
- STRINGREF str = StringObject::NewString(pwszProvider);
- pFD->SetRefValue(*pSafeThis, (OBJECTREF)str);
- }
- } else {
- pwszProvider = GetDefaultProvider(dwType);
- pProvCtx->m_fReleaseProvider = FALSE;
- STRINGREF str = StringObject::NewString(pwszProvider);
- pFD->SetRefValue(*pSafeThis, (OBJECTREF)str);
- }
-
- // look to see if the user specified that we should pass
- // CRYPT_MACHINE_KEYSET to CAPI to use machine key storage instead
- // of user key storage
- DWORD dwCspProviderFlags = 0;
-
- objref=NULL;
- GCPROTECT_BEGIN (objref);
-
- pFD = MscorlibBinder::GetField(FIELD__CSP_PARAMETERS__FLAGS);
- dwCspProviderFlags = pFD->GetValue32(*pSafeThis);
-
- // If the user specified CSP_PROVIDER_FLAGS_USE_DEFAULT_KEY_CONTAINER,
- // then ignore the container name and hand back the default container
-
- pFD = MscorlibBinder::GetField(FIELD__CSP_PARAMETERS__KEY_CONTAINER_NAME);
- if ((dwCspProviderFlags & CSP_PROVIDER_FLAGS_USE_DEFAULT_KEY_CONTAINER) == 0) {
- // Look for the key container name
- objref = pFD->GetRefValue(*pSafeThis);
- STRINGREF strContainer = ObjectToSTRINGREF(*(StringObject **) &objref);
- if (strContainer != NULL) {
- LPWSTR pwsz = strContainer->GetBuffer();
- if ((pwsz != NULL) && (*pwsz != 0))
- pwszContainer = CryptoHelper::STRINGREFToUnicode(strContainer);
- }
- }
-
- GCPROTECT_END ();
-
- // Go ahead and try to open the CSP. If we fail, make sure the CSP
- // returned is 0 as that is going to be the error check in the caller.
- HandleCSPHolder hProv(NULL);
- {
- GCX_PREEMP();
- dwFlags |= MapCspProviderFlags(dwCspProviderFlags);
-
- if (!CryptoHelper::WszCryptAcquireContext_SO_TOLERANT(&hProv, pwszContainer, pwszProvider, dwType, dwFlags))
- return HRESULT_FROM_GetLastError();
- }
-
- // CRYPT_PROV_CTX takes ownership of these resources, and frees them in its Release
- hProv.SuppressRelease();
- pwszContainer.SuppressRelease();
- pwszProviderHolder.SuppressRelease();
-
- pProvCtx->m_hProv = hProv;
- pProvCtx->m_pwszContainer = pwszContainer;
- pProvCtx->m_pwszProvider = pwszProvider;
- pProvCtx->m_dwType = dwType;
- pProvCtx->m_dwFlags = dwFlags;
-
- // If we are using CRYPT_VERIFYCONTEXT this is an ephemeral key, so clear the persist flag
- if (dwFlags & CRYPT_VERIFYCONTEXT)
- pProvCtx->m_fPersistKeyInCsp = FALSE;
-
- return S_OK;
-}
-
-//
-// FCALL functions
-//
-
-//
-// Native method to open a CSP using CRYPT_VERIFYCONTEXT
-//
-
-FCIMPL2(void, COMCryptography::_AcquireCSP, Object* cspParametersUNSAFE, SafeHandle** hProvUNSAFE)
-{
- FCALL_CONTRACT;
-
- OBJECTREF cspParameters = (OBJECTREF) cspParametersUNSAFE;
- SAFEHANDLE hProvSAFE = (SAFEHANDLE) *hProvUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_2(cspParameters, hProvSAFE);
-
- //
- // We want to just open this CSP. Passing in verify context will
- // open it and, if a container is given, map to open the container.
- //
-
- NewHolder<CRYPT_PROV_CTX> pProvCtx(new CRYPT_PROV_CTX());
- // protect the allocated structure with a holder
- HRESULT hr = OpenCSP(&cspParameters, CRYPT_VERIFYCONTEXT, pProvCtx);
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::OpenCSP failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- // we never want to delete a key container when using CRYPT_VERIFYCONTEXT
- pProvCtx->m_fPersistKeyInCsp = TRUE;
-
- // Set the handle field
- hProvSAFE->SetHandle((void*) pProvCtx.GetValue());
- pProvCtx.SuppressRelease();
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// This method opens an existing key container.
-// It returns FALSE if the container could not be found.
-//
-
-FCIMPL3(HRESULT, COMCryptography::_OpenCSP, Object* cspParametersUNSAFE, DWORD dwFlags, SafeHandle** hProvUNSAFE)
-{
- FCALL_CONTRACT;
-
- HRESULT hr = S_OK;
- OBJECTREF cspParameters = (OBJECTREF) cspParametersUNSAFE;
- SAFEHANDLE hProvSAFE = (SAFEHANDLE) *hProvUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(cspParameters, hProvSAFE);
-
- NewHolder<CRYPT_PROV_CTX> pProvCtx(new CRYPT_PROV_CTX());
- // We never want to delete a key container if it's already there.
- pProvCtx->m_fPersistKeyInCsp = TRUE;
-
- hr = OpenCSP(&cspParameters, dwFlags, pProvCtx);
- if (SUCCEEDED(hr)) {
- // Set the handle field
- hProvSAFE->SetHandle((void*) pProvCtx.GetValue());
- pProvCtx.SuppressRelease();
- }
-
- HELPER_METHOD_FRAME_END();
- return hr;
-}
-FCIMPLEND
-
-//
-// Native method for calling a CSP to get random bytes.
-//
-
-void QCALLTYPE COMCryptography::GetBytes(CRYPT_PROV_CTX * pProvCtx, BYTE * pbOut, INT32 cb)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- NewArrayHolder<BYTE> buffer = new BYTE[cb];
-
- if (!CryptGenRandom(pProvCtx->m_hProv, cb, buffer))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- memcpyNoGCRefs(pbOut, buffer, cb);
-
- END_QCALL;
-}
-
-//
-// Native method for calling a CSP to get random bytes.
-//
-
-void QCALLTYPE COMCryptography::GetNonZeroBytes(CRYPT_PROV_CTX * pProvCtx, BYTE * pbOut, INT32 cb)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- NewArrayHolder<BYTE> pb = new BYTE[cb];
- INT32 i = 0;
-
- while (i < cb) {
- if (!CryptGenRandom(pProvCtx->m_hProv, cb, pb))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- for (INT32 j=0; (i<cb) && (j<cb); j++) {
- if (pb[j] != 0) pbOut[i++] = pb[j];
- }
- }
-
- END_QCALL;
-}
-
-//
-// Release our handle to a CSP, potentially deleting the referenced key
-//
-// Arguments:
-// pProviderContext - CSP context to release
-//
-//
-// Notes:
-// This is the target of the System.Security.Cryptography.SafeProvHandle.FreeCsp QCall
-//
-
-// static
-void QCALLTYPE COMCryptography::FreeCsp(__in_opt CRYPT_PROV_CTX *pProviderContext)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- if (pProviderContext)
- pProviderContext->Release();
-
- END_QCALL;
-}
-
-//
-// _SearchForAlgorithm
-//
-// Method for determining whether a CSP supports a particular
-// algorithm and (optionally) a key size of that algorithm
-//
-BOOL QCALLTYPE COMCryptography::SearchForAlgorithm(CRYPT_PROV_CTX * pProvCtx, DWORD dwAlgID, DWORD dwKeyLength)
-{
- QCALL_CONTRACT;
-
- BOOL result = FALSE;
-
- BEGIN_QCALL;
-
- DWORD dwFlags = CRYPT_FIRST;
- DWORD cbData = 0;
- // First, we have to get the max size of the PP
- if (CryptGetProvParam(pProvCtx->m_hProv, PP_ENUMALGS_EX, NULL, &cbData, dwFlags)) {
-
- // Allocate pbData
- NewArrayHolder<BYTE> pbData = new BYTE[cbData];
- while (CryptGetProvParam(pProvCtx->m_hProv, PP_ENUMALGS_EX, pbData, &cbData, dwFlags)) {
- dwFlags = 0; // so we don't use CRYPT_FIRST more than once
- PROV_ENUMALGS_EX *provdata = (PROV_ENUMALGS_EX *) pbData.GetValue();
- ALG_ID provAlgID = provdata->aiAlgid;
- DWORD provMinLength = provdata->dwMinLen;
- DWORD provMaxLength = provdata->dwMaxLen;
-
- // OK, now check to see if we have an alg match
- if ((ALG_ID) dwAlgID == provAlgID) {
- // OK, see if we have a keylength match, or if we don't care
- if ((dwKeyLength == 0) ||
- (dwKeyLength >= provMinLength) &&
- (dwKeyLength <= provMaxLength)) {
- result = TRUE;
- break;
- }
- } // keep looping
- }
- }
-
- END_QCALL;
-
- return result;
-}
-
-//
-// This method creates a new key container.
-//
-
-FCIMPL3(void, COMCryptography::_CreateCSP, Object* cspParametersUNSAFE, CLR_BOOL randomKeyContainer, SafeHandle** hProvUNSAFE)
-{
- FCALL_CONTRACT;
-
- OBJECTREF cspParameters = (OBJECTREF) cspParametersUNSAFE;
- SAFEHANDLE hProvSAFE = (SAFEHANDLE) *hProvUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_2(cspParameters, hProvSAFE);
-
- NewHolder<CRYPT_PROV_CTX> pProvCtx(new CRYPT_PROV_CTX());
-
- // We always want to delete the random key container we create
- pProvCtx->m_fPersistKeyInCsp = (randomKeyContainer ? FALSE : TRUE);
-
- DWORD dwFlags = CRYPT_NEWKEYSET;
- if (randomKeyContainer) {
- dwFlags |= CRYPT_VERIFYCONTEXT;
- }
-
- HRESULT hr = OpenCSP(&cspParameters, dwFlags, pProvCtx);
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::OpenCSP failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- // Set the handle field
- hProvSAFE->SetHandle((void*) pProvCtx.GetValue());
- pProvCtx.SuppressRelease();
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-CRYPT_HASH_CTX * COMCryptography::CreateHash(CRYPT_PROV_CTX * pProvCtx, DWORD dwHashType)
-{
- QCALL_CONTRACT;
-
- CRYPT_HASH_CTX * pHashCtx = NULL;
-
- BEGIN_QCALL;
-
- HandleHashHolder hHash = NULL;
- HRESULT hr = S_OK;
-
- if (!CryptCreateHash(pProvCtx->m_hProv, dwHashType, NULL, 0, &hHash)) {
- hr = HRESULT_FROM_GetLastError();
- }
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::_CreateHash failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- pHashCtx = new CRYPT_HASH_CTX(pProvCtx, hHash);
- hHash.SuppressRelease();
-
- END_QCALL;
-
- return pHashCtx;
-}
-
-void QCALLTYPE COMCryptography::DeriveKey(CRYPT_PROV_CTX * pProvCtx, DWORD dwCalgKey, DWORD dwCalgHash,
- LPCBYTE pbPwd, DWORD cbPwd, DWORD dwFlags, LPBYTE pbIVIn, DWORD cbIVIn,
- QCall::ObjectHandleOnStack retKey)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- HandleHashHolder hHash(NULL);
- HandleKeyHolder hKey(NULL);
-
- NewArrayHolder<BYTE> bufferPwd = new BYTE[cbPwd];
- memcpyNoGCRefs (bufferPwd, pbPwd, cbPwd * sizeof(BYTE));
-
- NewArrayHolder<BYTE> rgbKey(NULL);
- NewArrayHolder<BYTE> pbIV(NULL);
- DWORD cb = 0;
- DWORD cbIV = 0;
-
- if (!CryptCreateHash(pProvCtx->m_hProv, dwCalgHash, NULL, 0, &hHash))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // Hash the password string
- if (!CryptHashData(hHash, pbPwd, cbPwd, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // Create a block cipher session key based on the hash of the password
- if (!CryptDeriveKey(pProvCtx->m_hProv, dwCalgKey, hHash, dwFlags | CRYPT_EXPORTABLE, &hKey))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- HRESULT hr = UnloadKey(pProvCtx->m_hProv, hKey, &rgbKey, &cb);
- if (FAILED(hr))
- CryptoHelper::COMPlusThrowCrypto(hr);
-
- // Get the length of the IV
- cbIV = 0;
- if (!CryptGetKeyParam(hKey, KP_IV, NULL, &cbIV, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // Now allocate space for the IV vector
- pbIV = new BYTE[cbIV];
- if (!CryptGetKeyParam(hKey, KP_IV, pbIV, &cbIV, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // Check to avoid writing in the wrong location of the GC heap
- if (cbIV != cbIVIn)
- COMPlusThrow(kCryptographicException, W("Cryptography_PasswordDerivedBytes_InvalidIV"));
- memcpyNoGCRefs (pbIVIn, pbIV, cbIV);
-
- retKey.SetByteArray(rgbKey, cb);
-
- END_QCALL;
-}
-
-FCIMPL8(DWORD, COMCryptography::_DecryptData, SafeHandle* hKeyUNSAFE, U1Array* dataUNSAFE,
- INT32 dwOffset, INT32 dwCount, U1Array** outputUNSAFE, INT32 dwOutputOffset, DWORD dwPaddingMode, CLR_BOOL fLast)
-{
- FCALL_CONTRACT;
-
- struct _gc
- {
- U1ARRAYREF data;
- U1ARRAYREF output;
- SAFEHANDLE hKeySAFE;
- } gc;
-
- gc.data = (U1ARRAYREF) dataUNSAFE;
- gc.output = (U1ARRAYREF) *outputUNSAFE;
- gc.hKeySAFE = (SAFEHANDLE) hKeyUNSAFE;
-
- INT32 dwResult = 0;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- DWORD cb2 = dwCount;
- // Do this check here as a sanity check. Also, this will catch bugs in CryptoAPITransform
- if (dwOffset < 0 || dwCount < 0 || dwCount > (INT32) gc.data->GetNumComponents() || dwOffset > ((INT32) gc.data->GetNumComponents() - dwCount))
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- NewArrayHolder<BYTE> pb(new BYTE[cb2]);
- memcpy(pb, dwOffset + (LPBYTE) gc.data->GetDirectPointerToNonObjectElements(), cb2);
-
- {
- SafeHandleHolder shh(&gc.hKeySAFE);
- CRYPT_KEY_CTX * pKeyCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_KEY_CTX>(gc.hKeySAFE);
- {
- GCX_PREEMP();
- // always call decryption with false, deal with padding manually
- if (!CryptDecrypt(pKeyCtx->m_hKey, NULL, FALSE, 0, pb, &cb2))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- }
-
- DWORD dwPadLen = 0;
- if (fLast) {
- switch(dwPaddingMode) {
- case CRYPTO_PADDING_NONE:
- // we don't remove any padding
- break;
- case CRYPTO_PADDING_Zeros:
- // nothing to check for here
- break;
- case CRYPTO_PADDING_PKCS5:
- // PKCS5 padding is as follows: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07
- dwPadLen = cb2 > 0 ? pb[cb2 - 1] : 0;
-
- if (cb2 < BLOCK_LEN || dwPadLen <= 0 || dwPadLen > BLOCK_LEN)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- // Check the padding bytes are all correct
- for (DWORD index = cb2 - dwPadLen; index + 1 < cb2; index++)
- if (pb[index] != dwPadLen)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- break;
- case CRYPTO_PADDING_ISO_10126:
- // The padding is as follows: FF FF FF FF FF FF FF FF FF 7D 2A 75 EF F8 EF 07
- dwPadLen = cb2 > 0 ? pb[cb2 - 1] : 0;
- if (cb2 < BLOCK_LEN || dwPadLen <= 0 || dwPadLen > BLOCK_LEN)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- // Just ignore the random bytes
- break;
- case CRYPTO_PADDING_ANSI_X_923:
- // The padding is as follows: FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 07
- dwPadLen = cb2 > 0 ? pb[cb2 - 1] : 0;
- if (cb2 < BLOCK_LEN || dwPadLen <= 0 || dwPadLen > BLOCK_LEN)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- // Check the padding bytes are all zeros
- for (DWORD index = cb2 - dwPadLen; index + 1 < cb2; index++)
- if (pb[index] != 0)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- break;
- }
- }
-
- dwResult = (cb2 - dwPadLen);
- if (dwResult < 0)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- if (gc.output == NULL) {
- gc.output = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, dwResult);
- memcpyNoGCRefs(gc.output->GetDirectPointerToNonObjectElements(), pb, dwResult);
- SetObjectReference((OBJECTREF*) outputUNSAFE, (OBJECTREF) gc.output, gc.output->GetAppDomain());
- } else {
- if (dwOutputOffset < 0 || dwResult < 0 || dwResult > (INT32) gc.output->GetNumComponents() || dwOutputOffset > ((INT32) gc.output->GetNumComponents() - dwResult))
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- memcpyNoGCRefs(dwOutputOffset + (LPBYTE) gc.output->GetDirectPointerToNonObjectElements(), pb, dwResult);
- }
-
- HELPER_METHOD_FRAME_END();
- return dwResult;
-}
-FCIMPLEND
-
-//---------------------------------------------------------------------------------------
-//
-// Decrypt a symmetric key using the private key in pKeyContext
-//
-// Arguments:
-// pKeyContext - private key used for decrypting pbEncryptedKey
-// pbEncryptedKey - [in] encrypted symmetric key
-// cbEncryptedKey - size, in bytes, of pbEncryptedKey
-// fOAEP - TRUE to use OAEP padding, FALSE to use PKCS #1 type 2 padding
-// ohRetDecryptedKey - [out] decrypted key
-//
-// Notes:
-// pbEncryptedKey is byte-reversed from the format that CAPI expects. This is for compatibility with
-// previous CLR versions and other RSA implementations.
-//
-// This method is the target of the System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey QCall
-//
-
-// static
-void QCALLTYPE COMCryptography::DecryptKey(__in CRYPT_KEY_CTX *pKeyContext,
- __in_bcount(cbEncryptedKey) BYTE *pbEncryptedKey,
- DWORD cbEncryptedKey,
- BOOL fOAEP,
- QCall::ObjectHandleOnStack ohRetDecryptedKey)
-{
- CONTRACTL
- {
- QCALL_CHECK;
- PRECONDITION(CheckPointer(pKeyContext));
- PRECONDITION(CheckPointer(pbEncryptedKey));
- PRECONDITION(cbEncryptedKey >= 0);
- }
- CONTRACTL_END;
-
- BEGIN_QCALL;
-
- NewArrayHolder<BYTE> pbKey = new BYTE[cbEncryptedKey];
- memcpy_s(pbKey, cbEncryptedKey, pbEncryptedKey, cbEncryptedKey);
- CryptoHelper::memrev(pbKey, cbEncryptedKey);
-
- DWORD dwDecryptFlags = fOAEP ? CRYPT_OAEP : 0;
- DWORD cbDecryptedKey = cbEncryptedKey;
- if (!CryptDecrypt(pKeyContext->m_hKey, NULL, TRUE, dwDecryptFlags, pbKey, &cbDecryptedKey))
- {
- HRESULT hrDecrypt = HRESULT_FROM_GetLastError();
-
- // If we're using OAEP mode and we recieved an NTE_BAD_FLAGS error, then OAEP is not supported on
- // this platform (XP+ only). Throw a generic cryptographic exception if we failed to decrypt OAEP
- // padded data in order to prevent a chosen ciphertext attack. We will allow NTE_BAD_KEY out, since
- // that error does not relate to the padding. Otherwise just throw a cryptographic exception based on
- // the error code.
- if ((dwDecryptFlags & CRYPT_OAEP) == CRYPT_OAEP && hrDecrypt != NTE_BAD_KEY)
- {
- if (hrDecrypt == NTE_BAD_FLAGS)
- COMPlusThrow(kCryptographicException, W("Cryptography_OAEP_XPOnly"));
- else
- COMPlusThrow(kCryptographicException, W("Cryptography_OAEPDecoding"));
- }
- else
- {
- CryptoHelper::COMPlusThrowCrypto(hrDecrypt);
- }
- }
-
- // CryptDecrypt operates in place, so pbKey now has the plaintext version of the key.
- // cbDecryptedKey was updated to indicate the number of bytes of plaintext that are in the buffer.
- ohRetDecryptedKey.SetByteArray(pbKey, cbDecryptedKey);
- END_QCALL;
-}
-
-FCIMPL8(DWORD, COMCryptography::_EncryptData, SafeHandle* hKeyUNSAFE, U1Array* dataUNSAFE,
- INT32 dwOffset, INT32 dwCount, U1Array** outputUNSAFE, INT32 dwOutputOffset, DWORD dwPaddingMode, CLR_BOOL fLast)
-{
- FCALL_CONTRACT;
-
- struct _gc
- {
- U1ARRAYREF data;
- U1ARRAYREF output;
- SAFEHANDLE hKeySAFE;
- } gc;
-
- gc.data = (U1ARRAYREF) dataUNSAFE;
- gc.output = (U1ARRAYREF) *outputUNSAFE;
- gc.hKeySAFE = (SAFEHANDLE) hKeyUNSAFE;
-
- DWORD cb2 = dwCount;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- DWORD cb = dwCount + (fLast ? 16 : 0); // account for an extra padding block that will be added by CAPI
- DWORD cbPartial = (dwCount % BLOCK_LEN);
-
- // Do this check here as a sanity check. Also, this will catch bugs in CryptoAPITransform
- if (dwOffset < 0 || dwCount < 0 || dwCount > (INT32) gc.data->GetNumComponents() || dwOffset > ((INT32) gc.data->GetNumComponents() - dwCount))
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- NewArrayHolder<BYTE> pb(new BYTE[cb]);
-
- // initialize memory
- memset(pb, 0, cb);
- memcpy(pb, dwOffset + (LPBYTE) gc.data->GetDirectPointerToNonObjectElements(), dwCount);
-
- {
- SafeHandleHolder shh(&gc.hKeySAFE);
- CRYPT_KEY_CTX * pKeyCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_KEY_CTX>(gc.hKeySAFE);
- _ASSERTE(pKeyCtx->m_pProvCtx);
- CRYPT_PROV_CTX * pProvCtx = pKeyCtx->m_pProvCtx;
-
- // Deal with padding modes by hand: we need this because Crypto API only supports PKCS#5 padding
- if (fLast) {
- DWORD dwPadLen = BLOCK_LEN - cbPartial;
- switch(dwPaddingMode) {
- case CRYPTO_PADDING_NONE:
- if (cbPartial > 0)
- COMPlusThrow(kCryptographicException, W("Cryptography_SSE_InvalidDataSize"));
- break;
- case CRYPTO_PADDING_Zeros:
- // no further processing required, just adjust the input count
- // we don't add zeros if we've got a full number of blocks
- if (cbPartial != 0)
- cb2 += dwPadLen;
- break;
- case CRYPTO_PADDING_PKCS5:
- // PKCS5 padding is as follows: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07
- cb2 += dwPadLen;
- for (DWORD index = dwCount; index < cb2; index++)
- pb[index] = static_cast<BYTE>(dwPadLen);
- break;
- case CRYPTO_PADDING_ISO_10126:
- // The padding is as follows: FF FF FF FF FF FF FF FF FF 7D 2A 75 EF F8 EF 07
- cb2 += dwPadLen;
- {
- GCX_PREEMP();
- // get some random bytes
- if (!CryptGenRandom(pProvCtx->m_hProv, dwPadLen-1, pb+dwCount)) {
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- }
- pb[cb2 - 1] = static_cast<BYTE>(dwPadLen);
- break;
- case CRYPTO_PADDING_ANSI_X_923:
- // The padding is as follows: FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 07
- cb2 += dwPadLen;
- for (DWORD index = dwCount; index < cb2-1; index++)
- pb[index] = 0;
- pb[cb2 - 1] = static_cast<BYTE>(dwPadLen);
- break;
- }
- }
-
- {
- GCX_PREEMP();
- // We have done the padding ourselves, so let's just pass the provided fLast flag
- // so we ensure the key is initialized for future use
- if (!CryptEncrypt(pKeyCtx->m_hKey, NULL, fLast, 0, pb, &cb2, cb))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- }
-
- // ignore the last padding block added by CAPI
- if (fLast) cb2 -= BLOCK_LEN;
-
- if (gc.output == NULL) {
- gc.output = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb2);
- memcpyNoGCRefs(gc.output->GetDirectPointerToNonObjectElements(), pb, cb2);
- SetObjectReference((OBJECTREF*) outputUNSAFE, (OBJECTREF) gc.output, gc.output->GetAppDomain());
- } else {
- if (dwOutputOffset < 0 || (INT32) cb2 < 0 || cb2 > gc.output->GetNumComponents() || dwOutputOffset > ((INT32) gc.output->GetNumComponents() - (INT32) cb2))
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- memcpyNoGCRefs(dwOutputOffset + (LPBYTE) gc.output->GetDirectPointerToNonObjectElements(), pb, cb2);
- }
-
- HELPER_METHOD_FRAME_END();
- return cb2;
-}
-FCIMPLEND
-
-
-//---------------------------------------------------------------------------------------
-//
-// Encrypt a symmetric key using the public key in pKeyContext
-//
-// Arguments:
-// pKeyContext - [in] public to encrypt pbKey with
-// pbKey - [in] symmetric key to encrypt
-// cbKey - size, in bytes, of pbKey
-// fOAEP - TRUE to use OAEP padding, FALSE to use PKCS #1 type 2 padding
-// ohRetEncryptedKey - [out] byte array holding the encrypted key
-//
-// Notes:
-// The returned value in ohRetEncryptedKey is byte-reversed from the version CAPI gives us. This is for
-// compatibility with previous releases of the CLR and other RSA implementations.
-//
-// This method is the target of the EncryptKey QCall in System.Security.Cryptography.RSACryptoServiceProvider.
-//
-
-// static
-void QCALLTYPE COMCryptography::EncryptKey(__in CRYPT_KEY_CTX *pKeyContext,
- __in_bcount(cbKey) BYTE *pbKey,
- DWORD cbKey,
- BOOL fOAEP,
- QCall::ObjectHandleOnStack ohRetEncryptedKey)
-{
- CONTRACTL
- {
- QCALL_CHECK;
- PRECONDITION(CheckPointer(pKeyContext));
- PRECONDITION(CheckPointer(pbKey));
- PRECONDITION(cbKey >= 0);
- }
- CONTRACTL_END;
-
- BEGIN_QCALL;
-
- DWORD dwEncryptFlags = fOAEP ? CRYPT_OAEP : 0;
-
- // Figure out how big the encrypted key will be
- DWORD cbEncryptedKey = cbKey;
- if (!CryptEncrypt(pKeyContext->m_hKey, NULL, TRUE, dwEncryptFlags, NULL, &cbEncryptedKey, cbEncryptedKey))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // pbData is an in/out buffer for CryptEncrypt. allocate space for the encrypted key, and copy the
- // plaintext key into that space. Since encrypted keys will have padding applied, the size of the encrypted
- // key should always be larger than the plaintext key, so use that to determine the buffer size.
- _ASSERTE(cbEncryptedKey >= cbKey);
- NewArrayHolder<BYTE> pbEncryptedKey = new BYTE[cbEncryptedKey];
- memcpy_s(pbEncryptedKey, cbEncryptedKey, pbKey, cbKey);
-
- // Encrypt for real - the last parameter is the total size of the in/out buffer, while the second to last
- // parameter specifies the size of the plaintext to encrypt.
- if (!CryptEncrypt(pKeyContext->m_hKey, NULL, TRUE, dwEncryptFlags, pbEncryptedKey, &cbKey, cbEncryptedKey))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- _ASSERTE(cbKey == cbEncryptedKey);
- CryptoHelper::memrev(pbEncryptedKey, cbEncryptedKey);
- ohRetEncryptedKey.SetByteArray(pbEncryptedKey, cbEncryptedKey);
- END_QCALL;
-}
-
-
-void QCALLTYPE COMCryptography::EndHash(CRYPT_HASH_CTX * pHashCtx, QCall::ObjectHandleOnStack retHash)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- DWORD cbHash = 0;
- DWORD cbHashCount = sizeof(cbHash);
- if (!CryptGetHashParam(pHashCtx->m_hHash, HP_HASHSIZE, reinterpret_cast<BYTE *>(&cbHash), &cbHashCount, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- NewArrayHolder<BYTE> pb = new BYTE[cbHash];
- if (!CryptGetHashParam(pHashCtx->m_hHash, HP_HASHVAL, pb, &cbHash, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- retHash.SetByteArray(pb, cbHash);
-
- END_QCALL;
-}
-
-//
-// Exports key information of an RSACryptoServiceProvider/DSACryptoServiceProvider into a CAPI key blob (PKCS#1 format).
-//
-
-void QCALLTYPE COMCryptography::ExportCspBlob(CRYPT_KEY_CTX * pKeyCtx, DWORD dwBlobType, QCall::ObjectHandleOnStack retBlob)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- HRESULT hr = S_OK;
- NewArrayHolder<BYTE> pbRawData(NULL);
- DWORD cbRawData = 0;
-
- if (!CryptExportKey(pKeyCtx->m_hKey, NULL, dwBlobType, 0, NULL, &cbRawData))
- hr = HRESULT_FROM_GetLastError();
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::_ExportCspBlob failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- pbRawData = new BYTE[cbRawData];
- if (!CryptExportKey(pKeyCtx->m_hKey, NULL, dwBlobType, 0, pbRawData, &cbRawData))
- hr = HRESULT_FROM_GetLastError();
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::_ExportCspBlob failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- retBlob.SetByteArray(pbRawData, cbRawData);
-
- END_QCALL;
-}
-
-//
-// _ExportKey
-//
-
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
-#endif
-FCIMPL3(void, COMCryptography::_ExportKey, SafeHandle* hKeyUNSAFE, DWORD dwBlobType, Object* theKeyUNSAFE)
-{
- FCALL_CONTRACT;
-
- HRESULT hr = S_OK;
- OBJECTREF theKey = (OBJECTREF) theKeyUNSAFE;
- SAFEHANDLE hKeySAFE = (SAFEHANDLE) hKeyUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_2(theKey, hKeySAFE);
-
- DWORD cb;
- BOOL f;
- DWORD dwFlags = 0;
- NewArrayHolder<BYTE> pb(NULL);
-
- struct __LocalGCR {
- RSA_CSPREF rsaKey;
- DSA_CSPREF dsaKey;
- } _gcr;
-
- _gcr.rsaKey = NULL;
- _gcr.dsaKey = NULL;
-
- {
- SafeHandleHolder shh(&hKeySAFE);
- CRYPT_KEY_CTX * pKeyCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_KEY_CTX>(hKeySAFE);
- _ASSERTE(pKeyCtx);
- {
- GCX_PREEMP();
- // calg
- ALG_ID dwCalg;
- cb = sizeof(dwCalg);
- if (CryptGetKeyParam(pKeyCtx->m_hKey, KP_ALGID, (LPBYTE) &dwCalg, &cb, 0)) {
- // We need to add the VER3 handle for DH and DSS keys so that we can
- // get the fullest possible amount of information.
- if (dwCalg == CALG_DSS_SIGN)
- dwFlags |= CRYPT_BLOB_VER3;
- }
-retry:
- f = CryptExportKey(pKeyCtx->m_hKey, NULL, dwBlobType, dwFlags, NULL, &cb);
- if (!f) {
- if (dwFlags & CRYPT_BLOB_VER3) {
- dwFlags &= ~CRYPT_BLOB_VER3;
- goto retry;
- }
- hr = HRESULT_FROM_GetLastError();
- }
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO100, "Error [%#x]: COMCryptography::_ExportKey failed.\n", hr));
- goto lExit;
- }
-
- pb = new BYTE[cb];
- if (!CryptExportKey(pKeyCtx->m_hKey, NULL, dwBlobType, dwFlags, pb, &cb))
- hr = HRESULT_FROM_GetLastError();
- }
- }
-
- DWORD cbMalloced = cb;
- LPBYTE pbX = NULL;
- DWORD cbKey = 0;
-
- GCPROTECT_BEGIN(_gcr);
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::_ExportKey failed.\n", hr));
- goto Exit;
- }
-
- BLOBHEADER * pblob = (BLOBHEADER *) pb.GetValue();
- KEY_HEADER * pKeyInfo = NULL;
-
- switch (pblob->aiKeyAlg) {
- case CALG_RSA_KEYX:
- case CALG_RSA_SIGN:
- VALIDATEOBJECTREF(theKey);
- _gcr.rsaKey = (RSA_CSPREF) theKey;
-
- if (dwBlobType == PUBLICKEYBLOB) {
- pKeyInfo = (KEY_HEADER *) pb.GetValue();
- cb = (pKeyInfo->rsa.bitlen/8);
-
- pbX = pb + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY);
-
- // Exponent
- NewArrayHolder<BYTE> pbExponent(NULL);
- DWORD cbExponent = 0;
- ConvertIntToByteArray(pKeyInfo->rsa.pubexp, &pbExponent, &cbExponent);
- OBJECTREF arrayExponent = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbExponent);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_Exponent,
- arrayExponent,
- _gcr.rsaKey->GetAppDomain());
- memcpyNoGCRefs(_gcr.rsaKey->m_Exponent->GetDirectPointerToNonObjectElements(), pbExponent, cbExponent);
-
- // Modulus
- OBJECTREF arrayModulus = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_Modulus,
- arrayModulus,
- _gcr.rsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cb);
- memcpyNoGCRefs(_gcr.rsaKey->m_Modulus->GetDirectPointerToNonObjectElements(),
- pbX, cb);
- pbX += cb;
- }
- else if (dwBlobType == PRIVATEKEYBLOB) {
- pKeyInfo = (KEY_HEADER *) pb.GetValue();
- cb = (pKeyInfo->rsa.bitlen/8);
- DWORD cbHalfModulus = (cb + 1)/2;
-
- pbX = pb + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY);
-
- // Exponent
- NewArrayHolder<BYTE> pbExponent(NULL);
- DWORD cbExponent = 0;
- ConvertIntToByteArray(pKeyInfo->rsa.pubexp, &pbExponent, &cbExponent);
- OBJECTREF arrayExponent = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbExponent);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_Exponent,
- arrayExponent,
- _gcr.rsaKey->GetAppDomain());
- memcpyNoGCRefs(_gcr.rsaKey->m_Exponent->GetDirectPointerToNonObjectElements(), pbExponent, cbExponent);
-
- // Modulus
- OBJECTREF arrayModulus = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_Modulus,
- arrayModulus,
- _gcr.rsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cb);
- memcpyNoGCRefs(_gcr.rsaKey->m_Modulus->GetDirectPointerToNonObjectElements(),
- pbX, cb);
- pbX += cb;
-
- // P
- OBJECTREF arrayP = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbHalfModulus);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_P,
- arrayP,
- _gcr.rsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbHalfModulus);
- memcpyNoGCRefs(_gcr.rsaKey->m_P->GetDirectPointerToNonObjectElements(),
- pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // Q
- OBJECTREF arrayQ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbHalfModulus);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_Q,
- arrayQ,
- _gcr.rsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbHalfModulus);
- memcpyNoGCRefs(_gcr.rsaKey->m_Q->GetDirectPointerToNonObjectElements(),
- pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // dp
- OBJECTREF arrayDP = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbHalfModulus);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_dp,
- arrayDP,
- _gcr.rsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbHalfModulus);
- memcpyNoGCRefs(_gcr.rsaKey->m_dp->GetDirectPointerToNonObjectElements(),
- pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // dq
- OBJECTREF arrayDQ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbHalfModulus);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_dq,
- arrayDQ,
- _gcr.rsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbHalfModulus);
- memcpyNoGCRefs(_gcr.rsaKey->m_dq->GetDirectPointerToNonObjectElements(),
- pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // InvQ
- OBJECTREF arrayInverseQ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbHalfModulus);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_InverseQ,
- arrayInverseQ,
- _gcr.rsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbHalfModulus);
- memcpyNoGCRefs(_gcr.rsaKey->m_InverseQ->GetDirectPointerToNonObjectElements(),
- pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // d
- OBJECTREF arrayD = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb);
- SetObjectReference((OBJECTREF *) &_gcr.rsaKey->m_d,
- arrayD,
- _gcr.rsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cb);
- memcpyNoGCRefs(_gcr.rsaKey->m_d->GetDirectPointerToNonObjectElements(),
- pbX, cb);
- pbX += cb;
- }
- else {
- hr = E_FAIL;
- goto Exit;
- }
- break;
-
- case CALG_DSS_SIGN:
- _gcr.dsaKey = (DSA_CSPREF) theKey;
- // we have to switch on whether the blob is v3 or not, because we have different
- // info available if it is...
- if (pblob->bVersion > 0x2) {
- if (dwBlobType == PUBLICKEYBLOB) {
- int cbP, cbQ, cbJ;
- DSSPUBKEY_VER3 * pdss;
-
- pdss = (DSSPUBKEY_VER3 *) (pb + sizeof(BLOBHEADER));
- cbP = (pdss->bitlenP+7)/8;
- cbQ = (pdss->bitlenQ+7)/8;
- cbJ = (pdss->bitlenJ+7)/8;
- pbX = pb + sizeof(BLOBHEADER) + sizeof(DSSPUBKEY_VER3);
-
- // P
- OBJECTREF arrayP = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_P, arrayP, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_P->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // Q
- OBJECTREF arrayQ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbQ);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_Q, arrayQ, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbQ);
- memcpyNoGCRefs(_gcr.dsaKey->m_Q->GetDirectPointerToNonObjectElements(), pbX, cbQ);
- pbX += cbQ;
-
- // G
- OBJECTREF arrayG = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_G, arrayG, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_G->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // J
- if (cbJ > 0) {
- OBJECTREF arrayJ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbJ);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_J, arrayJ, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbJ);
- memcpyNoGCRefs(_gcr.dsaKey->m_J->GetDirectPointerToNonObjectElements(), pbX, cbJ);
- pbX += cbJ;
- }
-
- // Y
- OBJECTREF arrayY = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_Y, arrayY, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_Y->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- if (pdss->DSSSeed.counter != 0xFFFFFFFF) {
- // seed
- OBJECTREF arraySeed = AllocatePrimitiveArray(ELEMENT_TYPE_U1, 20);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_seed, arraySeed, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pdss->DSSSeed.seed, 20);
- memcpyNoGCRefs(_gcr.dsaKey->m_seed->GetDirectPointerToNonObjectElements(), pdss->DSSSeed.seed, 20);
- // pdss->DSSSeed.c
- _gcr.dsaKey->m_counter = pdss->DSSSeed.counter;
- }
- }
- else {
- int cbP, cbQ, cbJ, cbX;
- DSSPRIVKEY_VER3 * pdss;
-
- pdss = (DSSPRIVKEY_VER3 *) (pb + sizeof(BLOBHEADER));
- cbP = (pdss->bitlenP+7)/8;
- cbQ = (pdss->bitlenQ+7)/8;
- cbJ = (pdss->bitlenJ+7)/8;
- cbX = (pdss->bitlenX+7)/8;
- pbX = pb + sizeof(BLOBHEADER) + sizeof(DSSPRIVKEY_VER3);
-
- // P
- OBJECTREF arrayP = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_P, arrayP, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_P->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // Q
- OBJECTREF arrayQ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbQ);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_Q, arrayQ, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbQ);
- memcpyNoGCRefs(_gcr.dsaKey->m_Q->GetDirectPointerToNonObjectElements(), pbX, cbQ);
- pbX += cbQ;
-
- // G
- OBJECTREF arrayG = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_G, arrayG, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_G->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // J
- if (pdss->bitlenJ > 0) {
- OBJECTREF arrayJ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbJ);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_J, arrayJ, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbJ);
- memcpyNoGCRefs(_gcr.dsaKey->m_J->GetDirectPointerToNonObjectElements(), pbX, cbJ);
- pbX += cbJ;
- }
-
- // Y
- OBJECTREF arrayY = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_Y, arrayY, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_Y->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // X
- OBJECTREF arrayX = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbX);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_X, arrayX, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbX);
- memcpyNoGCRefs(_gcr.dsaKey->m_X->GetDirectPointerToNonObjectElements(), pbX, cbX);
- pbX += cbX;
-
- if (pdss->DSSSeed.counter != 0xFFFFFFFF) {
- // seed
- OBJECTREF arraySeed = AllocatePrimitiveArray(ELEMENT_TYPE_U1, 20);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_seed, arraySeed, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pdss->DSSSeed.seed, 20);
- memcpyNoGCRefs(_gcr.dsaKey->m_seed->GetDirectPointerToNonObjectElements(), pdss->DSSSeed.seed, 20);
- // pdss->DSSSeed.c
- _gcr.dsaKey->m_counter = pdss->DSSSeed.counter;
- }
- }
- } else {
- // old-style blobs
- if (dwBlobType == PUBLICKEYBLOB) {
- int cbP, cbQ;
- DSSPUBKEY * pdss;
- DSSSEED * pseedstruct;
-
- pdss = (DSSPUBKEY *) (pb + sizeof(BLOBHEADER));
- cbP = (pdss->bitlen+7)/8; // bitlen is size of modulus
- cbQ = DSS_Q_LEN; // Q is always 20 bytes in length
- pbX = pb + sizeof(BLOBHEADER) + sizeof(DSSPUBKEY);
-
- // P
- OBJECTREF arrayP = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_P, arrayP, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_P->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // Q
- OBJECTREF arrayQ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbQ);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_Q, arrayQ, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbQ);
- memcpyNoGCRefs(_gcr.dsaKey->m_Q->GetDirectPointerToNonObjectElements(), pbX, cbQ);
- pbX += cbQ;
-
- // G
- OBJECTREF arrayG = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_G, arrayG, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_G->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // Y
- OBJECTREF arrayY = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_Y, arrayY, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_Y->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- pseedstruct = (DSSSEED *) pbX;
- if (pseedstruct->counter > 0) {
- // seed & counter
- OBJECTREF arraySeed = AllocatePrimitiveArray(ELEMENT_TYPE_U1, 20);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_seed, arraySeed, _gcr.dsaKey->GetAppDomain());
- // seed is always 20 bytes
- CryptoHelper::memrev(pseedstruct->seed, 20);
- memcpyNoGCRefs(_gcr.dsaKey->m_seed->GetDirectPointerToNonObjectElements(), pseedstruct->seed, 20);
- pbX += 20;
-
- // pdss->DSSSeed.c
- _gcr.dsaKey->m_counter = pseedstruct->counter;
- pbX += sizeof(DWORD);
- }
- }
- else {
- int cbP, cbQ, cbX;
- DSSPUBKEY * pdss;
- DSSSEED * pseedstruct;
-
- pdss = (DSSPUBKEY *) (pb + sizeof(BLOBHEADER));
- cbP = (pdss->bitlen+7)/8; //bitlen is size of modulus
- cbQ = DSS_Q_LEN; // Q is always 20 bytes in length
- pbX = pb + sizeof(BLOBHEADER) + sizeof(DSSPUBKEY);
-
- // P
- OBJECTREF arrayP = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_P, arrayP, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_P->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // Q
- OBJECTREF arrayQ = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbQ);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_Q, arrayQ, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbQ);
- memcpyNoGCRefs(_gcr.dsaKey->m_Q->GetDirectPointerToNonObjectElements(), pbX, cbQ);
- pbX += cbQ;
-
- // G
- OBJECTREF arrayG = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_G, arrayG, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_G->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
-
- // X
- cbX = 20; // X must be 20 bytes in length
- OBJECTREF arrayX = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbX);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_X, arrayX, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbX);
- memcpyNoGCRefs(_gcr.dsaKey->m_X->GetDirectPointerToNonObjectElements(), pbX, cbX);
- pbX += cbX;
-
- pseedstruct = (DSSSEED *) pbX;
- if (pseedstruct->counter > 0) {
- // seed
- OBJECTREF arraySeed = AllocatePrimitiveArray(ELEMENT_TYPE_U1, 20);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_seed, arraySeed, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pseedstruct->seed, 20);
- memcpyNoGCRefs(_gcr.dsaKey->m_seed->GetDirectPointerToNonObjectElements(), pseedstruct->seed, 20);
- pbX += 20;
- // pdss->DSSSeed.c
- _gcr.dsaKey->m_counter = pseedstruct->counter;
- pbX += sizeof(DWORD);
- }
-
- // Add this sanity check here to avoid reading from the heap
- cbKey = (DWORD)(pbX - pb);
- if (cbKey > cbMalloced) {
- hr = E_FAIL;
- goto Exit;
- }
-
- // OK, we have one more thing to do. Because old DSS shared the DSSPUBKEY struct for both public and private keys,
- // when we have a private key blob we get X but not Y. TO get Y, we have to do another export asking for a public key blob
-
- {
- SafeHandleHolder shh(&hKeySAFE);
- CRYPT_KEY_CTX * pKeyCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_KEY_CTX>(hKeySAFE);
- {
- GCX_PREEMP();
- f = CryptExportKey(pKeyCtx->m_hKey, NULL, PUBLICKEYBLOB, dwFlags, NULL, &cb);
-
- if (!f) {
- hr = HRESULT_FROM_GetLastError();
- goto Exit;
- }
-
- pb = new BYTE[cb];
- cbMalloced = cb;
-
- f = CryptExportKey(pKeyCtx->m_hKey, NULL, PUBLICKEYBLOB, dwFlags, pb, &cb);
- if (!f) {
- hr = HRESULT_FROM_GetLastError();
- goto Exit;
- }
- }
- }
-
- // skip over header, DSSPUBKEY, P, Q and G. Y is of size cbP
- pbX = pb + sizeof(BLOBHEADER) + sizeof(DSSPUBKEY) + cbP + cbQ + cbP;
- OBJECTREF arrayY = AllocatePrimitiveArray(ELEMENT_TYPE_U1, cbP);
- SetObjectReference((OBJECTREF *) &_gcr.dsaKey->m_Y, arrayY, _gcr.dsaKey->GetAppDomain());
- CryptoHelper::memrev(pbX, cbP);
- memcpyNoGCRefs(_gcr.dsaKey->m_Y->GetDirectPointerToNonObjectElements(), pbX, cbP);
- pbX += cbP;
- }
- }
- break;
-
- default:
- hr = E_FAIL;
- goto Exit;
- }
-
- // Add this sanity check here to avoid reading from the heap
- cbKey = (DWORD)(pbX - pb);
- if (cbKey > cbMalloced) {
- hr = E_FAIL;
- goto Exit;
- }
-
- hr = S_OK;
-
-Exit: ;
- GCPROTECT_END();
-
-lExit:
-
- if (FAILED(hr))
- CryptoHelper::COMPlusThrowCrypto(hr);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
-//
-// We implicitly assume these methods are not going to do a LoadLibrary
-//
-
-
-//---------------------------------------------------------------------------------------
-//
-// Release our handle to a hash, potentially also releasing the provider
-//
-// Arguments:
-// pHashContext - Hash context to release
-//
-// Notes:
-// This is the target of the System.Security.Cryptography.SafeHashHandle.FreeHash QCall
-//
-
-// static
-void QCALLTYPE COMCryptography::FreeHash(__in_opt CRYPT_HASH_CTX *pHashContext)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- if (pHashContext)
- pHashContext->Release();
-
- END_QCALL;
-}
-
-//---------------------------------------------------------------------------------------
-//
-// Release our handle to a key, potentially also releasing the provider
-//
-// Arguments:
-// pKeyContext - Key context to release
-//
-// Notes:
-// This is the target of the System.Security.Cryptography.SafeKeyHandle.FreeKey QCall
-//
-
-// static
-void QCALLTYPE COMCryptography::FreeKey(__in_opt CRYPT_KEY_CTX *pKeyContext)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- if (pKeyContext)
- pKeyContext->Release();
-
- END_QCALL;
-}
-
-//
-// Native method for creation of a key in a CSP
-//
-
-FCIMPL5(void, COMCryptography::_GenerateKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, DWORD dwFlags, DWORD dwKeySize, SafeHandle** hKeyUNSAFE)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE hProvSAFE = (SAFEHANDLE) hProvUNSAFE;
- SAFEHANDLE hKeySAFE = (SAFEHANDLE) *hKeyUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_2(hProvSAFE, hKeySAFE);
-
- HandleKeyHolder hKey(NULL);
- CRYPT_PROV_CTX * pProvCtx = NULL;
- HRESULT hr = S_OK;
-
- {
- SafeHandleHolder shh(&hProvSAFE);
- pProvCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_PROV_CTX>(hProvSAFE);
- {
- GCX_PREEMP();
- DWORD dwCapiFlags = MapCspKeyFlags (dwFlags) | (dwKeySize << 16);
- if (!CryptoHelper::CryptGenKey_SO_TOLERANT(pProvCtx->m_hProv, dwCalg, dwCapiFlags, &hKey))
- hr = HRESULT_FROM_GetLastError();
- }
- }
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::_GenerateKey failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- CRYPT_KEY_CTX * pKeyCtx = new CRYPT_KEY_CTX(pProvCtx, hKey);
- pKeyCtx->m_dwKeySpec = dwCalg;
- hKeySAFE->SetHandle((void*) pKeyCtx);
- hKey.SuppressRelease();
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-
-//---------------------------------------------------------------------------------------
-//
-// Check to see if the CLR should enforce the machine wide FIPS algorithm policy
-//
-// Return Value:
-// True if the CLR should prevent any non-FIPS certified algorithms from being
-// instantiated if the FIPS algorithm policy is set on the machine, false otherwise.
-//
-
-FCIMPL0(FC_BOOL_RET, COMCryptography::_GetEnforceFipsPolicySetting)
-{
- FCALL_CONTRACT;
- FC_RETURN_BOOL(g_pConfig->EnforceFIPSPolicy());
-}
-FCIMPLEND
-
-//
-// This method acquires key specific parameters.
-// It will pop up a UI if the key is user protected.
-//
-
-FCIMPL2(U1Array*, COMCryptography::_GetKeyParameter, SafeHandle* hKeyUNSAFE, DWORD dwKeyParam)
-{
- FCALL_CONTRACT;
-
- U1ARRAYREF ret = NULL;
- SAFEHANDLE hKeySAFE = (SAFEHANDLE) hKeyUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(ret, hKeySAFE);
-
- DWORD cb = 0;
- NewArrayHolder<BYTE> pb(NULL);
- NewArrayHolder<WCHAR> pwszUnicode(NULL);
-
- SafeHandleHolder shh(&hKeySAFE);
- CRYPT_KEY_CTX * pKeyCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_KEY_CTX>(hKeySAFE);
- switch (dwKeyParam) {
- case CLR_KEYLEN:
- // Some Csp's may pop up a UI here since we don't use CRYPT_SILENT flag
- // which is not supported in downlevel platforms
- if (!CryptGetKeyParam(pKeyCtx->m_hKey, KP_KEYLEN, NULL, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- pb = new BYTE[cb];
- if (!CryptGetKeyParam(pKeyCtx->m_hKey, KP_KEYLEN, pb, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- CryptoHelper::ByteArrayToU1ARRAYREF(pb, cb, &ret);
- break;
-
- case CLR_PUBLICKEYONLY:
- // returns whether the key is a public only key
- pb = new BYTE[4];
- *((DWORD*) pb.GetValue()) = pKeyCtx->m_fPublicOnly;
- CryptoHelper::ByteArrayToU1ARRAYREF(pb, 4, &ret);
- break;
-
- case CLR_ALGID:
- // returns the algorithm ID for the key
- if (!CryptGetKeyParam(pKeyCtx->m_hKey, KP_ALGID, NULL, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- pb = new BYTE[cb];
- if (!CryptGetKeyParam(pKeyCtx->m_hKey, KP_ALGID, pb, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- CryptoHelper::ByteArrayToU1ARRAYREF(pb, cb, &ret);
- break;
-
- default:
- _ASSERTE(FALSE);
- }
-
- HELPER_METHOD_FRAME_END();
- return (U1Array*) OBJECTREFToObject(ret);
-}
-FCIMPLEND
-
-//
-// _GetKeySetSecurityInfo
-//
-
-FCIMPL3(U1Array*, COMCryptography::_GetKeySetSecurityInfo, SafeHandle* hProvUNSAFE, DWORD dwSecurityInformation, DWORD* pdwErrorCode)
-{
- FCALL_CONTRACT;
-
- U1ARRAYREF ret = NULL;
- SAFEHANDLE hProvSAFE = (SAFEHANDLE) hProvUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_1(hProvSAFE);
-
- SafeHandleHolder shh(&hProvSAFE);
- CRYPT_PROV_CTX * pProvCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_PROV_CTX>(hProvSAFE);
-
- DWORD cb = 0;
- NewHolder<BYTE> pSD(NULL);
- *pdwErrorCode = 0;
- if (!CryptGetProvParam(pProvCtx->m_hProv, PP_KEYSET_SEC_DESCR, NULL, &cb, dwSecurityInformation)) {
- *pdwErrorCode = GetLastError();
- goto Error;
- }
-
- pSD = new BYTE[cb];
- if (!CryptGetProvParam(pProvCtx->m_hProv, PP_KEYSET_SEC_DESCR, pSD, &cb, dwSecurityInformation)) {
- *pdwErrorCode = GetLastError();
- goto Error;
- }
-
- if (pSD != NULL)
- CryptoHelper::ByteArrayToU1ARRAYREF(pSD, cb, &ret);
-
-Error:;
-
- HELPER_METHOD_FRAME_END();
- return (U1Array*) OBJECTREFToObject(ret);
-}
-FCIMPLEND
-
-
-BOOL QCALLTYPE COMCryptography::GetPersistKeyInCsp(CRYPT_PROV_CTX * pProvCtx)
-{
- QCALL_CONTRACT;
-
- BOOL fResult = TRUE;
-
- BEGIN_QCALL;
-
- fResult = pProvCtx->m_fPersistKeyInCsp;
-
- END_QCALL;
-
- return fResult;
-}
-
-//
-// This method queries the key container and gets some of its properties.
-// Those properties should never cause a UI to display.
-//
-
-FCIMPL3(Object*, COMCryptography::_GetProviderParameter, SafeHandle* hProvUNSAFE, DWORD dwKeySpec, DWORD dwKeyParam)
-{
- FCALL_CONTRACT;
-
- OBJECTREF ret = NULL;
- SAFEHANDLE hProvSAFE = (SAFEHANDLE) hProvUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(ret, hProvSAFE);
-
- DWORD cb = 0;
- NewArrayHolder<BYTE> pb(NULL);
- NewArrayHolder<WCHAR> pwszUnicode(NULL);
- DWORD dwImpType = 0;
- HandleKeyHolder hKey(NULL);
-
- SafeHandleHolder shh(&hProvSAFE);
- CRYPT_PROV_CTX * pProvCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_PROV_CTX>(hProvSAFE);
-
- switch (dwKeyParam) {
- case CLR_EXPORTABLE:
- cb = sizeof(dwImpType);
- if (!CryptGetProvParam(pProvCtx->m_hProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- if (!(dwImpType & CRYPT_IMPL_HARDWARE)) {
- if (!CryptGetUserKey(pProvCtx->m_hProv, dwKeySpec, &hKey))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- DWORD dwPermissions;
- dwPermissions = 0;
- cb = sizeof(dwPermissions);
- if (!CryptGetKeyParam(hKey, KP_PERMISSIONS, (PBYTE) &dwPermissions, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- pb = new BYTE[4];
- *((DWORD*) pb.GetValue()) = dwPermissions & CRYPT_EXPORT ? 1 : 0;
- } else {
- // We assume hardware keys are not exportable
- pb = new BYTE[4];
- *((DWORD*) pb.GetValue()) = 0;
- }
- CryptoHelper::ByteArrayToU1ARRAYREF(pb, 4, (U1ARRAYREF*) &ret);
- break;
-
- case CLR_REMOVABLE:
- cb = sizeof(dwImpType);
- if (!CryptGetProvParam(pProvCtx->m_hProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- pb = new BYTE[4];
- *((DWORD*) pb.GetValue()) = dwImpType & CRYPT_IMPL_REMOVABLE ? 1 : 0;
- CryptoHelper::ByteArrayToU1ARRAYREF(pb, 4, (U1ARRAYREF*) &ret);
- break;
-
- case CLR_HARDWARE:
- cb = sizeof(dwImpType);
- if (!CryptGetProvParam(pProvCtx->m_hProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- pb = new BYTE[4];
- *((DWORD*) pb.GetValue()) = dwImpType & CRYPT_IMPL_HARDWARE ? 1 : 0;
- CryptoHelper::ByteArrayToU1ARRAYREF(pb, 4, (U1ARRAYREF*) &ret);
- break;
-
- case CLR_ACCESSIBLE:
- pb = new BYTE[4];
- *((DWORD*) pb.GetValue()) = CryptGetUserKey(pProvCtx->m_hProv, dwKeySpec, &hKey) ? 1 : 0;
- CryptoHelper::ByteArrayToU1ARRAYREF(pb, 4, (U1ARRAYREF*) &ret);
- break;
-
- case CLR_PROTECTED:
- cb = sizeof(dwImpType);
- if (!CryptGetProvParam(pProvCtx->m_hProv, PP_IMPTYPE, (PBYTE) &dwImpType, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- BOOL isProtected;
- if (dwImpType & CRYPT_IMPL_HARDWARE) {
- // Assume hardware keys are protected
- isProtected = TRUE;
- } else {
- isProtected = FALSE;
- }
-
- pb = new BYTE[4];
- *((DWORD*) pb.GetValue()) = isProtected;
- CryptoHelper::ByteArrayToU1ARRAYREF(pb, 4, (U1ARRAYREF*) &ret);
- break;
-
- case CLR_UNIQUE_CONTAINER:
- if (!CryptGetProvParam(pProvCtx->m_hProv, PP_UNIQUE_CONTAINER, NULL, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- pb = new BYTE[cb];
- if (!CryptGetProvParam(pProvCtx->m_hProv, PP_UNIQUE_CONTAINER, pb, &cb, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- pwszUnicode = CryptoHelper::AnsiToUnicode((char*) pb.GetValue());
- ret = StringObject::NewString(pwszUnicode);
- break;
-
- default:
- _ASSERTE(FALSE);
- }
-
- HELPER_METHOD_FRAME_END();
- return OBJECTREFToObject(ret);
-}
-FCIMPLEND
-
-//
-// _GetUserKey
-//
-// Native method to get the user key pair of a key container
-//
-
-FCIMPL3(HRESULT, COMCryptography::_GetUserKey, SafeHandle* hProvUNSAFE, DWORD dwKeySpec, SafeHandle** hKeyUNSAFE)
-{
- FCALL_CONTRACT;
-
- HRESULT hr = S_OK;
-
- SAFEHANDLE hProvSAFE = (SAFEHANDLE) hProvUNSAFE;
- SAFEHANDLE hKeySAFE = (SAFEHANDLE) *hKeyUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(hProvSAFE, hKeySAFE);
-
- HandleKeyHolder hKey(NULL);
- CRYPT_PROV_CTX * pProvCtx = NULL;
- {
- SafeHandleHolder shh(&hProvSAFE);
- pProvCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_PROV_CTX>(hProvSAFE);
- {
- GCX_PREEMP();
- if (!CryptGetUserKey(pProvCtx->m_hProv, dwKeySpec, &hKey))
- hr = HRESULT_FROM_GetLastError();
- }
- }
-
- if (hr == S_OK) {
- CRYPT_KEY_CTX * pKeyCtx = new CRYPT_KEY_CTX(pProvCtx, hKey);
- pKeyCtx->m_dwKeySpec = dwKeySpec;
- hKeySAFE->SetHandle((void*) pKeyCtx);
- hKey.SuppressRelease();
- }
-
- LOG((LF_SECURITY, LL_INFO10000, "COMCryptography::_GetUserKey returned error code [%#x].\n", hr));
-
- HELPER_METHOD_FRAME_END();
- return hr;
-}
-FCIMPLEND
-
-void QCALLTYPE COMCryptography::HashData(CRYPT_HASH_CTX * pHashCtx, LPCBYTE pData, DWORD cbData, DWORD dwStart, DWORD dwSize)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- // Do this check here as a sanity check. Also, this will catch bugs in CryptoAPITransform
- if (dwStart < 0 || dwSize < 0 || dwSize > cbData || dwStart > (cbData - dwSize))
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- if (!CryptHashData(pHashCtx->m_hHash, pData + dwStart, dwSize, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- END_QCALL;
-}
-
-//
-// WARNING: This function side-effects hCSP
-//
-
-FCIMPL5(void, COMCryptography::_ImportBulkKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, CLR_BOOL useSalt, U1Array* rgbKeyUNSAFE, SafeHandle** hKeyUNSAFE)
-{
- FCALL_CONTRACT;
-
- struct _gc
- {
- U1ARRAYREF rgbKey;
- SAFEHANDLE hProvSAFE;
- SAFEHANDLE hKeySAFE;
- } gc;
-
- gc.rgbKey = (U1ARRAYREF) rgbKeyUNSAFE;
- gc.hProvSAFE = (SAFEHANDLE) hProvUNSAFE;
- gc.hKeySAFE = (SAFEHANDLE) *hKeyUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
-
- HandleKeyHolder hKey(NULL);
- DWORD cbKey = gc.rgbKey->GetNumComponents();
- NewArrayHolder<BYTE> buffer(new BYTE[cbKey]);
- memcpyNoGCRefs (buffer, (LPBYTE) gc.rgbKey->GetDirectPointerToNonObjectElements(), cbKey);
- CRYPT_PROV_CTX * pProvCtx = NULL;
- HRESULT hr = S_OK;
-
- {
- SafeHandleHolder shh(&gc.hProvSAFE);
- pProvCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_PROV_CTX>(gc.hProvSAFE);
- {
- GCX_PREEMP();
- // If we are running in rsabase.dll compatibility mode, make sure 11 bytes of
- // zero salt are generated when using a 40 bits RC2 key.
- DWORD dwFlags = (dwCalg == CALG_RC2 ? CRYPT_EXPORTABLE | CRYPT_NO_SALT : CRYPT_EXPORTABLE);
- if (useSalt && dwCalg == CALG_RC2)
- dwFlags &= ~CRYPT_NO_SALT;
- hr = LoadKey(buffer, cbKey, pProvCtx->m_hProv, dwCalg, dwFlags, &hKey);
- }
- }
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::_ImportBulkKey failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- CRYPT_KEY_CTX * pKeyCtx = new CRYPT_KEY_CTX(pProvCtx, hKey);
- gc.hKeySAFE->SetHandle((void*) pKeyCtx);
- hKey.SuppressRelease();
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// Imports a CSP blob into an RSACryptoServiceProvider/DSACryptoServiceProvider managed object. The blob format is CAPI key blob format (PKCS#1)
-//
-
-FCIMPL4(DWORD, COMCryptography::_ImportCspBlob, U1Array* rawDataUNSAFE, SafeHandle* hProvUNSAFE, DWORD dwFlags, SafeHandle** hKeyUNSAFE)
-{
- FCALL_CONTRACT;
-
- DWORD dwKeySpec = 0;
-
- struct _gc
- {
- U1ARRAYREF rawDataSAFE;
- SAFEHANDLE hProvSAFE;
- SAFEHANDLE hKeySAFE;
- } gc;
-
- gc.rawDataSAFE = (U1ARRAYREF) rawDataUNSAFE;
- gc.hProvSAFE = (SAFEHANDLE) hProvUNSAFE;
- gc.hKeySAFE = (SAFEHANDLE) *hKeyUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- CRYPT_PROV_CTX * pProvCtx = NULL;
- HandleKeyHolder hKey(NULL);
- HRESULT hr = S_OK;
-
- DWORD dwCapiFlags = MapCspKeyFlags (dwFlags);
-
- if (gc.rawDataSAFE == NULL)
- COMPlusThrowArgumentNull(W("rawData"));
-
- NewArrayHolder<BYTE> pbRawData(CryptoHelper::U1ARRAYREFToByteArray(gc.rawDataSAFE));
- DWORD cbRawData = gc.rawDataSAFE->GetNumComponents();
-
- PUBLICKEYSTRUC* pPubKeyStruc = (PUBLICKEYSTRUC*) pbRawData.GetValue();
- // If this is a public key, ignore the CRYPT_EXPORTABLE flag.
- if (pPubKeyStruc->bType == PUBLICKEYBLOB)
- dwCapiFlags &= ~CRYPT_EXPORTABLE;
-
- {
- SafeHandleHolder shh(&gc.hProvSAFE);
- pProvCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_PROV_CTX>(gc.hProvSAFE);
- {
- GCX_PREEMP();
- if (!CryptImportKey(pProvCtx->m_hProv, pbRawData, cbRawData, NULL, dwCapiFlags, &hKey))
- hr = HRESULT_FROM_GetLastError();
- }
- }
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::_ImportCspBlob failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- CRYPT_KEY_CTX * pKeyCtx = new CRYPT_KEY_CTX(pProvCtx, hKey);
- pKeyCtx->m_dwKeySpec = (pPubKeyStruc->aiKeyAlg == CALG_RSA_KEYX ? AT_KEYEXCHANGE : AT_SIGNATURE);
- pKeyCtx->m_fPublicOnly = (pPubKeyStruc->bType == PUBLICKEYBLOB ? TRUE : FALSE);
- gc.hKeySAFE->SetHandle((void*) pKeyCtx);
-
- dwKeySpec = pKeyCtx->m_dwKeySpec;
- hKey.SuppressRelease();
-
- HELPER_METHOD_FRAME_END();
- return dwKeySpec;
-}
-FCIMPLEND
-
-//
-// _ImportKey
-//
-
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
-#endif
-FCIMPL5(void, COMCryptography::_ImportKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, DWORD dwFlags, Object* refKeyUNSAFE, SafeHandle** hKeyUNSAFE)
-{
- FCALL_CONTRACT;
-
- struct _gc
- {
- OBJECTREF refKey;
- SAFEHANDLE hProvSAFE;
- SAFEHANDLE hKeySAFE;
- } gc;
-
- gc.refKey = (OBJECTREF) refKeyUNSAFE;
- gc.hProvSAFE = (SAFEHANDLE) hProvUNSAFE;
- gc.hKeySAFE = (SAFEHANDLE) *hKeyUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
-
- BOOL fPrivate = FALSE;
- HandleKeyHolder hKey(NULL);
- NewArrayHolder<BYTE> pbKey(NULL);
- DWORD cbKey = 0;
- LPBYTE pbX = NULL;
- KEY_HEADER* pKeyInfo = NULL;
-
- switch (dwCalg) {
- case CALG_DSS_SIGN: {
- DWORD cbP;
- DWORD cbQ;
- DWORD cbX = 0;
- DWORD cbJ = 0;
- DSA_CSPREF dssKey;
-
- VALIDATEOBJECTREF(gc.refKey);
- dssKey = (DSA_CSPREF) gc.refKey;
-
- // Validate the DSA structure first
- // P, Q and G are required. Q is a 160 bit divisor of P-1 and G is an element of Z_p
- if (dssKey->m_P == NULL || dssKey->m_Q == NULL || dssKey->m_Q->GetNumComponents() != DSS_Q_LEN)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- cbP = dssKey->m_P->GetNumComponents();
- cbQ = dssKey->m_Q->GetNumComponents();
- if (dssKey->m_G == NULL || dssKey->m_G->GetNumComponents() != cbP)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- // If J is present, it should be less than the size of P: J = (P-1) / Q
- // This is only a sanity check. Not doing it here is not really an issue as CAPI will fail.
- if (dssKey->m_J != NULL && dssKey->m_J->GetNumComponents() >= cbP)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- // Y is present for V3 DSA key blobs, Y = g^j mod P
- if (dssKey->m_Y != NULL && dssKey->m_Y->GetNumComponents() != cbP)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- // The seed is allways a 20 byte array
- if (dssKey->m_seed != NULL && dssKey->m_seed->GetNumComponents() != 20)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- // The private key is less than q-1
- if (dssKey->m_X != NULL && dssKey->m_X->GetNumComponents() != DSS_Q_LEN)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- // Compute size of data to include
- cbKey = 3*cbP + cbQ + sizeof(KEY_HEADER) + sizeof(DSSSEED);
- if (dssKey->m_X != 0) {
- cbX = dssKey->m_X->GetNumComponents();
- cbKey += cbX;
- }
- if (dssKey->m_J != NULL) {
- cbJ = dssKey->m_J->GetNumComponents();
- cbKey += cbJ;
- }
- pbKey = new BYTE[cbKey];
-
- // Public or Private import?
-
- pKeyInfo = (KEY_HEADER *) pbKey.GetValue();
- pKeyInfo->blob.bType = PUBLICKEYBLOB;
- pKeyInfo->blob.bVersion = CUR_BLOB_VERSION;
- pKeyInfo->blob.reserved = 0;
- pKeyInfo->blob.aiKeyAlg = dwCalg;
-
- if (cbX != 0) {
- pKeyInfo->blob.bType = PRIVATEKEYBLOB;
- fPrivate = TRUE;
- }
-
- //
- // If y is present and this is a private key, or
- // If y and J are present and this is a public key,
- // this should be a v3 blob
- //
- // make the assumption that if the item is present, there are bytes
-
- if (((dssKey->m_Y != NULL) && fPrivate) ||
- ((dssKey->m_Y != NULL) && (dssKey->m_J != NULL))) {
- pKeyInfo->blob.bVersion = 0x3;
- }
-
- pbX = pbKey + sizeof(pKeyInfo->blob);
- if (pKeyInfo->blob.bVersion == 0x3) {
- if (fPrivate) {
- pbX += sizeof(pKeyInfo->dss_priv_v3);
- pKeyInfo->dss_priv_v3.bitlenP = cbP*8;
- pKeyInfo->dss_priv_v3.bitlenQ = cbQ*8;
- pKeyInfo->dss_priv_v3.bitlenJ = cbJ*8;
- pKeyInfo->dss_priv_v3.bitlenX = cbX*8;
- pKeyInfo->dss_priv_v3.magic = DSS_PRIV_MAGIC_VER3;
- }
- else {
- pbX += sizeof(pKeyInfo->dss_pub_v3);
- pKeyInfo->dss_pub_v3.bitlenP = cbP*8;
- pKeyInfo->dss_pub_v3.bitlenQ = cbQ*8;
- pKeyInfo->dss_pub_v3.bitlenJ = cbJ*8;
- pKeyInfo->dss_pub_v3.magic = DSS_PUB_MAGIC_VER3;
- }
- }
- else {
- if (fPrivate) {
- pKeyInfo->dss_v2.magic = DSS_PRIVATE_MAGIC;
- }
- else {
- pKeyInfo->dss_v2.magic = DSS_MAGIC;
- }
- pKeyInfo->dss_v2.bitlen = cbP*8;
- pbX += sizeof(pKeyInfo->dss_v2);
- }
-
- // P
- memcpy(pbX, dssKey->m_P->GetDirectPointerToNonObjectElements(), cbP);
- CryptoHelper::memrev(pbX, cbP);
- pbX += cbP;
-
- // Q
- memcpy(pbX, dssKey->m_Q->GetDirectPointerToNonObjectElements(), cbQ);
- CryptoHelper::memrev(pbX, cbQ);
- pbX += cbQ;
-
- // G
- memcpy(pbX, dssKey->m_G->GetDirectPointerToNonObjectElements(), cbP);
- CryptoHelper::memrev(pbX, cbP);
- pbX += cbP;
-
- if (pKeyInfo->blob.bVersion == 0x3) {
- // J -- if present then bVersion == 3;
- if (dssKey->m_J != NULL) {
- memcpy(pbX, dssKey->m_J->GetDirectPointerToNonObjectElements(), cbJ);
- CryptoHelper::memrev(pbX, cbJ);
- pbX += cbJ;
- }
- }
-
- if (!fPrivate || (pKeyInfo->blob.bVersion == 0x3)) {
- // Y -- if present then bVersion == 3;
- if (dssKey->m_Y != NULL) {
- memcpy(pbX, dssKey->m_Y->GetDirectPointerToNonObjectElements(), cbP);
- CryptoHelper::memrev(pbX, cbP);
- pbX += cbP;
- }
- }
-
- // X -- if present then private
- if (fPrivate) {
- memcpy(pbX, dssKey->m_X->GetDirectPointerToNonObjectElements(), cbX);
- CryptoHelper::memrev(pbX, cbX);
- pbX += cbX;
- }
-
- if ((dssKey->m_seed == NULL) || (dssKey->m_seed->GetNumComponents() == 0)){
- // No seed present, so set them to zero
- if (pKeyInfo->blob.bVersion == 0x3) {
- if (fPrivate) {
- memset(&pKeyInfo->dss_priv_v3.DSSSeed, 0xFFFFFFFF, sizeof(DSSSEED));
- }
- else {
- memset(&pKeyInfo->dss_pub_v3.DSSSeed, 0xFFFFFFFF, sizeof(DSSSEED));
- }
- }
- else {
- memset(pbX, 0xFFFFFFFF, sizeof(DSSSEED));
- pbX += sizeof(DSSSEED);
- }
- } else {
- if (pKeyInfo->blob.bVersion == 0x3) {
- if (fPrivate) {
- pKeyInfo->dss_priv_v3.DSSSeed.counter = dssKey->m_counter;
- memcpy(pKeyInfo->dss_priv_v3.DSSSeed.seed, dssKey->m_seed->GetDirectPointerToNonObjectElements(), 20);
- CryptoHelper::memrev(pKeyInfo->dss_priv_v3.DSSSeed.seed, 20);
- } else {
- pKeyInfo->dss_pub_v3.DSSSeed.counter = dssKey->m_counter;
- memcpy(pKeyInfo->dss_pub_v3.DSSSeed.seed, dssKey->m_seed->GetDirectPointerToNonObjectElements(), 20);
- CryptoHelper::memrev(pKeyInfo->dss_pub_v3.DSSSeed.seed, 20);
- }
- } else {
- memcpy(pbX,&dssKey->m_counter, sizeof(DWORD));
- pbX += sizeof(DWORD);
- // now the seed
- memcpy(pbX, dssKey->m_seed->GetDirectPointerToNonObjectElements(), 20);
- CryptoHelper::memrev(pbX, 20);
- pbX += 20;
- }
- }
-
- cbKey = (DWORD)(pbX - pbKey);
- break;
- }
-
- case CALG_RSA_SIGN:
- case CALG_RSA_KEYX: {
- RSA_CSPREF rsaKey;
-
- VALIDATEOBJECTREF(gc.refKey);
- rsaKey = (RSA_CSPREF) gc.refKey;
-
- // Validate the RSA structure first
- if (rsaKey->m_Modulus == NULL)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- // The exponent is a DWORD, so the byte array must not be longer than 4 bytes
- if (rsaKey->m_Exponent == NULL || rsaKey->m_Exponent->GetNumComponents() > 4)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
-
- DWORD cb = rsaKey->m_Modulus->GetNumComponents();
- DWORD cbHalfModulus = (cb + 1)/2;
- // We assume that if P != null, then so are Q, DP, DQ, InverseQ and D
- if (rsaKey->m_P != NULL) {
- if (rsaKey->m_P->GetNumComponents() != cbHalfModulus)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- if (rsaKey->m_Q == NULL || rsaKey->m_Q->GetNumComponents() != cbHalfModulus)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- if (rsaKey->m_dp == NULL || rsaKey->m_dp->GetNumComponents() != cbHalfModulus)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- if (rsaKey->m_dq == NULL || rsaKey->m_dq->GetNumComponents() != cbHalfModulus)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- if (rsaKey->m_InverseQ == NULL || rsaKey->m_InverseQ->GetNumComponents() != cbHalfModulus)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- if (rsaKey->m_d == NULL || rsaKey->m_d->GetNumComponents() != cb)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_DATA);
- }
-
- // Compute the size of the data to include
- pbKey = new BYTE[2*cb + 5*cbHalfModulus + sizeof(KEY_HEADER)];
-
- // Public or private import?
-
- pKeyInfo = (KEY_HEADER *) pbKey.GetValue();
- pKeyInfo->blob.bType = PUBLICKEYBLOB; // will change to PRIVATEKEYBLOB if necessary
- pKeyInfo->blob.bVersion = CUR_BLOB_VERSION;
- pKeyInfo->blob.reserved = 0;
- pKeyInfo->blob.aiKeyAlg = dwCalg;
-
- pKeyInfo->rsa.magic = RSA_PUB_MAGIC; // will change to RSA_PRIV_MAGIC below if necesary
- pKeyInfo->rsa.bitlen = cb*8;
- pKeyInfo->rsa.pubexp = ConvertByteArrayToDWORD(rsaKey->m_Exponent->GetDirectPointerToNonObjectElements(), rsaKey->m_Exponent->GetNumComponents());
- pbX = pbKey + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY);
-
- // Copy over the modulus -- put in for both public & private
-
- memcpy(pbX, rsaKey->m_Modulus->GetDirectPointerToNonObjectElements(), cb);
- CryptoHelper::memrev(pbX, cb);
- pbX += cb;
-
- //
- // See if we are doing private keys.
- //
-
- if ((rsaKey->m_P != 0) && (rsaKey->m_P->GetNumComponents() != 0)) {
- pKeyInfo->blob.bType = PRIVATEKEYBLOB;
- pKeyInfo->rsa.magic = RSA_PRIV_MAGIC;
- fPrivate = TRUE;
-
- // Copy over P
- memcpy(pbX, rsaKey->m_P->GetDirectPointerToNonObjectElements(), cbHalfModulus);
- CryptoHelper::memrev(pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // Copy over Q
- memcpy(pbX, rsaKey->m_Q->GetDirectPointerToNonObjectElements(), cbHalfModulus);
- CryptoHelper::memrev(pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // Copy over dp
- memcpy(pbX, rsaKey->m_dp->GetDirectPointerToNonObjectElements(), cbHalfModulus);
- CryptoHelper::memrev(pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // Copy over dq
- memcpy(pbX, rsaKey->m_dq->GetDirectPointerToNonObjectElements(), cbHalfModulus);
- CryptoHelper::memrev(pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // Copy over InvQ
- memcpy(pbX, rsaKey->m_InverseQ->GetDirectPointerToNonObjectElements(), cbHalfModulus);
- CryptoHelper::memrev(pbX, cbHalfModulus);
- pbX += cbHalfModulus;
-
- // Copy over d
- memcpy(pbX, rsaKey->m_d->GetDirectPointerToNonObjectElements(), cb);
- CryptoHelper::memrev(pbX, cb);
- pbX += cb;
- }
- cbKey = (DWORD)(pbX - pbKey);
- break;
- }
-
- default:
- COMPlusThrow(kCryptographicException, IDS_EE_CRYPTO_UNKNOWN_OPERATION);
- }
-
- DWORD dwCapiFlags = MapCspKeyFlags(dwFlags);
- if (!fPrivate)
- dwCapiFlags &= ~CRYPT_EXPORTABLE;
-
- CRYPT_PROV_CTX * pProvCtx = NULL;
- HRESULT hr = S_OK;
-
- {
- SafeHandleHolder shh(&gc.hProvSAFE);
- pProvCtx = CryptoHelper::DereferenceSafeHandle<CRYPT_PROV_CTX>(gc.hProvSAFE);
- {
- GCX_PREEMP();
- if (!CryptImportKey(pProvCtx->m_hProv, pbKey, cbKey, NULL, dwCapiFlags, &hKey))
- hr = HRESULT_FROM_GetLastError();
- }
- }
-
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: COMCryptography::_ImportKey failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
-
- CRYPT_KEY_CTX * pKeyCtx = new CRYPT_KEY_CTX(pProvCtx, hKey);
- pKeyCtx->m_dwKeySpec = (dwCalg == CALG_RSA_KEYX ? AT_KEYEXCHANGE : AT_SIGNATURE);
- pKeyCtx->m_fPublicOnly = (pKeyInfo->blob.bType == PUBLICKEYBLOB ? TRUE : FALSE);
- gc.hKeySAFE->SetHandle((void*) pKeyCtx);
- hKey.SuppressRelease();
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
-//---------------------------------------------------------------------------------------
-//
-// Check to see if we should default to calculating HMAC values correctly or in Whidbey
-// compatibility mode.
-//
-// Return Value:
-// Default compatibiltiy mode for HMACSHA384 and HMACSHA512. TRUE indicates that we
-// should match Whidbey, false to use the correct calculation.
-//
-
-FCIMPL0(FC_BOOL_RET, COMCryptography::_ProduceLegacyHMACValues)
-{
- FCALL_CONTRACT;
-
- FC_RETURN_BOOL(g_pConfig->LegacyHMACMode());
-}
-FCIMPLEND
-
-//
-// SetKeyParamDw
-//
-// Sets the value of a key parameter
-//
-
-void QCALLTYPE COMCryptography::SetKeyParamDw(CRYPT_KEY_CTX * pKeyCtx, DWORD param, DWORD dwValue)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- if (!CryptSetKeyParam(pKeyCtx->m_hKey, param, (LPBYTE) &dwValue, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- END_QCALL;
-}
-
-//
-// SetKeyParamRgb
-//
-
-void QCALLTYPE COMCryptography::SetKeyParamRgb(CRYPT_KEY_CTX * pKeyCtx, DWORD dwParam, LPCBYTE pValue, DWORD cbValue)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- NewArrayHolder<BYTE> buffer = new BYTE[cbValue];
- memcpyNoGCRefs (buffer, pValue, cbValue);
-
- if (!CryptSetKeyParam(pKeyCtx->m_hKey, dwParam, buffer, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- END_QCALL;
-}
-
-//
-// SetKeySetSecurityInfo
-//
-
-DWORD QCALLTYPE COMCryptography::SetKeySetSecurityInfo(CRYPT_PROV_CTX * pProvCtx, DWORD dwSecurityInformation, LPCBYTE pSecurityDescriptor)
-{
- QCALL_CONTRACT;
-
- DWORD dwErrorCode = 0;
-
- BEGIN_QCALL;
-
- if (!CryptSetProvParam(pProvCtx->m_hProv,
- PP_KEYSET_SEC_DESCR,
- pSecurityDescriptor,
- dwSecurityInformation))
- dwErrorCode = GetLastError();
-
- END_QCALL;
-
- return dwErrorCode;
-}
-
-//
-// SetPersistKeyInCsp
-//
-
-void QCALLTYPE COMCryptography::SetPersistKeyInCsp(CRYPT_PROV_CTX * pProvCtx, BOOL fPersistKeyInCsp)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- pProvCtx->m_fPersistKeyInCsp = fPersistKeyInCsp;
-
- END_QCALL;
-}
-
-//
-// SetProviderParameter
-//
-
-void QCALLTYPE COMCryptography::SetProviderParameter(CRYPT_PROV_CTX * pProvCtx, DWORD dwKeySpec, DWORD dwProvParam, INT_PTR pbData)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- switch (dwProvParam) {
- case CLR_PP_CLIENT_HWND:
- if (!CryptSetProvParam(pProvCtx->m_hProv, PP_CLIENT_HWND, (LPBYTE) pbData, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- break;
-
- case CLR_PP_PIN:
- if (!CryptSetProvParam(pProvCtx->m_hProv, (dwKeySpec == AT_SIGNATURE ? PP_SIGNATURE_PIN : PP_KEYEXCHANGE_PIN), (LPBYTE) pbData, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- break;
-
- default:
- _ASSERTE(FALSE);
- }
-
- END_QCALL;
-}
-
-//
-// SignValue
-//
-
-void QCALLTYPE COMCryptography::SignValue(CRYPT_KEY_CTX * pKeyCtx, DWORD dwKeySpec, DWORD dwCalgKey, DWORD dwCalgHash,
- LPCBYTE pbHash, DWORD cbHash, QCall::ObjectHandleOnStack retSignature)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- HandleHashHolder hHash = NULL;
-
- // Make sure it's either RSA or DSA key
- _ASSERTE(dwCalgKey == CALG_DSS_SIGN || dwCalgKey == CALG_RSA_SIGN);
-
- NewArrayHolder<BYTE> buffer = new BYTE[cbHash];
- memcpyNoGCRefs (buffer, pbHash, cbHash);
-
- _ASSERTE(pKeyCtx->m_pProvCtx);
- CRYPT_PROV_CTX * pProvCtx = pKeyCtx->m_pProvCtx;
-
- // Take the hash value and create a hash object in the correct CSP.
- if (!CryptCreateHash(pProvCtx->m_hProv, dwCalgHash, NULL, 0, &hHash))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- DWORD dwHashSize = 0;
- DWORD cbHashSize = sizeof(dwHashSize);
- if (!CryptGetHashParam(hHash, HP_HASHSIZE, reinterpret_cast<BYTE *>(&dwHashSize), &cbHashSize, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- if (dwHashSize != cbHash)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_HASH);
-
- if (!CryptSetHashParam(hHash, HP_HASHVAL, buffer, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // Find out how long the signature is going to be
- DWORD cbSignature = 0;
- if (!WszCryptSignHash(hHash, dwKeySpec, NULL, 0, NULL, &cbSignature))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // Allocate the buffer to hold the signature
- NewArrayHolder<BYTE> buffer2 = new BYTE[cbSignature];
-
- // Now do the actual signature into the return buffer
- if (!WszCryptSignHash(hHash, dwKeySpec, NULL, 0, buffer2, &cbSignature))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- switch(dwCalgKey) {
- case CALG_RSA_SIGN:
- // the RSA signature needs to be reversed
- CryptoHelper::memrev(buffer2, cbSignature);
- break;
- case CALG_DSS_SIGN:
- // A DSA signature consists of two 20-byte components, each of which
- // must be reversed in place
- if (cbSignature != 40)
- COMPlusThrow(kCryptographicException, W("Cryptography_InvalidDSASignatureSize"));
- CryptoHelper::memrev(buffer2, 20);
- CryptoHelper::memrev(buffer2 + 20, 20);
- break;
- }
-
- retSignature.SetByteArray(buffer2, cbSignature);
-
- END_QCALL;
-}
-
-//
-// VerifySign
-//
-
-BOOL QCALLTYPE COMCryptography::VerifySign(CRYPT_KEY_CTX * pKeyCtx, DWORD dwCalgKey, DWORD dwCalgHash,
- LPCBYTE pbHash, DWORD cbHash, LPCBYTE pbSignature, DWORD cbSignature)
-{
- QCALL_CONTRACT;
-
- BOOL result = FALSE;
-
- BEGIN_QCALL;
-
- // Make sure it's either RSA or DSA key
- _ASSERTE(dwCalgKey == CALG_DSS_SIGN || dwCalgKey == CALG_RSA_SIGN);
-
- HandleHashHolder hHash = NULL;
-
- //
- // Take the hash value and create a hash object in the correct CSP.
- //
-
- NewArrayHolder<BYTE> bufferHash(new BYTE[cbHash]);
- memcpyNoGCRefs (bufferHash, pbHash, cbHash * sizeof(BYTE));
- NewArrayHolder<BYTE> bufferSignature(new BYTE[cbSignature]);
- memcpyNoGCRefs (bufferSignature, pbSignature, cbSignature * sizeof(BYTE));
-
- switch(dwCalgKey) {
- case CALG_RSA_SIGN:
- // the RSA signature needs to be reversed
- CryptoHelper::memrev(bufferSignature, cbSignature);
- break;
- case CALG_DSS_SIGN:
- // A DSA signature consists of two 20-byte components, each of which
- // must be reversed in place
- if (cbSignature != 40)
- COMPlusThrow(kCryptographicException, W("Cryptography_InvalidDSASignatureSize"));
- CryptoHelper::memrev(bufferSignature, 20);
- CryptoHelper::memrev(bufferSignature + 20, 20);
- break;
- }
-
- CRYPT_PROV_CTX * pProvCtx = pKeyCtx->m_pProvCtx;
-
- if (!CryptCreateHash(pProvCtx->m_hProv, dwCalgHash, NULL, 0, &hHash))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- DWORD dwHashSize = 0;
- DWORD cbHashSize = sizeof(dwHashSize);
- if (!CryptGetHashParam(hHash, HP_HASHSIZE, reinterpret_cast<BYTE *>(&dwHashSize), &cbHashSize, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- if (dwHashSize != cbHash)
- CryptoHelper::COMPlusThrowCrypto(NTE_BAD_HASH);
-
- if (!CryptSetHashParam(hHash, HP_HASHVAL, bufferHash, 0))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // Now see if the signature verifies.
- result = WszCryptVerifySignature(hHash, bufferSignature, cbSignature, pKeyCtx->m_hKey, NULL, 0);
-
- END_QCALL;
-
- return result;
-}
-#endif // FEATURE_CRYPTO
-
diff --git a/src/classlibnative/cryptography/cryptography.h b/src/classlibnative/cryptography/cryptography.h
deleted file mode 100644
index 70171c7130..0000000000
--- a/src/classlibnative/cryptography/cryptography.h
+++ /dev/null
@@ -1,521 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-//
-
-//
-
-
-#ifndef _CRYPTOGRAPHY_H_
-#define _CRYPTOGRAPHY_H_
-
-#include <wincrypt.h>
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-#include "fcall.h"
-
-class DSA_CSP_Object : public Object {
-public:
- U1ARRAYREF m_P; // ubyte[]
- U1ARRAYREF m_Q; // ubyte[]
- U1ARRAYREF m_G; // ubyte[]
- U1ARRAYREF m_Y; // ubyte[] - optional
- U1ARRAYREF m_J; // ubyte[] - optional
- U1ARRAYREF m_X; // ubyte[] - optional - private key
- U1ARRAYREF m_seed; // ubyte[] - optional - paired with counter
- DWORD m_counter; // DWORD - optional
-};
-
-class RSA_CSP_Object : public Object {
-public:
- U1ARRAYREF m_Exponent; // ubyte[]
- U1ARRAYREF m_Modulus; // ubyte[]
- U1ARRAYREF m_P; // ubyte[] - optional
- U1ARRAYREF m_Q; // ubyte[] - optional
- U1ARRAYREF m_dp; // ubyte[] - optional
- U1ARRAYREF m_dq; // ubyte[] - optional
- U1ARRAYREF m_InverseQ; // ubyte[] - optional
- U1ARRAYREF m_d; // ubyte[] - optional
-};
-
-#ifdef USE_CHECKED_OBJECTREFS
-typedef REF<DSA_CSP_Object> DSA_CSPREF;
-typedef REF<RSA_CSP_Object> RSA_CSPREF;
-#else // !_DEBUG
-typedef DSA_CSP_Object * DSA_CSPREF;
-typedef RSA_CSP_Object * RSA_CSPREF;
-#endif // _DEBUG
-
-#endif // #if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-
-#define DSS_MAGIC 0x31535344
-#define DSS_PRIVATE_MAGIC 0x32535344
-#define DSS_PUB_MAGIC_VER3 0x33535344
-#define DSS_PRIV_MAGIC_VER3 0x34535344
-#define RSA_PUB_MAGIC 0x31415352
-#define RSA_PRIV_MAGIC 0x32415352
-
-#define DSS_Q_LEN 20
-
-// Keep in sync with managed definition in System.Security.Cryptography.Utils
-#define CLR_KEYLEN 1
-#define CLR_PUBLICKEYONLY 2
-#define CLR_EXPORTABLE 3
-#define CLR_REMOVABLE 4
-#define CLR_HARDWARE 5
-#define CLR_ACCESSIBLE 6
-#define CLR_PROTECTED 7
-#define CLR_UNIQUE_CONTAINER 8
-#define CLR_ALGID 9
-#define CLR_PP_CLIENT_HWND 10
-#define CLR_PP_PIN 11
-
-#define MAX_CACHE_DEFAULT_PROVIDERS 20
-// size of a symmetric key block size. 8 is the only supported for now
-#define BLOCK_LEN 8
-
-// Dependency in managed : System/Security/Cryptography/Crypto.cs
-#define CRYPTO_PADDING_NONE 1
-#define CRYPTO_PADDING_PKCS5 2
-#define CRYPTO_PADDING_Zeros 3
-#define CRYPTO_PADDING_ANSI_X_923 4
-#define CRYPTO_PADDING_ISO_10126 5
-
-// These flags match those defined for the CspProviderFlags enum in
-// src/bcl/system/security/cryptography/CryptoAPITransform.cs
-
-#define CSP_PROVIDER_FLAGS_USE_MACHINE_KEYSTORE 0x0001
-#define CSP_PROVIDER_FLAGS_USE_DEFAULT_KEY_CONTAINER 0x0002
-#define CSP_PROVIDER_FLAGS_USE_NON_EXPORTABLE_KEY 0x0004
-#define CSP_PROVIDER_FLAGS_USE_EXISTING_KEY 0x0008
-#define CSP_PROVIDER_FLAGS_USE_ARCHIVABLE_KEY 0x0010
-#define CSP_PROVIDER_FLAGS_USE_USER_PROTECTED_KEY 0x0020
-#define CSP_PROVIDER_FLAGS_USE_CRYPT_SILENT 0x0040
-#define CSP_PROVIDER_FLAGS_CREATE_EPHEMERAL_KEY 0x0080
-
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO) || defined(FEATURE_X509)
-class CryptoHelper {
-public:
- static void COMPlusThrowCrypto (HRESULT hr);
- static BOOL WszCryptAcquireContext_SO_TOLERANT (HCRYPTPROV *phProv, LPCWSTR pwszContainer, LPCWSTR pwszProvider, DWORD dwProvType, DWORD dwFlags);
- static WCHAR* STRINGREFToUnicode (STRINGREF s);
- static WCHAR* AnsiToUnicode (__in_z char* pszAnsi);
- static void ByteArrayToU1ARRAYREF (LPBYTE pb, DWORD cb, U1ARRAYREF* u1);
- static BYTE* U1ARRAYREFToByteArray (U1ARRAYREF u1);
- static char* UnicodeToAnsi (__in_z WCHAR* pwszUnicode);
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
- static WCHAR* GetRandomKeyContainer ();
- static inline void memrev (LPBYTE pb, DWORD cb);
- static BOOL CryptGenKey_SO_TOLERANT (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY* phKey);
-#endif // FEATURE_CRYPTO
-
- static LPCWSTR UpgradeDSS(DWORD dwProvType, __in_z LPCWSTR wszProvider);
- static LPCWSTR UpgradeRSA(DWORD dwProvType, __in_z LPCWSTR wszProvider);
-
- // Since crytpo classes use safe handles where the handles are really pointers to structures, we
- // need to ensure that they weren't freed and set to NULL if the handle was used in an unsafe
- // multithreaded way. This method unpacks the handle, ensuring it doesn't contain a NULL pointer.
- template<class T>
- static T * DereferenceSafeHandle(const SAFEHANDLE &handle)
- {
- CONTRACT(T *)
- {
- POSTCONDITION(RETVAL != NULL);
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACT_END;
-
- T * pValue = static_cast<T *>(handle->GetHandle());
- if (!pValue)
- {
- LOG((LF_SECURITY, LL_INFO10000, "Attempt to access a NULL crypto handle, possible unsafe use of a crypto function from multiple threads"));
- COMPlusThrowCrypto(E_POINTER);
- }
-
- RETURN(pValue);
- }
-};
-#endif // FEATURE_CRYPTO || FEATURE_X509
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-typedef struct {
- BLOBHEADER blob;
- union {
- DSSPRIVKEY_VER3 dss_priv_v3;
- DSSPUBKEY_VER3 dss_pub_v3;
- DSSPUBKEY dss_v2;
- RSAPUBKEY rsa;
- };
-} KEY_HEADER;
-
-// We need to define this unmanaged memory structure to hold
-// all the information relevant to the CSP in order to guarantee
-// critical finalization of the resources
-typedef struct CRYPT_PROV_CTX {
-private:
- // We implicitely assume this method is not going to do a LoadLibrary
- HRESULT DeleteKeyContainer() {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GCX_PREEMP();
-
- HCRYPTPROV hProv = NULL;
- if (!CryptoHelper::WszCryptAcquireContext_SO_TOLERANT(&hProv, m_pwszContainer, m_pwszProvider,
- m_dwType, (m_dwFlags & CRYPT_MACHINE_KEYSET) | CRYPT_DELETEKEYSET))
- return HRESULT_FROM_GetLastError();
- return S_OK;
- }
-
-public:
- HCRYPTPROV m_hProv;
- LPCWSTR m_pwszContainer;
- LPCWSTR m_pwszProvider;
- DWORD m_dwType;
- DWORD m_dwFlags;
- BOOL m_fPersistKeyInCsp;
- BOOL m_fReleaseProvider;
- Volatile<ULONG> m_refCount;
-
- CRYPT_PROV_CTX() :
- m_hProv(0),
- m_pwszContainer(NULL),
- m_pwszProvider(NULL),
- m_fReleaseProvider(TRUE),
- m_dwType(0),
- m_dwFlags(0),
- m_fPersistKeyInCsp(TRUE),
- m_refCount(1) {
- LIMITED_METHOD_CONTRACT;
- }
-
- // This can be called twice. Also it can be called by multiple threads. The only
- // invariant that needs to be enforced is that when the refCount reaches 0, the
- // object is not going to be referenced anymore by a CRYPT_KEY_CTX or a CRYPT_HASH_CTX.
- // But this is true in the way we use this in the managed side.
- void Release () {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- ULONG cbRef = InterlockedDecrement((LONG*)&m_refCount);
- if (cbRef == 0) {
- // Make sure not to delete a key that we want to keep in the key container or an ephemeral key
- if (m_fPersistKeyInCsp == FALSE && !(m_dwFlags & CRYPT_VERIFYCONTEXT)) {
- // We cannot throw if we fail to delete the key container, since this code runs on the
- // finalizer thread and any exception will tear the process
- DeleteKeyContainer();
- }
-
- if (m_pwszContainer) {
- delete[] m_pwszContainer;
- m_pwszContainer = NULL;
- }
-
- // The provider strings are allocated per process, so
- // we should not free m_pwszProvider unless specified otherwise
- if (m_fReleaseProvider) {
- if (m_pwszProvider) {
- delete[] m_pwszProvider;
- m_pwszProvider = NULL;
- }
- }
-
- // We need to free the CSP handle -- make sure not to throw since this code could be on the
- // finalizer thread.
- if (m_hProv != 0)
- {
- CryptReleaseContext(m_hProv, 0);
- m_hProv = 0;
- }
-
- delete this;
- }
- }
-
-} CRYPT_PROV_CTX;
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
-// A key handle needs to be freed before the provider handle
-// it was loaded into is freed; so we need to keep a pointer to
-// the CRYPT_PROV_CTX and make the managed SafeKeyHandle contain
-// a pointer to the CRYPT_KEY_CTX pointer
-typedef struct CRYPT_KEY_CTX {
-public:
- CRYPT_PROV_CTX *m_pProvCtx;
- HCRYPTKEY m_hKey;
- DWORD m_dwKeySpec;
- BOOL m_fPublicOnly;
-
- CRYPT_KEY_CTX(CRYPT_PROV_CTX * pProvCtx, HCRYPTKEY hKey) :
- m_pProvCtx(pProvCtx),
- m_hKey(hKey),
- m_dwKeySpec(0),
- m_fPublicOnly(FALSE) {
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(hKey != NULL);
- PRECONDITION(CheckPointer(m_pProvCtx));
- PRECONDITION((m_pProvCtx->m_refCount >= 1)); // We can't acquire a dead CRYPT_PROV_CTX
- } CONTRACTL_END;
-
- InterlockedIncrement((LONG*)&m_pProvCtx->m_refCount);
- }
-
- void Release () {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- // We cannot throw if CryptDestroyKey fails, since this can be executed on the finalizer thread
- if (m_hKey)
- CryptDestroyKey(m_hKey);
-
- // We need to release the reference to the CSP handle
- if (m_pProvCtx)
- m_pProvCtx->Release();
-
- delete this;
- }
-
-} CRYPT_KEY_CTX;
-
-// A hash handle needs to be freed before the provider handle
-// it was loaded into is freed; so we need to keep a pointer to
-// the CRYPT_PROV_CTX and make the managed SafeHashHandle contain
-// a pointer to the CRYPT_HASH_CTX pointer
-typedef struct CRYPT_HASH_CTX {
-public:
- CRYPT_PROV_CTX *m_pProvCtx;
- HCRYPTHASH m_hHash;
-
- CRYPT_HASH_CTX(CRYPT_PROV_CTX * pProvCtx, HCRYPTHASH hHash) :
- m_pProvCtx(pProvCtx),
- m_hHash(hHash) {
- CONTRACTL {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(hHash != NULL);
- PRECONDITION(CheckPointer(m_pProvCtx));
- PRECONDITION((m_pProvCtx->m_refCount >= 1)); // We can't acquire a dead CRYPT_PROV_CTX
- } CONTRACTL_END;
-
- InterlockedIncrement((LONG*)&m_pProvCtx->m_refCount);
- }
-
- void Release () {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- // We cannot throw if CryptDestroyHash fails since this code could run on the finalizer thread
- if (m_hHash)
- CryptDestroyHash(m_hHash);
-
- // We need to release the reference to the CSP handle
- if (m_pProvCtx)
- m_pProvCtx->Release();
-
- delete this;
- }
-
-} CRYPT_HASH_CTX;
-#endif // FEATURE_CRYPTO
-
-class COMCryptography
-{
-public:
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
- //
- // QCalls from RSACryptoServiceProvider
- //
-
- // Decrypt a symmetric key using the private key in pKeyContext
- static
- void QCALLTYPE DecryptKey(__in CRYPT_KEY_CTX *pKeyContext,
- __in_bcount(cbEncryptedKey) BYTE *pbEncryptedKey,
- DWORD cbEncryptedKey,
- BOOL fOAEP,
- QCall::ObjectHandleOnStack ohRetDecryptedKey);
-
- // Encrypt a symmetric key using the public key in pKeyContext
- static
- void QCALLTYPE EncryptKey(__in CRYPT_KEY_CTX *pKeyContext,
- __in_bcount(cbKey) BYTE *pbKey,
- DWORD cbKey,
- BOOL fOAEP,
- QCall::ObjectHandleOnStack ohRetEncryptedKey);
-
- //
- // SafeHandle release QCALLS
- //
-#endif // FEATURE_CRYPTO
- // Release our handle to a CSP, potentially deleting the referenced key.
- static
- void QCALLTYPE FreeCsp(__in_opt CRYPT_PROV_CTX *pProviderContext);
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
- // Release our handle to a hash, potentially also releasing the provider
- static
- void QCALLTYPE FreeHash(__in_opt CRYPT_HASH_CTX *pHashContext);
-
- // Release our handle to a key, potentially also releasing the provider
- static
- void QCALLTYPE FreeKey(__in_opt CRYPT_KEY_CTX *pKeyContext);
-
- //
- // Util QCALLS
- //
-
- static
- CRYPT_HASH_CTX * CreateHash(CRYPT_PROV_CTX * pProvCtx, DWORD dwHashType);
-
- static
- void QCALLTYPE DeriveKey(CRYPT_PROV_CTX * pProvCtx, DWORD dwCalgKey, DWORD dwCalgHash,
- LPCBYTE pbPwd, DWORD cbPwd, DWORD dwFlags, LPBYTE pbIVIn, DWORD cbIVIn,
- QCall::ObjectHandleOnStack retKey);
-
- static
- void QCALLTYPE EndHash(CRYPT_HASH_CTX * pHashCtx, QCall::ObjectHandleOnStack retHash);
-
- static
- void QCALLTYPE ExportCspBlob(CRYPT_KEY_CTX * pKeyCtx, DWORD dwBlobType, QCall::ObjectHandleOnStack retBlob);
-#endif // FEATURE_CRYPTO
-
- static
- void QCALLTYPE GetBytes(CRYPT_PROV_CTX * pProvCtx, BYTE * pbOut, INT32 cb);
-
- static
- void QCALLTYPE GetNonZeroBytes(CRYPT_PROV_CTX * pProvCtx, BYTE * pbOut, INT32 cb);
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
- static
- BOOL QCALLTYPE GetPersistKeyInCsp(CRYPT_PROV_CTX * pProvCtx);
-
- static
- void QCALLTYPE HashData(CRYPT_HASH_CTX * pHashCtx, LPCBYTE pData, DWORD cbData, DWORD dwStart, DWORD dwSize);
-
- static
- BOOL QCALLTYPE SearchForAlgorithm(CRYPT_PROV_CTX * pProvCtx, DWORD dwAlgID, DWORD dwKeyLength);
-
- static
- void QCALLTYPE SetKeyParamDw(CRYPT_KEY_CTX * pKeyCtx, DWORD dwParam, DWORD dwValue);
-
- static
- void QCALLTYPE SetKeyParamRgb(CRYPT_KEY_CTX * pKeyCtx, DWORD dwParam, LPCBYTE pValue, DWORD cbValue);
-
- static
- DWORD QCALLTYPE SetKeySetSecurityInfo(CRYPT_PROV_CTX * pProvCtx, DWORD dwSecurityInformation, LPCBYTE pSecurityDescriptor);
-
- static
- void QCALLTYPE SetPersistKeyInCsp(CRYPT_PROV_CTX * pProvCtx, BOOL fPersistKeyInCsp);
-
- static
- void QCALLTYPE SetProviderParameter(CRYPT_PROV_CTX * pProvCtx, DWORD dwKeySpec, DWORD dwProvParam, INT_PTR pbData);
-
- static
- void QCALLTYPE SignValue(CRYPT_KEY_CTX * pKeyCtx, DWORD dwKeySpec, DWORD dwCalgKey, DWORD dwCalgHash,
- LPCBYTE pbHash, DWORD cbHash, QCall::ObjectHandleOnStack retSignature);
-
- static
- BOOL QCALLTYPE VerifySign(CRYPT_KEY_CTX * pKeyCtx, DWORD dwCalgKey, DWORD dwCalgHash,
- LPCBYTE pbHash, DWORD cbHash, LPCBYTE pbSignature, DWORD cbSignature);
-
-#endif // FEATURE_CRYPTO
-
-public:
- //
- // FCalls from System.Security.Cryptography.Utils
- //
-
- static FCDECL2(void, _AcquireCSP, Object* cspParametersUNSAFE, SafeHandle** hProvUNSAFE);
- static FCDECL3(HRESULT, _OpenCSP, Object* cspParametersUNSAFE, DWORD dwFlags, SafeHandle** hProvUNSAFE);
- static FCDECL0(StringObject*, _GetRandomKeyContainer);
- static LPCWSTR GetDefaultProvider(DWORD dwType);
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
- static FCDECL3(void, _CreateCSP, Object* cspParametersUNSAFE, CLR_BOOL randomKeyContainer, SafeHandle** hProvUNSAFE);
- static FCDECL8(DWORD, _DecryptData, SafeHandle* hKeyUNSAFE, U1Array* dataUNSAFE, INT32 dwOffset, INT32 dwCount, U1Array** outputUNSAFE, INT32 dwOutputOffset, DWORD dwPaddingMode, CLR_BOOL fLast);
- static FCDECL8(DWORD, _EncryptData, SafeHandle* hKeyUNSAFE, U1Array* dataUNSAFE, INT32 dwOffset, INT32 dwCount, U1Array** outputUNSAFE, INT32 dwOutputOffset, DWORD dwPaddingMode, CLR_BOOL fLast);
- static FCDECL3(void, _ExportKey, SafeHandle* hKeyUNSAFE, DWORD dwBlobType, Object* theKeyUNSAFE);
- static FCDECL5(void, _GenerateKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, DWORD dwFlags, DWORD dwKeySize, SafeHandle** hKeyUNSAFE);
- static FCDECL0(FC_BOOL_RET, _GetEnforceFipsPolicySetting);
- static FCDECL2(U1Array*, _GetKeyParameter, SafeHandle* hKeyUNSAFE, DWORD dwKeyParam);
- static FCDECL3(U1Array*, _GetKeySetSecurityInfo, SafeHandle* hProvUNSAFE, DWORD dwSecurityInformation, DWORD* pdwErrorCode);
- static FCDECL3(Object*, _GetProviderParameter, SafeHandle* hKeyUNSAFE, DWORD dwKeySpec, DWORD dwKeyParam);
- static FCDECL3(HRESULT, _GetUserKey, SafeHandle* hProvUNSAFE, DWORD dwKeySpec, SafeHandle** hKeyUNSAFE);
- static FCDECL5(void, _ImportBulkKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, CLR_BOOL useSalt, U1Array* rgbKeyUNSAFE, SafeHandle** hKeyUNSAFE);
- static FCDECL4(DWORD, _ImportCspBlob, U1Array* rawDataUNSAFE, SafeHandle* hProvUNSAFE, DWORD dwFlags, SafeHandle** hKeyUNSAFE);
- static FCDECL5(void, _ImportKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, DWORD dwFlags, Object* refKeyUNSAFE, SafeHandle** hKeyUNSAFE);
- static FCDECL0(FC_BOOL_RET, _ProduceLegacyHMACValues);
-#endif // FEATURE_CRYPTO
-
-private:
- static HRESULT OpenCSP(OBJECTREF * pSafeThis, DWORD dwFlags, CRYPT_PROV_CTX * pProvCtxStruct);
- static DWORD MapCspProviderFlags (DWORD dwFlags);
-
-#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
- static HRESULT MSProviderCryptImportKey(HCRYPTPROV hProv, LPBYTE rgbSymKey, DWORD cbSymKey, DWORD dwFlags, HCRYPTKEY * phkey);
- static HRESULT ExponentOfOneImport(HCRYPTPROV hProv, LPBYTE rgbKeyMaterial, DWORD cbKeyMaterial, DWORD dwKeyAlg, DWORD dwFlags, HCRYPTKEY * phkey);
- static HRESULT PlainTextKeyBlobImport(HCRYPTPROV hProv, LPBYTE rgbKeyMaterial, DWORD cbKeyMaterial, DWORD dwKeyAlg, DWORD dwFlags, HCRYPTKEY * phkey);
- static HRESULT LoadKey(LPBYTE rgbKeyMaterial, DWORD cbKeyMaterial, HCRYPTPROV hprov, DWORD dwCalg, DWORD dwFlags, HCRYPTKEY * phkey);
- static HRESULT UnloadKey(HCRYPTPROV hprov, HCRYPTKEY hkey, LPBYTE * ppb, DWORD * pcb);
- static inline DWORD ConvertByteArrayToDWORD (LPBYTE pb, DWORD cb);
- static inline void ConvertIntToByteArray(DWORD dwInput, LPBYTE * ppb, DWORD * pcb);
- static DWORD MapCspKeyFlags (DWORD dwFlags);
-#endif //FEATURE_CRYPTO
-
-}; // class COMCryptography
-
-// @telesto - with talk of registry access, sounds like this should be #ifdef out from Telesto?
-//---------------------------------------------------------------------------------------
-//
-// Cache of CSP data we've already looked up in the registry
-//
-// Notes:
-// This cache is thread safe. If a CSP is not stored in the cache, it will
-// return NULL rather than throwing. Attempting to store multiple CSPs with
-// the same type will result in only the first CSP being stored.
-//
-
-class ProviderCache
-{
-public:
- // Associate a name with a CSP type
- static void CacheProvider(DWORD dwType, __in_z LPWSTR pwzProvider);
-
- // Get the name that's associated with the given type, NULL if there is no association setup
- static LPCWSTR GetProvider(DWORD dwType);
-
-private:
- // The largest type of CSP that Windows defines. This should be updated as new CSP types are defined
- static const DWORD MaxWindowsProviderType = PROV_RSA_AES;
-
- static ProviderCache *s_pCache; // singleton cache instance
-
- EEIntHashTable m_htCache; // Mapping between cached provider types and CSP names
- Crst m_crstCache; // Lock guarding access to m_htCache
-
- ProviderCache();
-
- void InternalCacheProvider(DWORD dwType, __in_z LPWSTR pwzProvider);
- LPCWSTR InternalGetProvider(DWORD dwType);
-};
-#endif // FEATURE_CRYPTO -- review flags
-
-#endif // !_CRYPTOGRPAPHY_H_
diff --git a/src/classlibnative/cryptography/cryptography.nativeproj b/src/classlibnative/cryptography/cryptography.nativeproj
deleted file mode 100644
index 44b8f93aea..0000000000
--- a/src/classlibnative/cryptography/cryptography.nativeproj
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="dogfood">
- <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" />
- <Import Project="$(ClrBase)\src\debug\SetDebugTargetLocal.props" />
- <PropertyGroup Label="Globals">
- <SccProjectName>SAK</SccProjectName>
- <SccAuxPath>SAK</SccAuxPath>
- <SccLocalPath>SAK</SccLocalPath>
- <SccProvider>SAK</SccProvider>
- </PropertyGroup>
- <PropertyGroup>
- <BuildCoreBinaries>true</BuildCoreBinaries>
- <BuildSysBinaries>true</BuildSysBinaries>
- <NoWarningDotH>true</NoWarningDotH>
- <ClWarningLevel>4</ClWarningLevel>
- <UserIncludes>
- $(UserIncludes);
- .;
- ..\inc;
- $(Clrbase)\src\vm;
- $(Clrbase)\src\vm\$(TargetCpu);
- $(VCToolsIncPath);
- $(Clrbase)\src\strongname\inc;
- ..\bcltype
- </UserIncludes>
- <OutputName>comcrypt_wks</OutputName>
- <OutputPath>$(ClrLibDest)</OutputPath>
- <TargetType>LIBRARY</TargetType>
- <CDefines>$(CDefines);UNICODE;_UNICODE</CDefines>
- </PropertyGroup>
- <ItemGroup>
- <CppCompile Include="Cryptography.cpp" />
- <CppCompile Include="X509Certificate.cpp" />
- </ItemGroup>
- <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.targets" />
-</Project>
diff --git a/src/classlibnative/cryptography/x509certificate.cpp b/src/classlibnative/cryptography/x509certificate.cpp
deleted file mode 100644
index 54a45f020a..0000000000
--- a/src/classlibnative/cryptography/x509certificate.cpp
+++ /dev/null
@@ -1,1340 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-//
-// File: X509Certificate.cpp
-//
-
-//
-// Native method implementations and helper code for supporting CAPI based operations on X509 signatures
-//
-//---------------------------------------------------------------------------
-
-
-#include "common.h"
-
-#ifdef FEATURE_X509
-
-#include "x509certificate.h"
-
-#if !defined(FEATURE_CORECLR)
-//
-// Builds a certificate chain using the specified policy.
-//
-
-HRESULT X509Helper::BuildChain (PCCERT_CONTEXT pCertContext,
- HCERTSTORE hCertStore,
- LPCSTR pszPolicy,
- PCCERT_CHAIN_CONTEXT * ppChainContext)
-{
- CONTRACTL {
- THROWS; // THROWS because the delay-loading of crypt32.dll may fail when we call CertGetCertificateChain()
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GCX_PREEMP();
-
- CERT_CHAIN_PARA ChainPara = {0};
- LPSTR rgpszUsageIdentifier[1] = {NULL};
-
- // Initialize the structure size.
- ChainPara.cbSize = sizeof(ChainPara);
-
- // Check policy.
- if (CERT_CHAIN_POLICY_BASE == pszPolicy) {
- // No EKU for base policy.
- }
- else
- return CERT_E_INVALID_POLICY;
-
- // Build the chain.
- if (!CertGetCertificateChain(NULL,
- pCertContext,
- NULL,
- hCertStore,
- &ChainPara,
- 0,
- NULL,
- ppChainContext)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertGetCertificateChain failed.\n", HRESULT_FROM_GetLastError()));
- return HRESULT_FROM_GetLastError();
- }
-
- return S_OK;
-}
-
-//
-// decodes an ASN encoded data. The caller is responsible for calling delete[] to free the allocated memory.
-//
-
-HRESULT X509Helper::DecodeObject(LPCSTR pszStructType,
- LPBYTE pbEncoded,
- DWORD cbEncoded,
- void** ppvDecoded,
- DWORD* pcbDecoded) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GCX_PREEMP();
-
- DWORD cbDecoded = 0;
- if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- pszStructType,
- pbEncoded,
- cbEncoded,
- 0,
- NULL,
- &cbDecoded)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptDecodeObject failed.\n", HRESULT_FROM_GetLastError()));
- return HRESULT_FROM_GetLastError();
- }
-
- *ppvDecoded = (void*) new BYTE[cbDecoded];
- if (!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- pszStructType,
- pbEncoded,
- cbEncoded,
- 0,
- *ppvDecoded,
- &cbDecoded)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptDecodeObject failed.\n", HRESULT_FROM_GetLastError()));
- return HRESULT_FROM_GetLastError();
- }
-
- if (pcbDecoded)
- *pcbDecoded = cbDecoded;
-
- return S_OK;
-}
-
-//
-// Deletes a key container given a certificate context.
-//
-
-BOOL X509Helper::DeleteKeyContainer (PCCERT_CONTEXT pCertContext) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GCX_PREEMP();
-
- NewHolder<CRYPT_KEY_PROV_INFO> pProvInfo;
- DWORD cbData = 0;
- if (!CertGetCertificateContextProperty(pCertContext,
- CERT_KEY_PROV_INFO_PROP_ID,
- NULL,
- &cbData))
- return TRUE;
-
- pProvInfo = (CRYPT_KEY_PROV_INFO*) new BYTE[cbData];
- if (!CertGetCertificateContextProperty(pCertContext,
- CERT_KEY_PROV_INFO_PROP_ID,
- (void*) pProvInfo.GetValue(),
- &cbData))
- return FALSE;
-
- // First disassociate the key from the cert.
- if (!CertSetCertificateContextProperty(pCertContext,
- CERT_KEY_PROV_INFO_PROP_ID,
- 0,
- NULL))
- return FALSE;
-
- HCRYPTPROV hProv = NULL;
- return CryptoHelper::WszCryptAcquireContext_SO_TOLERANT(&hProv,
- pProvInfo->pwszContainerName,
- pProvInfo->pwszProvName,
- pProvInfo->dwProvType,
- (pProvInfo->dwFlags & CRYPT_MACHINE_KEYSET) | CRYPT_DELETEKEYSET);
-}
-#endif // !FEATURE_CORECLR
-
-//
-// Loads a certificate or store from a blob and returns that content type.
-//
-
-DWORD X509Helper::LoadFromBlob (CERT_BLOB* pCertBlob,
- __in_opt WCHAR* pwszPassword,
- DWORD dwFlags,
- PCCERT_CONTEXT* pCertContext,
- HCERTSTORE* phCertStore,
- HCRYPTMSG* phCryptMsg) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- DWORD dwContentType = 0;
- GCX_PREEMP();
- if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
- pCertBlob,
- dwFlags,
- X509_CERT_FORMAT_FLAGS,
- 0,
- NULL,
- &dwContentType,
- NULL,
- phCertStore,
- phCryptMsg,
- (const void **)pCertContext)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptQueryObject failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- return dwContentType;
-}
-
-//
-// Loads a certificate or store from a file and returns that content type.
-//
-
-DWORD X509Helper::LoadFromFile (__in_z WCHAR* pwszFileName,
- __in_opt WCHAR* pwszPassword,
- DWORD dwFlags,
- PCCERT_CONTEXT* pCertContext,
- HCERTSTORE* phCertStore,
- HCRYPTMSG* phCryptMsg) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- DWORD dwContentType = 0;
- GCX_PREEMP();
- if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
- pwszFileName,
- dwFlags,
- X509_CERT_FORMAT_FLAGS,
- 0,
- NULL,
- &dwContentType,
- NULL,
- phCertStore,
- phCryptMsg,
- (const void **)pCertContext)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptQueryObject failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- return dwContentType;
-}
-
-//
-// Reads a file into memory. The caller is responsible for deleting the allocated memory.
-//
-
-HRESULT X509Helper::ReadFileIntoMemory (LPCWSTR wszFileName,
- LPBYTE* ppbBuffer,
- DWORD* pdwBufLen)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GCX_PREEMP();
-
- HandleHolder hFile(WszCreateFile (wszFileName,
- GENERIC_READ,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
- NULL));
- if (hFile == INVALID_HANDLE_VALUE)
- return HRESULT_FROM_GetLastError();
-
- DWORD dwFileLen = SafeGetFileSize(hFile, 0);
- if (dwFileLen == 0xFFFFFFFF)
- return HRESULT_FROM_GetLastError();
-
- _ASSERTE(ppbBuffer);
- *ppbBuffer = new BYTE[dwFileLen];
-
- if ((SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == 0xFFFFFFFF) ||
- (!ReadFile(hFile, *ppbBuffer, dwFileLen, pdwBufLen, NULL))) {
- delete[] *ppbBuffer;
- *ppbBuffer = 0;
- return HRESULT_FROM_GetLastError();
- }
-
- _ASSERTE(dwFileLen == *pdwBufLen);
- return S_OK;
-}
-
-//
-// Returns the name for the subject or issuer.
-// dwFlags : 0 for subject name or CERT_NAME_ISSUER_FLAG for issuer name.
-// dwDisplayType: display type.
-//
-// It is the caller's responsibility to free the allocated buffer.
-//
-
-WCHAR* COMX509Certificate::GetCertNameInfo(PCCERT_CONTEXT pCertContext, DWORD dwFlags, DWORD dwDisplayType, DWORD dwStrType) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GCX_PREEMP();
-
- DWORD cchCount = 0;
- if ((cchCount = CertGetNameString(pCertContext,
- dwDisplayType,
- dwFlags,
- &dwStrType,
- NULL,
- 0)) == 0) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertGetNameString failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- NewArrayHolder<WCHAR> pwszName(new WCHAR[cchCount]);
- if (!CertGetNameString(pCertContext,
- dwDisplayType,
- dwFlags,
- &dwStrType,
- pwszName,
- cchCount)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertGetNameString failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- pwszName.SuppressRelease();
- return pwszName;
-}
-
-#if !defined(FEATURE_CORECLR)
-//
-// Finds the first certificate with a private key in a PFX store.
-// If none has a private key, we take the first certificatee in the PFX store.
-//
-
-PCCERT_CONTEXT COMX509Certificate::FilterPFXStore (CERT_BLOB* pfxBlob, __in_z WCHAR* pwszPassword, DWORD dwFlags) {
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- } CONTRACTL_END;
-
- GCX_PREEMP();
-
- HandleCertStoreHolder hCertStore = NULL;
- hCertStore = PFXImportCertStore(pfxBlob, pwszPassword, dwFlags);
- if (hCertStore == NULL) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: PFXImportCertStore failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- // now filter the PFX store
- PCCERT_CONTEXT pCertContext = NULL;
- PCCERT_CONTEXT pEnumContext = NULL;
- DWORD cb = 0;
-
- // Find the first cert with private key, if none, then simply take the very first cert.
- while ((pEnumContext = CertEnumCertificatesInStore(hCertStore, pEnumContext)) != NULL) {
- if (CertGetCertificateContextProperty(pEnumContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cb)) {
- if (pCertContext != NULL) {
- if (CertGetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cb)) {
- X509Helper::DeleteKeyContainer(pEnumContext);
- } else {
- CertFreeCertificateContext(pCertContext);
- pCertContext = CertDuplicateCertificateContext(pEnumContext);
- }
- } else {
- pCertContext = CertDuplicateCertificateContext(pEnumContext);
- }
- } else {
- // Keep the first one.
- if (pCertContext == NULL)
- pCertContext = CertDuplicateCertificateContext(pEnumContext);
- }
- // Don't free pEnumContext here, as CertEnumCertificatesInStore will do it for us
- }
-
- if (pCertContext == NULL)
- CryptoHelper::COMPlusThrowCrypto(ERROR_INVALID_PARAMETER);
-
- return pCertContext;
-}
-
-//
-// Finds the signer certificate in a PKCS7 signed store.
-//
-
-PCCERT_CONTEXT COMX509Certificate::GetSignerInPKCS7Store (HCERTSTORE hCertStore, HCRYPTMSG hCryptMsg)
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- GCX_PREEMP();
-
- // make sure that there is at least one signer of the certificate store
- DWORD dwSigners;
- DWORD cbSigners = sizeof(dwSigners);
- if (!CryptMsgGetParam(hCryptMsg,
- CMSG_SIGNER_COUNT_PARAM,
- 0,
- &dwSigners,
- &cbSigners))
- {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptMsgGetParam(CMSG_SIGNER_COUNT_PARAM) failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- if (dwSigners == 0)
- CryptoHelper::COMPlusThrowCrypto(CRYPT_E_SIGNER_NOT_FOUND);
-
- // get the first signer from the store, and use that as the loaded certificate
- DWORD cbData = 0;
- if (!CryptMsgGetParam(hCryptMsg,
- CMSG_SIGNER_INFO_PARAM,
- 0,
- NULL,
- &cbData))
- {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptMsgGetParam(CMS_SIGNER_INFO_PARAM) failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- NewArrayHolder<CMSG_SIGNER_INFO> pCmsgSigner = (CMSG_SIGNER_INFO*) new BYTE[cbData];
- if (!CryptMsgGetParam(hCryptMsg,
- CMSG_SIGNER_INFO_PARAM,
- 0,
- pCmsgSigner,
- &cbData))
- {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptMsgGetParam failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- CERT_INFO CertInfo;
- CertInfo.Issuer = pCmsgSigner->Issuer;
- CertInfo.SerialNumber = pCmsgSigner->SerialNumber;
- PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hCertStore,
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- 0,
- CERT_FIND_SUBJECT_CERT,
- (LPVOID) &CertInfo,
- NULL);
-
- if (pCertContext == NULL)
- {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertFindCertificateInStore failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- return pCertContext;
-}
-#endif // !FEATURE_CORECLR
-
-//
-// FCALL methods
-//
-
-//
-// The certificate context ref count is incremented by CertDuplicateCertificateContext,
-// so it is the caller's responsibility to free the context.
-//
-
-FCIMPL2(void, COMX509Certificate::DuplicateCertContext, INT_PTR handle, SafeHandle** ppCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) *ppCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_1(pCertSAFE);
-
- PCCERT_CONTEXT pCertContext = (PCCERT_CONTEXT) handle;
- PCCERT_CONTEXT pCertDup = NULL;
- BOOL bDelKeyContainer = FALSE;
- {
- GCX_PREEMP();
- if ((pCertDup = CertDuplicateCertificateContext(pCertContext)) == NULL)
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE));
-
- DATA_BLOB blob;
- DWORD cbData = 0;
- if (CertGetCertificateContextProperty(pCertDup,
- CERT_DELETE_KEYSET_PROP_ID, // This value should be defined in wincrypt.h
- // as well to avoid conflicts.
- (void*) &blob,
- &cbData))
- bDelKeyContainer = TRUE;
- }
-
- CERT_CTX* pCert = new CERT_CTX(pCertDup);
-#if !defined(FEATURE_CORECLR)
- pCert->m_fDelKeyContainer = bDelKeyContainer;
-#endif // !FEATURE_CORECLR
-
- pCertSAFE->SetHandle((void*) pCert);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// Free a handle to a CERT_CTX structure. Critical finalizer method for SafeCertContextHandle.
-//
-
-FCIMPL1(void, COMX509Certificate::FreePCertContext, INT_PTR pCertCtx)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_0();
-
- BOOL bRet = TRUE;
- CERT_CTX* pCert = (CERT_CTX*) pCertCtx;
-
- if (pCert)
- bRet = pCert->Release();
-
- // Add this assert to debug failures to free resources
- _ASSERTE(bRet);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// ASN encoded certificate as a byte array.
-//
-
-FCIMPL1(U1Array*, COMX509Certificate::GetCertRawData, SafeHandle* pCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
- U1ARRAYREF pbRawData = NULL;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(pbRawData, pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- CryptoHelper::ByteArrayToU1ARRAYREF(pCert->m_pCtx->pbCertEncoded,
- pCert->m_pCtx->cbCertEncoded,
- &pbRawData);
-
- HELPER_METHOD_FRAME_END();
- return (U1Array*) OBJECTREFToObject(pbRawData);
-}
-FCIMPLEND
-
-//
-// Returns the NotAfter field.
-//
-
-FCIMPL2(void, COMX509Certificate::GetDateNotAfter, SafeHandle* pCertUNSAFE, FILETIME* pFileTime)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_1(pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- pFileTime->dwLowDateTime = pCert->m_pCtx->pCertInfo->NotAfter.dwLowDateTime;
- pFileTime->dwHighDateTime = pCert->m_pCtx->pCertInfo->NotAfter.dwHighDateTime;
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// Returns the NotBefore field.
-//
-
-FCIMPL2(void, COMX509Certificate::GetDateNotBefore, SafeHandle* pCertUNSAFE, FILETIME* pFileTime)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_1(pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- pFileTime->dwLowDateTime = pCert->m_pCtx->pCertInfo->NotBefore.dwLowDateTime;
- pFileTime->dwHighDateTime = pCert->m_pCtx->pCertInfo->NotBefore.dwHighDateTime;
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// Issuer name as a string.
-//
-
-FCIMPL2(StringObject*, COMX509Certificate::GetIssuerName, SafeHandle* pCertUNSAFE, CLR_BOOL fLegacyV1Mode)
-{
- FCALL_CONTRACT;
-
- STRINGREF issuerString = NULL;
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(issuerString, pCertSAFE);
-
- DWORD dwStrType = CERT_X500_NAME_STR;
- if (!fLegacyV1Mode)
- dwStrType |= CERT_NAME_STR_REVERSE_FLAG;
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- DWORD cchCount = 0;
- if ((cchCount = CertGetNameString(pCert->m_pCtx,
- CERT_NAME_RDN_TYPE,
- CERT_NAME_ISSUER_FLAG,
- &dwStrType,
- NULL,
- 0)) == 0) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertGetNameString failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- NewArrayHolder<WCHAR> pwszIssuerName(new WCHAR[cchCount]);
- if (!CertGetNameString(pCert->m_pCtx,
- CERT_NAME_RDN_TYPE,
- CERT_NAME_ISSUER_FLAG,
- &dwStrType,
- pwszIssuerName,
- cchCount)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertGetNameString failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- issuerString = StringObject::NewString(pwszIssuerName);
-
- HELPER_METHOD_FRAME_END();
- return (StringObject*) OBJECTREFToObject(issuerString);
-}
-FCIMPLEND
-
-//
-// Returns the public key friendly name.
-//
-
-FCIMPL1(StringObject*, COMX509Certificate::GetPublicKeyOid, SafeHandle* pCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- STRINGREF oidString = NULL;
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(oidString, pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- NewArrayHolder<WCHAR> pwszOid(CryptoHelper::AnsiToUnicode((char*) pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId));
- oidString = StringObject::NewString(pwszOid);
-
- HELPER_METHOD_FRAME_END();
- return (StringObject*) OBJECTREFToObject(oidString);
-}
-FCIMPLEND
-
-//
-// Returns the public key ASN encoded parameters.
-//
-
-FCIMPL1(U1Array*, COMX509Certificate::GetPublicKeyParameters, SafeHandle* pCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- U1ARRAYREF pbParameters = NULL;
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(pbParameters, pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- BOOL bInheritedParams = FALSE;
-
-#if defined(FEATURE_CORECLR)
- // We'll support RSA-based certificates only in Telesto, not DSS.
- // This is in lieu of looking up the OID info, as it would require implementing
- // CryptFindOIDInfo in the PAL, along with the tables of OID infos relating to
- // at least the OIDs whose Algid's are CALG_DSS_SIGN.
- _ASSERTE(pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId != NULL);
- if(strncmp(szOID_RSA_RSA, pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, COUNTOF(szOID_RSA_RSA)) != 0)
- CryptoHelper::COMPlusThrowCrypto(COR_E_PLATFORMNOTSUPPORTED);
-#else // FEATURE_CORECLR
- PCCRYPT_OID_INFO pOidInfo = NULL;
- {
- GCX_PREEMP();
-
- // check to see if this is the most common case -- szOID_RSA_RSA. If so, we know that this is not
- // a DSS cert, so we don't need to get extra information about the OID to determine that. If it
- // is not, then we can first check in the public key OID group before falling back to check in
- // all OID groups.
- _ASSERTE(pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId != NULL);
- if(strncmp(szOID_RSA_RSA, pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, COUNTOF(szOID_RSA_RSA)) != 0)
- {
- pOidInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, CRYPT_PUBKEY_ALG_OID_GROUP_ID);
- if(pOidInfo == NULL)
- pOidInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, 0);
- }
- }
-
- //
- // DSS certificates may not have the DSS parameters in the certificate. In this case, we try to build
- // the certificate chain and propagate the parameters down from the certificate chain.
- //
-
- if (pOidInfo != NULL && pOidInfo->Algid == CALG_DSS_SIGN) {
- if ((pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData == 0) ||
- (*pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData == NULL_ASN_TAG)) {
- // Build the chain to inherit parameters in the property, if not already inherited.
- DWORD cbData = 0;
- HRESULT hr = S_OK;
- if (!CertGetCertificateContextProperty(pCert->m_pCtx,
- CERT_PUBKEY_ALG_PARA_PROP_ID,
- NULL,
- &cbData)) {
- // build the chain and ignore any errors during the chain building
- HandleCertChainHolder pChainContext = NULL;
- hr = X509Helper::BuildChain(pCert->m_pCtx, NULL, CERT_CHAIN_POLICY_BASE, &pChainContext);
- if (SUCCEEDED(hr)) {
- if (!CertGetCertificateContextProperty(pCert->m_pCtx,
- CERT_PUBKEY_ALG_PARA_PROP_ID,
- NULL,
- &cbData)) {
- hr = HRESULT_FROM_GetLastError();
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CERT_PUBKEY_ALG_PARA_PROP_ID property not found.\n", hr));
- }
- }
- }
- if (FAILED(hr))
- CryptoHelper::COMPlusThrowCrypto(hr);
-
- // The property exists; get it for real.
- NewArrayHolder<BYTE> pbData = new BYTE[cbData];
- if (!CertGetCertificateContextProperty(pCert->m_pCtx,
- CERT_PUBKEY_ALG_PARA_PROP_ID,
- (void*) pbData.GetValue(),
- &cbData))
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- CryptoHelper::ByteArrayToU1ARRAYREF(pbData, cbData, &pbParameters);
- bInheritedParams = TRUE;
- }
- }
-#endif // (FEATURE_CORECLR) else
-
- if (!bInheritedParams) {
- CryptoHelper::ByteArrayToU1ARRAYREF(pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
- pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData,
- &pbParameters);
- }
-
- HELPER_METHOD_FRAME_END();
- return (U1Array*) OBJECTREFToObject(pbParameters);
-}
-FCIMPLEND
-
-//
-// Returns the public key ASN encoded value.
-//
-
-FCIMPL1(U1Array*, COMX509Certificate::GetPublicKeyValue, SafeHandle* pCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- U1ARRAYREF pbKeyValue = NULL;
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(pbKeyValue, pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- CryptoHelper::ByteArrayToU1ARRAYREF(pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
- pCert->m_pCtx->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
- &pbKeyValue);
-
- HELPER_METHOD_FRAME_END();
- return (U1Array*) OBJECTREFToObject(pbKeyValue);
-}
-FCIMPLEND
-
-//
-// Serial number as a byte array.
-//
-
-FCIMPL1(U1Array*, COMX509Certificate::GetSerialNumber, SafeHandle* pCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
- U1ARRAYREF pbSerialNumber = NULL;
- HELPER_METHOD_FRAME_BEGIN_RET_2(pbSerialNumber, pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- CryptoHelper::ByteArrayToU1ARRAYREF(pCert->m_pCtx->pCertInfo->SerialNumber.pbData,
- pCert->m_pCtx->pCertInfo->SerialNumber.cbData,
- &pbSerialNumber);
-
- HELPER_METHOD_FRAME_END();
- return (U1Array*) OBJECTREFToObject(pbSerialNumber);
-}
-FCIMPLEND
-
-//
-// Subject info as a string.
-//
-
-FCIMPL3(StringObject*, COMX509Certificate::GetSubjectInfo, SafeHandle* pCertUNSAFE, DWORD dwDisplayType, CLR_BOOL fLegacyV1Mode)
-{
- FCALL_CONTRACT;
-
- STRINGREF subjectString = NULL;
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(subjectString, pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- DWORD dwStrType = CERT_X500_NAME_STR;
- if (!fLegacyV1Mode)
- dwStrType |= CERT_NAME_STR_REVERSE_FLAG;
- NewArrayHolder<WCHAR> pwszSubjName(GetCertNameInfo(pCert->m_pCtx, 0, dwDisplayType, dwStrType));
- subjectString = StringObject::NewString(pwszSubjName);
-
- HELPER_METHOD_FRAME_END();
- return (StringObject*) OBJECTREFToObject(subjectString);
-}
-FCIMPLEND
-
-//
-// Returns the thumbprint of the certificate.
-//
-
-FCIMPL1(U1Array*, COMX509Certificate::GetThumbprint, SafeHandle* pCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
- U1ARRAYREF pbThumbprint = NULL;
-
- HELPER_METHOD_FRAME_BEGIN_RET_2(pbThumbprint, pCertSAFE);
-
- SafeHandleHolder shh(&pCertSAFE);
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- DWORD dwSize = 0;
- if(!CertGetCertificateContextProperty(pCert->m_pCtx,
- CERT_SHA1_HASH_PROP_ID,
- NULL,
- &dwSize)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertGetCertificateContextProperty failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- pbThumbprint = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, dwSize);
- if(!CertGetCertificateContextProperty(pCert->m_pCtx,
- CERT_SHA1_HASH_PROP_ID,
- pbThumbprint->m_Array,
- &dwSize)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertGetCertificateContextProperty failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- HELPER_METHOD_FRAME_END();
- return (U1Array*) OBJECTREFToObject(pbThumbprint);
-}
-FCIMPLEND
-
-//
-// Opens the blob and gets its type, then loads a certificate from it. Depending on the blob type,
-// the blob can contain 1 or more certificates. If more than 1, we select the most likely choice.
-//
-
-FCIMPL5(void, COMX509Certificate::LoadCertFromBlob, U1Array* dataUNSAFE,
- __in_z WCHAR* pwszPassword, DWORD dwFlags, CLR_BOOL persistKeySet, SafeHandle** ppCertUNSAFE);
-{
- FCALL_CONTRACT;
-
- struct _gc {
- U1ARRAYREF dataSAFE;
- SAFEHANDLE pCertSAFE;
- } gc;
-
- gc.dataSAFE = (U1ARRAYREF) dataUNSAFE;
- gc.pCertSAFE = (SAFEHANDLE) *ppCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
-
- NewArrayHolder<BYTE> buffer(CryptoHelper::U1ARRAYREFToByteArray(gc.dataSAFE));
- CERT_BLOB certBlob = {gc.dataSAFE->GetNumComponents(), buffer};
- HandleCertContextHolder pCertContext(NULL);
-
- HandleCertStoreHolder hCertStore(NULL);
- HandleCryptMsgHolder hCryptMsg(NULL);
-
- DWORD dwContentType; dwContentType = X509Helper::LoadFromBlob(&certBlob,
- pwszPassword,
- X509_CERT_CONTENT_FLAGS,
- &pCertContext,
- &hCertStore,
- &hCryptMsg);
-
-#if !defined(FEATURE_CORECLR)
- if (dwContentType == CERT_QUERY_CONTENT_PKCS7_SIGNED
- || dwContentType == CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED) {
- pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg);
- } else if (dwContentType == CERT_QUERY_CONTENT_PFX) {
- pCertContext = FilterPFXStore(&certBlob, pwszPassword, dwFlags);
- }
-#endif // !FEATURE_CORECLR
-
- CERT_CTX* pCert = new CERT_CTX(pCertContext);
-#if !defined(FEATURE_CORECLR)
- if (dwContentType == CERT_QUERY_CONTENT_PFX)
- pCert->m_fDelKeyContainer = (persistKeySet == FALSE);
-#endif // !FEATURE_CORECLR
-
- gc.pCertSAFE->SetHandle((void*) pCert);
- pCertContext.SuppressRelease();
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// Opens the file and gets its type, then loads a certificate from it. Depending on the blob type,
-// the blob can contain 1 or more certificates. If more than 1, we select the most likely choice.
-//
-
-FCIMPL5(void, COMX509Certificate::LoadCertFromFile, StringObject* fileNameUNSAFE,
- __in_z WCHAR* pwszPassword, DWORD dwFlags, CLR_BOOL persistKeySet, SafeHandle** ppCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- struct _gc
- {
- STRINGREF fileNameSAFE;
- SAFEHANDLE pCertSAFE;
- } gc;
-
- gc.fileNameSAFE = (STRINGREF) fileNameUNSAFE;
- gc.pCertSAFE = (SAFEHANDLE) *ppCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
-
- NewArrayHolder<WCHAR> pwszFileName(CryptoHelper::STRINGREFToUnicode(gc.fileNameSAFE));
-
- HandleCertStoreHolder hCertStore(NULL);
- HandleCryptMsgHolder hCryptMsg(NULL);
-
- HandleCertContextHolder pCertContext(NULL);
- DWORD dwContentType; dwContentType = X509Helper::LoadFromFile(pwszFileName,
- pwszPassword,
- X509_CERT_CONTENT_FLAGS,
- &pCertContext,
- &hCertStore,
- &hCryptMsg);
-
-#if !defined(FEATURE_CORECLR)
- if (dwContentType == CERT_QUERY_CONTENT_PKCS7_SIGNED || dwContentType == CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED) {
- pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg);
- } else if (dwContentType == CERT_QUERY_CONTENT_PFX) {
- NewArrayHolder<BYTE> pb = NULL;
- DWORD cb = 0;
- // read the file
- HRESULT hr = X509Helper::ReadFileIntoMemory(gc.fileNameSAFE->GetBuffer(), &pb, &cb);
- if (FAILED(hr)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: ReadFileIntoMemory failed.\n", hr));
- CryptoHelper::COMPlusThrowCrypto(hr);
- }
- CERT_BLOB certBlob = {cb, pb};
- pCertContext = FilterPFXStore(&certBlob, pwszPassword, dwFlags);
- }
-#endif // !FEATURE_CORECLR
-
- CERT_CTX* pCert = new CERT_CTX(pCertContext);
-#if !defined(FEATURE_CORECLR)
- if (dwContentType == CERT_QUERY_CONTENT_PFX)
- pCert->m_fDelKeyContainer = (persistKeySet == FALSE);
-#endif // !FEATURE_CORECLR
-
- gc.pCertSAFE->SetHandle((void*) pCert);
- pCertContext.SuppressRelease();
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// This method opens the blob and returns its type.
-//
-
-FCIMPL1(DWORD, COMX509Certificate::QueryCertBlobType, U1Array* dataUNSAFE)
-{
- FCALL_CONTRACT;
-
- DWORD dwContentType = 0;
- U1ARRAYREF dataSAFE = (U1ARRAYREF) dataUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_1(dataSAFE);
-
- NewArrayHolder<BYTE> buffer(CryptoHelper::U1ARRAYREFToByteArray(dataSAFE));
- CERT_BLOB certBlob = {dataSAFE->GetNumComponents(), buffer};
-
- {
- GCX_PREEMP();
- if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
- &certBlob,
- X509_CERT_CONTENT_FLAGS,
- X509_CERT_FORMAT_FLAGS,
- 0,
- NULL,
- &dwContentType,
- NULL,
- NULL,
- NULL,
- NULL)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptQueryObject failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- }
-
- HELPER_METHOD_FRAME_END();
- return dwContentType;
-
-}
-FCIMPLEND
-
-//
-// This method opens the file and returns its type.
-//
-
-FCIMPL1(DWORD, COMX509Certificate::QueryCertFileType, StringObject* fileNameUNSAFE)
-{
- FCALL_CONTRACT;
-
- DWORD dwContentType = 0;
- STRINGREF fileNameSAFE = (STRINGREF) fileNameUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_1(fileNameSAFE);
-
- NewArrayHolder<WCHAR> buffer(CryptoHelper::STRINGREFToUnicode(fileNameSAFE));
-
- {
- GCX_PREEMP();
- if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
- buffer,
- X509_CERT_CONTENT_FLAGS,
- X509_CERT_FORMAT_FLAGS,
- 0,
- NULL,
- &dwContentType,
- NULL,
- NULL,
- NULL,
- NULL)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CryptQueryObject failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- }
-
- HELPER_METHOD_FRAME_END();
- return dwContentType;
-
-}
-FCIMPLEND
-
-//
-// FCALL methods
-//
-
-#if !defined(FEATURE_CORECLR)
-//
-// Add a certificate to the store.
-// Added certificates are not persisted for non-system stores.
-//
-
-FCIMPL2(void, COMX509Store::AddCertificate, SafeHandle* hStoreUNSAFE, SafeHandle* pCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE hStoreSAFE = (SAFEHANDLE) hStoreUNSAFE;
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_2(hStoreSAFE, pCertSAFE);
-
- SafeHandleHolder shh1(&hStoreSAFE);
- SafeHandleHolder shh2(&pCertSAFE);
-
- HCERTSTORE hCertStore = (HCERTSTORE) hStoreSAFE->GetHandle();
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- GCX_PREEMP();
- if (!CertAddCertificateLinkToStore(hCertStore,
- pCert->m_pCtx,
- CERT_STORE_ADD_ALWAYS,
- NULL)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertAddCertificateContextToStore failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// Exports a memory store of certificates into a byte array.
-//
-
-FCIMPL3(U1Array*, COMX509Store::ExportCertificatesToBlob, SafeHandle* hStoreUNSAFE, DWORD dwContentType, __in_z WCHAR* pwszPassword)
-{
- FCALL_CONTRACT;
-
- struct _gc
- {
- U1ARRAYREF pbBlob;
- SAFEHANDLE hStoreSAFE;
- } gc;
-
- gc.pbBlob = NULL;
- gc.hStoreSAFE = (SAFEHANDLE) hStoreUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- SafeHandleHolder shh(&gc.hStoreSAFE);
- HCERTSTORE hCertStore = (HCERTSTORE) gc.hStoreSAFE->GetHandle();
-
- HandleCertContextHolder pEnumContext(NULL);
- NewArrayHolder<BYTE> pbEncoded(NULL);
- DWORD dwSaveAs = CERT_STORE_SAVE_AS_PKCS7;
- CRYPT_DATA_BLOB DataBlob = {0, NULL};
-
- switch(dwContentType) {
- case X509_CERT_TYPE:
- pEnumContext = CertEnumCertificatesInStore(hCertStore, pEnumContext);
- if (pEnumContext.GetValue() != NULL)
- CryptoHelper::ByteArrayToU1ARRAYREF(pEnumContext->pbCertEncoded,
- pEnumContext->cbCertEncoded,
- &gc.pbBlob);
- break;
-
- case X509_SERIALIZED_CERT_TYPE:
- pEnumContext = CertEnumCertificatesInStore(hCertStore, pEnumContext);
- if (pEnumContext.GetValue() != NULL) {
- DWORD cbEncoded = 0;
- if (!CertSerializeCertificateStoreElement(pEnumContext,
- 0,
- NULL,
- &cbEncoded)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertSerializeCertificateStoreElement failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- pbEncoded = new BYTE[cbEncoded];
- if (!CertSerializeCertificateStoreElement(pEnumContext,
- 0,
- pbEncoded,
- &cbEncoded)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertSerializeCertificateStoreElement failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- CryptoHelper::ByteArrayToU1ARRAYREF(pbEncoded, cbEncoded, &gc.pbBlob);
- }
- break;
-
- case X509_PFX_TYPE:
- {
- GCX_PREEMP();
- if (!PFXExportCertStore(hCertStore,
- &DataBlob,
- pwszPassword,
- EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: PFXExportCertStorePFXExportCertStore failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- pbEncoded = new BYTE[DataBlob.cbData];
- DataBlob.pbData = pbEncoded;
- if (!PFXExportCertStore(hCertStore,
- &DataBlob,
- pwszPassword,
- EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: PFXExportCertStorePFXExportCertStore failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- }
- CryptoHelper::ByteArrayToU1ARRAYREF(DataBlob.pbData, DataBlob.cbData, &gc.pbBlob);
- break;
-
- case X509_SERIALIZED_STORE_TYPE:
- dwSaveAs = CERT_STORE_SAVE_AS_STORE;
- // falling through
- case X509_PKCS7_TYPE:
- {
- GCX_PREEMP();
- // determine the required length
- if (!CertSaveStore(hCertStore,
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- dwSaveAs,
- CERT_STORE_SAVE_TO_MEMORY,
- (void *) &DataBlob,
- 0)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertSaveStore failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- pbEncoded = new BYTE[DataBlob.cbData];
- DataBlob.pbData = pbEncoded;
- // now save the store to a memory blob
- if (!CertSaveStore(hCertStore,
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- dwSaveAs,
- CERT_STORE_SAVE_TO_MEMORY,
- (void *) &DataBlob,
- 0)) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertSaveStore failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- }
- CryptoHelper::ByteArrayToU1ARRAYREF(DataBlob.pbData, DataBlob.cbData, &gc.pbBlob);
- break;
-
- default:
- COMPlusThrow(kCryptographicException, W("Cryptography_X509_InvalidContentType"));
- }
-
- HELPER_METHOD_FRAME_END();
- return (U1Array*) OBJECTREFToObject(gc.pbBlob);
-}
-FCIMPLEND
-
-//
-// Free an HCERTSTORE handle. Critical finalizer method for SafeCertStoreHandle.
-//
-
-FCIMPL1(void, COMX509Store::FreeCertStoreContext, INT_PTR hCertStore)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_0();
-
- BOOL bRet = TRUE;
- HCERTSTORE hStore = (HCERTSTORE) hCertStore;
- if (hStore)
- bRet = CertCloseStore(hStore, 0);
-
- // Add this assert to debug failures to free resources
- _ASSERTE(bRet);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-//
-// Open a certificate store.
-//
-
-FCIMPL4(void, COMX509Store::OpenX509Store, DWORD dwType, DWORD dwFlags, StringObject* storeNameUNSAFE, SafeHandle** phStoreUNSAFE)
-{
- FCALL_CONTRACT;
-
- STRINGREF storeNameSAFE = (STRINGREF) storeNameUNSAFE;
- SAFEHANDLE hStoreSAFE = (SAFEHANDLE) *phStoreUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_2(storeNameSAFE, hStoreSAFE);
-
- NewArrayHolder<WCHAR> pwszStoreName(NULL);
- if (storeNameSAFE != NULL) {
- DWORD dwSize = storeNameSAFE->GetStringLength();
- if (dwSize > 0)
- pwszStoreName = CryptoHelper::STRINGREFToUnicode(storeNameSAFE);
- }
-
- HCERTSTORE hCertStore = NULL;
- {
- GCX_PREEMP();
- hCertStore = CertOpenStore((LPCSTR)(size_t)dwType,
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- NULL,
- dwFlags | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
- pwszStoreName);
- if (hCertStore == NULL) {
- LOG((LF_SECURITY, LL_INFO10000, "Error [%#x]: CertOpenStore failed.\n", HRESULT_FROM_GetLastError()));
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
- }
- }
-
- hStoreSAFE->SetHandle(hCertStore);
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-// COMX509Store::RemoveCertificate is an FCALL that is not consumed by managed code
-// nor is it referred to by native code. This #ifdef makes it be dead code, which it
-// would otherwise not be and require CertFindCertificateInStore, which is otherwise
-// not required, and thus does not need to get implemented in the PAL.
-
-//
-// Remove a certificate from the store.
-// Removed certificates are not persisted for non-system stores.
-//
-
-FCIMPL2(void, COMX509Store::RemoveCertificate, SafeHandle* hStoreUNSAFE, SafeHandle* pCertUNSAFE)
-{
- FCALL_CONTRACT;
-
- SAFEHANDLE hStoreSAFE = (SAFEHANDLE) hStoreUNSAFE;
- SAFEHANDLE pCertSAFE = (SAFEHANDLE) pCertUNSAFE;
-
- HELPER_METHOD_FRAME_BEGIN_2(hStoreSAFE, pCertSAFE);
-
- SafeHandleHolder shh1(&hStoreSAFE);
- SafeHandleHolder shh2(&pCertSAFE);
-
- HCERTSTORE hCertStore = (HCERTSTORE) hStoreSAFE->GetHandle();
- CERT_CTX* pCert = CryptoHelper::DereferenceSafeHandle<CERT_CTX>(pCertSAFE);
-
- // Find the certificate in the store.
- PCCERT_CONTEXT pCert2 = NULL;
- if ((pCert2 = CertFindCertificateInStore(hCertStore,
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- 0,
- CERT_FIND_EXISTING,
- (const void *) pCert->m_pCtx,
- NULL)) == NULL)
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- // Remove from the store.
- if (!CertDeleteCertificateFromStore(pCert2))
- // CertDeleteCertificateFromStore always releases the context regardless of success
- // or failure so we don't need to manually release it
- CryptoHelper::COMPlusThrowCrypto(HRESULT_FROM_GetLastError());
-
- HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-#endif // !FEATURE_CORECLR
-
-#endif // FEATURE_X509
diff --git a/src/classlibnative/cryptography/x509certificate.h b/src/classlibnative/cryptography/x509certificate.h
deleted file mode 100644
index 3f0dd20b26..0000000000
--- a/src/classlibnative/cryptography/x509certificate.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-//+--------------------------------------------------------------------------
-//
-
-//
-//---------------------------------------------------------------------------
-//
-
-//
-
-
-#ifndef _X509CERTIFICATE_H_
-#define _X509CERTIFICATE_H_
-
-#include "cryptography.h"
-
-#define CERT_DELETE_KEYSET_PROP_ID 101 // This value shall be defined in wincrypt.h later to avoid conflicts.
-
-#if defined(FEATURE_CORECLR)
-#define X509_CERT_CONTENT_FLAGS CERT_QUERY_CONTENT_FLAG_CERT
-#define X509_CERT_FORMAT_FLAGS CERT_QUERY_FORMAT_FLAG_BINARY
-#else // !FEATURE_CORECLR
-#define X509_CERT_CONTENT_FLAGS (\
- CERT_QUERY_CONTENT_FLAG_CERT | CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT | \
- CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | \
- CERT_QUERY_CONTENT_FLAG_PFX)
-#define X509_CERT_FORMAT_FLAGS CERT_QUERY_FORMAT_FLAG_ALL
-#endif // (FEATURE_CORECLR) else
-
-FORCEINLINE void VoidCertFreeCertificateContext(PCCERT_CONTEXT pCert) { LIMITED_METHOD_CONTRACT; CertFreeCertificateContext(pCert); }
-FORCEINLINE void VoidCertCloseStore(HCERTSTORE hCertStore) { LIMITED_METHOD_CONTRACT; CertCloseStore(hCertStore, 0); }
-FORCEINLINE void VoidCryptMsgClose(HCRYPTMSG hCryptMsg) { LIMITED_METHOD_CONTRACT; CryptMsgClose(hCryptMsg); }
-#if !defined(FEATURE_CORECLR)
-FORCEINLINE void VoidCertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext) { LIMITED_METHOD_CONTRACT; CertFreeCertificateChain(pChainContext); }
-#endif // !FEATURE_CORECLR
-
-typedef Wrapper<PCCERT_CONTEXT, DoNothing<PCCERT_CONTEXT>, VoidCertFreeCertificateContext, 0> HandleCertContextHolder;
-typedef Wrapper<HCERTSTORE, DoNothing<HCERTSTORE>, VoidCertCloseStore, 0> HandleCertStoreHolder;
-typedef Wrapper<HCRYPTMSG, DoNothing<HCRYPTMSG>, VoidCryptMsgClose, 0> HandleCryptMsgHolder;
-#if !defined(FEATURE_CORECLR)
-typedef Wrapper<PCCERT_CHAIN_CONTEXT, DoNothing<PCCERT_CHAIN_CONTEXT>, VoidCertFreeCertificateChain, 0> HandleCertChainHolder;
-#endif // !FEATURE_CORECLR
-
-class X509Helper {
-public:
-#if !defined(FEATURE_CORECLR)
- static HRESULT BuildChain (PCCERT_CONTEXT pCertContext, HCERTSTORE hCertStore,
- LPCSTR pszPolicy, PCCERT_CHAIN_CONTEXT * ppChainContext);
- static HRESULT DecodeObject(LPCSTR pszStructType, LPBYTE pbEncoded,
- DWORD cbEncoded, void** ppvDecoded, DWORD* pcbDecoded);
- static BOOL DeleteKeyContainer (PCCERT_CONTEXT pCertContext);
-#endif // !FEATURE_CORECLR
- static DWORD LoadFromBlob (CERT_BLOB* pCertBlob, __in_opt WCHAR* pwszPassword, DWORD dwFlags,
- PCCERT_CONTEXT* pCertContext, HCERTSTORE* phCertStore, HCRYPTMSG* phCryptMsg);
- static DWORD LoadFromFile (__in_z WCHAR* pwszFileName, __in_opt WCHAR* pwszPassword, DWORD dwFlags,
- PCCERT_CONTEXT* pCertContext, HCERTSTORE* phCertStore, HCRYPTMSG* phCryptMsg);
- static HRESULT ReadFileIntoMemory(LPCWSTR wszFileName, LPBYTE* ppbBuffer, DWORD* pdwBufLen);
-};
-
-class COMX509Certificate {
-private:
-#if !defined(FEATURE_CORECLR)
- static PCCERT_CONTEXT FilterPFXStore (CERT_BLOB* pfxBlob, __in_z WCHAR* pwszPassword, DWORD dwFlags);
-#endif // !FEATURE_CORECLR
- static WCHAR* GetCertNameInfo(PCCERT_CONTEXT pCertContext, DWORD dwNameType, DWORD dwDisplayType, DWORD dwStrType);
-#if !defined(FEATURE_CORECLR)
- static PCCERT_CONTEXT GetSignerInPKCS7Store (HCERTSTORE hCertStore, HCRYPTMSG hCryptMsg);
-#endif // !FEATURE_CORECLR
-
-public:
- static FCDECL2(void, DuplicateCertContext, INT_PTR handle, SafeHandle** ppCertUNSAFE);
- static FCDECL1(void, FreePCertContext, INT_PTR pCertCtx);
- static FCDECL1(U1Array*, GetCertRawData, SafeHandle* pCertUNSAFE);
- static FCDECL2(void, GetDateNotAfter, SafeHandle* pCertUNSAFE, FILETIME* pFileTime);
- static FCDECL2(void, GetDateNotBefore, SafeHandle* pCertUNSAFE, FILETIME* pFileTime);
- static FCDECL2(StringObject*, GetIssuerName, SafeHandle* pCertUNSAFE, CLR_BOOL fLegacyV1Mode);
- static FCDECL1(StringObject*, GetPublicKeyOid, SafeHandle* pCertUNSAFE);
- static FCDECL1(U1Array*, GetPublicKeyParameters, SafeHandle* pCertUNSAFE);
- static FCDECL1(U1Array*, GetPublicKeyValue, SafeHandle* pCertUNSAFE);
- static FCDECL1(U1Array*, GetSerialNumber, SafeHandle* pCertUNSAFE);
- static FCDECL3(StringObject*, GetSubjectInfo, SafeHandle* pCertUNSAFE, DWORD dwDisplayType, CLR_BOOL fLegacyV1Mode);
- static FCDECL1(U1Array*, GetThumbprint, SafeHandle* pCertUNSAFE);
- static FCDECL5(void, LoadCertFromBlob, U1Array* dataUNSAFE, __in_z WCHAR* pwszPassword, DWORD dwFlags, CLR_BOOL persistKeySet, SafeHandle** ppCertUNSAFE);
- static FCDECL5(void, LoadCertFromFile, StringObject* fileNameUNSAFE, __in_z WCHAR* pwszPassword, DWORD dwFlags, CLR_BOOL persistKeySet, SafeHandle** ppCertUNSAFE);
- static FCDECL1(DWORD, QueryCertBlobType, U1Array* dataUNSAFE);
- static FCDECL1(DWORD, QueryCertFileType, StringObject* fileNameUNSAFE);
-};
-
-#define X509_STORE_CONTENT_FLAGS (\
- CERT_QUERY_CONTENT_FLAG_CERT | CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT | \
- CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | \
- CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED | CERT_QUERY_CONTENT_FLAG_PFX | \
- CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE)
-
-#define NULL_ASN_TAG 0x05
-
-// Keep in sync with System.Security.Cryptography.X509Certificates.X509ContentType
-enum X509_ASSERTION_CONTENT_TYPE {
- UNKNOWN_TYPE = 0x00,
- X509_CERT_TYPE = 0x01,
- X509_SERIALIZED_CERT_TYPE = 0x02,
- X509_PFX_TYPE = 0x03,
- X509_SERIALIZED_STORE_TYPE = 0x04,
- X509_PKCS7_TYPE = 0x05,
- X509_AUTHENTICODE_TYPE = 0x06
-};
-
-// We need to define this unmanaged memory structure to hold
-// all the information relevant to the cert context in order to guarantee
-// critical finalization of the resources
-typedef struct CERT_CTX {
-public:
- PCCERT_CONTEXT m_pCtx;
-#if !defined(FEATURE_CORECLR)
- BOOL m_fDelKeyContainer;
-#endif // !FEATURE_CORECLR
-
- CERT_CTX(PCCERT_CONTEXT pCertContext) :
- m_pCtx(pCertContext)
-#if !defined(FEATURE_CORECLR)
- ,m_fDelKeyContainer(FALSE)
-#endif // !FEATURE_CORECLR
- {
- LIMITED_METHOD_CONTRACT;
- }
-
- // This method should not be called twice.
- BOOL Release () {
- WRAPPER_NO_CONTRACT;
-#if !defined(FEATURE_CORECLR)
- if (m_fDelKeyContainer)
- X509Helper::DeleteKeyContainer(m_pCtx);
-#endif // !FEATURE_CORECLR
-
- // We need to free the cert context.
- if (m_pCtx != NULL)
- if (!CertFreeCertificateContext(m_pCtx))
- return FALSE;
-
- m_pCtx = 0;
- delete this;
- return TRUE;
- }
-
-} CERT_CTX;
-
-#ifndef FEATURE_CORECLR
-class COMX509Store {
-public:
- static FCDECL2(void, AddCertificate, SafeHandle* hStoreUNSAFE, SafeHandle* pCertUNSAFE);
- static FCDECL3(U1Array*, ExportCertificatesToBlob, SafeHandle* hStoreUNSAFE, DWORD dwContentType, __in_z WCHAR* pwszPassword);
- static FCDECL1(void, FreeCertStoreContext, INT_PTR hCertStore);
- static FCDECL4(void, OpenX509Store, DWORD dwType, DWORD dwFlags, StringObject* storeNameUNSAFE, SafeHandle** phStoreUNSAFE);
- // RemoveCertificate is an FCALL that is not consumed by managed code
- // nor is it referred to by native code. This #ifdef makes it be dead code, which it
- // would otherwise not be and require CertFindCertificateInStore, which is otherwise
- // not required, and thus does not need to get implemented in the PAL.
- static FCDECL2(void, RemoveCertificate, SafeHandle* hStoreUNSAFE, SafeHandle* pCertUNSAFE);
-};
-#endif // !FEATURE_CORECLR
-
-#endif // !_X509CERTIFICATE_H_