//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: sp3crmsg.cpp // //-------------------------------------------------------------------------- //+------------------------------------------------------------------------- // File: sp3crmsg.cpp // // Contents: Installable OID functions providing backwards compatiblity // with the way the NT4.0 SP3 and IE 3.02 versions of crypt32.dll // encrypted the symmetric key in a PKCS #7 EnvelopedData message. // // The SP3 version of crypt32.dll failed to byte reverse the // encrypted symmetric key. It also added zero salt instead // of no salt. // // Functions: DllMain // DllRegisterServer // DllUnregisterServer // SP3ImportEncryptKey // SP3GenEncryptKey // SP3ExportEncryptKey #ifdef CMS_PKCS7 // DllInstall // CryptMsgDllGenContentEncryptKey // CryptMsgDllExportKeyTrans // CryptMsgDllImportKeyTrans // NotImplCryptMsgDllImportKeyTrans #endif // CMS_PKCS7 //-------------------------------------------------------------------------- #define CMS_PKCS7 1 #include #include #include "sp3crmsg.h" // memory management #define SP3Alloc(cb) ((void*)LocalAlloc(LPTR, cb)) #define SP3Free(pv) (LocalFree((HLOCAL)pv)) // The Thread Local Storage (TLS) referenced by iSP3TLS has pointer of // ((void *) 0x1) if SP3 compatible encryption is enabled. Otherwise, its 0. static DWORD iSP3TLS = 0xFFFFFFFF; #define SP3_TLS_POINTER ((void *) 0x1) typedef struct _SIMPLEBLOBHEADER { ALG_ID aiEncAlg; } SIMPLEBLOBHEADER, *PSIMPLEBLOBHEADER; typedef struct _OID_REG_ENTRY { LPCSTR pszOID; LPCSTR pszOverrideFuncName; } OID_REG_ENTRY, *POID_REG_ENTRY; //+------------------------------------------------------------------------- // ImportEncryptKey OID Installable Functions //-------------------------------------------------------------------------- static HCRYPTOIDFUNCSET hImportEncryptKeyFuncSet; static PFN_CMSG_IMPORT_ENCRYPT_KEY pfnDefaultImportEncryptKey = NULL; BOOL WINAPI SP3ImportEncryptKey( IN HCRYPTPROV hCryptProv, IN DWORD dwKeySpec, IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt, IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey, IN PBYTE pbEncodedKey, IN DWORD cbEncodedKey, OUT HCRYPTKEY *phEncryptKey); static const CRYPT_OID_FUNC_ENTRY ImportEncryptKeyFuncTable[] = { szOID_OIWSEC_desCBC, SP3ImportEncryptKey, szOID_RSA_RC2CBC, SP3ImportEncryptKey, szOID_RSA_RC4, SP3ImportEncryptKey }; #define IMPORT_ENCRYPT_KEY_FUNC_COUNT (sizeof(ImportEncryptKeyFuncTable) / \ sizeof(ImportEncryptKeyFuncTable[0])) static const OID_REG_ENTRY ImportEncryptKeyRegTable[] = { szOID_OIWSEC_desCBC, "SP3ImportEncryptKey", szOID_RSA_RC2CBC, "SP3ImportEncryptKey", szOID_RSA_RC4, "SP3ImportEncryptKey" }; #define IMPORT_ENCRYPT_KEY_REG_COUNT (sizeof(ImportEncryptKeyRegTable) / \ sizeof(ImportEncryptKeyRegTable[0])) //+------------------------------------------------------------------------- // GenEncryptKey OID Installable Functions //-------------------------------------------------------------------------- static HCRYPTOIDFUNCSET hGenEncryptKeyFuncSet; static PFN_CMSG_GEN_ENCRYPT_KEY pfnDefaultGenEncryptKey = NULL; BOOL WINAPI SP3GenEncryptKey( IN OUT HCRYPTPROV *phCryptProv, IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt, IN PVOID pvEncryptAuxInfo, IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo, IN PFN_CMSG_ALLOC pfnAlloc, OUT HCRYPTKEY *phEncryptKey, OUT PBYTE *ppbEncryptParameters, OUT PDWORD pcbEncryptParameters); static const CRYPT_OID_FUNC_ENTRY GenEncryptKeyFuncTable[] = { szOID_OIWSEC_desCBC, SP3GenEncryptKey, szOID_RSA_RC2CBC, SP3GenEncryptKey, szOID_RSA_RC4, SP3GenEncryptKey }; #define GEN_ENCRYPT_KEY_FUNC_COUNT (sizeof(GenEncryptKeyFuncTable) / \ sizeof(GenEncryptKeyFuncTable[0])) static const OID_REG_ENTRY GenEncryptKeyRegTable[] = { szOID_OIWSEC_desCBC, "SP3GenEncryptKey", szOID_RSA_RC2CBC, "SP3GenEncryptKey", szOID_RSA_RC4, "SP3GenEncryptKey" }; #define GEN_ENCRYPT_KEY_REG_COUNT (sizeof(GenEncryptKeyRegTable) / \ sizeof(GenEncryptKeyRegTable[0])) //+------------------------------------------------------------------------- // ExportEncryptKey OID Installable Functions //-------------------------------------------------------------------------- static HCRYPTOIDFUNCSET hExportEncryptKeyFuncSet; static PFN_CMSG_EXPORT_ENCRYPT_KEY pfnDefaultExportEncryptKey = NULL; BOOL WINAPI SP3ExportEncryptKey( IN HCRYPTPROV hCryptProv, IN HCRYPTKEY hEncryptKey, IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo, OUT PBYTE pbData, IN OUT PDWORD pcbData); static const CRYPT_OID_FUNC_ENTRY ExportEncryptKeyFuncTable[] = { szOID_RSA_RSA, SP3ExportEncryptKey }; #define EXPORT_ENCRYPT_KEY_FUNC_COUNT (sizeof(ExportEncryptKeyFuncTable) / \ sizeof(ExportEncryptKeyFuncTable[0])) static const OID_REG_ENTRY ExportEncryptKeyRegTable[] = { szOID_RSA_RSA, "SP3ExportEncryptKey" }; #define EXPORT_ENCRYPT_KEY_REG_COUNT (sizeof(ExportEncryptKeyRegTable) / \ sizeof(ExportEncryptKeyRegTable[0])) static char szCrypt32[]="crypt32.dll"; // First post IE4.0 versions of crypt32.dll start with "5.101.1681.1" static DWORD dwLowVersion = (1681 << 16) | 1; static DWORD dwHighVersion = (5 << 16) | 101; static BOOL IsPostIE4Crypt32() { BOOL fPostIE4 = FALSE; // default to IE4 DWORD dwHandle = 0; DWORD cbInfo; void *pvInfo = NULL; VS_FIXEDFILEINFO *pFixedFileInfo = NULL; // not allocated UINT ccFixedFileInfo = 0; if (0 == (cbInfo = GetFileVersionInfoSizeA(szCrypt32, &dwHandle))) goto ErrorReturn; if (NULL == (pvInfo = SP3Alloc(cbInfo))) goto ErrorReturn; if (!GetFileVersionInfoA( szCrypt32, 0, // dwHandle, ignored cbInfo, pvInfo )) goto ErrorReturn; if (!VerQueryValueA( pvInfo, "\\", // VS_FIXEDFILEINFO (void **) &pFixedFileInfo, &ccFixedFileInfo )) goto ErrorReturn; if (pFixedFileInfo->dwFileVersionMS > dwHighVersion || (pFixedFileInfo->dwFileVersionMS == dwHighVersion && pFixedFileInfo->dwFileVersionLS >= dwLowVersion)) fPostIE4 = TRUE; CommonReturn: if (pvInfo) SP3Free(pvInfo); return fPostIE4; ErrorReturn: goto CommonReturn; } static HRESULT HError() { DWORD dw = GetLastError(); HRESULT hr; if ( dw <= 0xFFFF ) hr = HRESULT_FROM_WIN32 ( dw ); else hr = dw; if ( ! FAILED ( hr ) ) { // somebody failed a call without properly setting an error condition hr = E_UNEXPECTED; } return hr; } STDAPI DllRegisterServer(void) { int i; DWORD dwFlags = CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG; for (i = 0; i < IMPORT_ENCRYPT_KEY_REG_COUNT; i++) { if (!CryptRegisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC, ImportEncryptKeyRegTable[i].pszOID, L"sp3crmsg.dll", ImportEncryptKeyRegTable[i].pszOverrideFuncName )) return HError(); if (!CryptSetOIDFunctionValue( X509_ASN_ENCODING, CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC, ImportEncryptKeyRegTable[i].pszOID, CRYPT_OID_REG_FLAGS_VALUE_NAME, REG_DWORD, (BYTE *) &dwFlags, sizeof(dwFlags) )) return HError(); } for (i = 0; i < GEN_ENCRYPT_KEY_REG_COUNT; i++) { if (!CryptRegisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_GEN_ENCRYPT_KEY_FUNC, GenEncryptKeyRegTable[i].pszOID, L"sp3crmsg.dll", GenEncryptKeyRegTable[i].pszOverrideFuncName )) return HError(); if (!CryptSetOIDFunctionValue( X509_ASN_ENCODING, CMSG_OID_GEN_ENCRYPT_KEY_FUNC, GenEncryptKeyRegTable[i].pszOID, CRYPT_OID_REG_FLAGS_VALUE_NAME, REG_DWORD, (BYTE *) &dwFlags, sizeof(dwFlags) )) return HError(); } for (i = 0; i < EXPORT_ENCRYPT_KEY_REG_COUNT; i++) { if (!CryptRegisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC, ExportEncryptKeyRegTable[i].pszOID, L"sp3crmsg.dll", ExportEncryptKeyRegTable[i].pszOverrideFuncName )) return HError(); if (!CryptSetOIDFunctionValue( X509_ASN_ENCODING, CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC, ExportEncryptKeyRegTable[i].pszOID, CRYPT_OID_REG_FLAGS_VALUE_NAME, REG_DWORD, (BYTE *) &dwFlags, sizeof(dwFlags) )) return HError(); } return S_OK; } STDAPI DllUnregisterServer(void) { HRESULT hr = S_OK; int i; for (i = 0; i < IMPORT_ENCRYPT_KEY_REG_COUNT; i++) { if (!CryptUnregisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC, ImportEncryptKeyRegTable[i].pszOID )) { if (ERROR_FILE_NOT_FOUND != GetLastError()) hr = HError(); } } for (i = 0; i < GEN_ENCRYPT_KEY_REG_COUNT; i++) { if (!CryptUnregisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_GEN_ENCRYPT_KEY_FUNC, GenEncryptKeyRegTable[i].pszOID )) { if (ERROR_FILE_NOT_FOUND != GetLastError()) hr = HError(); } } for (i = 0; i < EXPORT_ENCRYPT_KEY_REG_COUNT; i++) { if (!CryptUnregisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC, ExportEncryptKeyRegTable[i].pszOID )) { if (ERROR_FILE_NOT_FOUND != GetLastError()) hr = HError(); } } #ifdef CMS_PKCS7 if (!CryptUnregisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC, szOID_RSA_RC2CBC )) { if (ERROR_FILE_NOT_FOUND != GetLastError()) hr = HError(); } if (!CryptUnregisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_EXPORT_KEY_TRANS_FUNC, szOID_RSA_RSA )) { if (ERROR_FILE_NOT_FOUND != GetLastError()) hr = HError(); } if (!CryptUnregisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_IMPORT_KEY_TRANS_FUNC, szOID_RSA_RSA "!" szOID_RSA_RC2CBC )) { if (ERROR_FILE_NOT_FOUND != GetLastError()) hr = HError(); } if (!CryptUnregisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_IMPORT_KEY_TRANS_FUNC, szOID_RSA_RC2CBC )) { if (ERROR_FILE_NOT_FOUND != GetLastError()) hr = HError(); } #endif // CMS_PKCS7 return hr; } #ifdef CMS_PKCS7 //+--------------------------------------------------------------------------- // // Function: DllInstall // // Synopsis: dll installation entry point // //---------------------------------------------------------------------------- STDAPI DllInstall (BOOL fRegister, LPCSTR pszCommand) { if (!fRegister) return DllUnregisterServer(); if (!CryptRegisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC, szOID_RSA_RC2CBC, L"sp3crmsg.dll", NULL // pszOverrideFuncName )) return HError(); if (!CryptRegisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_EXPORT_KEY_TRANS_FUNC, szOID_RSA_RSA, L"sp3crmsg.dll", NULL // pszOverrideFuncName )) return HError(); if (!CryptRegisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_IMPORT_KEY_TRANS_FUNC, szOID_RSA_RSA "!" szOID_RSA_RC2CBC, L"sp3crmsg.dll", "NotImplCryptMsgDllImportKeyTrans" )) return HError(); if (!CryptRegisterOIDFunction( X509_ASN_ENCODING, CMSG_OID_IMPORT_KEY_TRANS_FUNC, szOID_RSA_RC2CBC, L"sp3crmsg.dll", NULL // pszOverrideFuncName )) return HError(); return S_OK; } #endif // CMS_PKCS7 //+------------------------------------------------------------------------- // Function: DllMain // // Synopsis: Process/Thread attach/detach // // At process attach install the SP3 compatible version of // CryptMsgDllImportEncryptKey, CryptMsgDllGenEncryptKey and // CryptMsgDllExportEncryptKey. //-------------------------------------------------------------------------- BOOL WINAPI DllMain( HMODULE hInst, ULONG ulReason, LPVOID lpReserved) { BOOL fResult; HCRYPTOIDFUNCADDR hFuncAddr; switch (ulReason) { case DLL_PROCESS_ATTACH: #if 0 // Post IE 4.0 releases of crypt32.dll already have the SP3 // backwards compatible fix. if (IsPostIE4Crypt32()) return TRUE; #endif if (NULL == (hImportEncryptKeyFuncSet = CryptInitOIDFunctionSet( CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC, 0))) goto ErrorReturn; if (NULL == (hGenEncryptKeyFuncSet = CryptInitOIDFunctionSet( CMSG_OID_GEN_ENCRYPT_KEY_FUNC, 0))) goto ErrorReturn; if (NULL == (hExportEncryptKeyFuncSet = CryptInitOIDFunctionSet( CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC, 0))) goto ErrorReturn; // Get the default import encrypt key function which we will call if // unable to do a successful import without byte reversing the // encrypted symmetric key. if (CryptGetOIDFunctionAddress( hImportEncryptKeyFuncSet, X509_ASN_ENCODING, szOID_RSA_RC2CBC, CRYPT_GET_INSTALLED_OID_FUNC_FLAG, (void **) &pfnDefaultImportEncryptKey, &hFuncAddr)) CryptFreeOIDFunctionAddress(hFuncAddr, 0); #if 0 if (!CryptInstallOIDFunctionAddress( hInst, X509_ASN_ENCODING, CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC, IMPORT_ENCRYPT_KEY_FUNC_COUNT, ImportEncryptKeyFuncTable, CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags )) goto ErrorReturn; #endif // Get the default gen and export encrypt key functions which we will // call if pvEncryptionAuxInfo points to a // CMSG_SP3_COMPATIBLE_AUX_INFO data structure. if (CryptGetOIDFunctionAddress( hGenEncryptKeyFuncSet, X509_ASN_ENCODING, szOID_RSA_RC2CBC, CRYPT_GET_INSTALLED_OID_FUNC_FLAG, (void **) &pfnDefaultGenEncryptKey, &hFuncAddr)) CryptFreeOIDFunctionAddress(hFuncAddr, 0); if (CryptGetOIDFunctionAddress( hExportEncryptKeyFuncSet, X509_ASN_ENCODING, szOID_RSA_RSA, CRYPT_GET_INSTALLED_OID_FUNC_FLAG, (void **) &pfnDefaultExportEncryptKey, &hFuncAddr)) CryptFreeOIDFunctionAddress(hFuncAddr, 0); #if 0 if (!CryptInstallOIDFunctionAddress( hInst, X509_ASN_ENCODING, CMSG_OID_GEN_ENCRYPT_KEY_FUNC, GEN_ENCRYPT_KEY_FUNC_COUNT, GenEncryptKeyFuncTable, CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags )) goto ErrorReturn; if (!CryptInstallOIDFunctionAddress( hInst, X509_ASN_ENCODING, CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC, EXPORT_ENCRYPT_KEY_FUNC_COUNT, ExportEncryptKeyFuncTable, CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags )) goto ErrorReturn; #endif // Allocate TLS which contains a pointer of ((void *) 0x1) for SP3 // compatible encryption. This pointer will be passed from // SP3GenEncryptKey() to SP3ExportEncryptKey(). // // If not SP3 encryption, the pointer is NULL. if ((iSP3TLS = TlsAlloc()) == 0xFFFFFFFF) goto ErrorReturn; break; case DLL_PROCESS_DETACH: if (iSP3TLS != 0xFFFFFFFF) { TlsFree(iSP3TLS); iSP3TLS = 0xFFFFFFFF; } break; case DLL_THREAD_DETACH: default: break; } fResult = TRUE; CommonReturn: return fResult; ErrorReturn: fResult = FALSE; goto CommonReturn; } //+------------------------------------------------------------------------- // SP3 import of the encryption key. // // The SP3 version of crypt32.dll didn't include any parameters for the // encryption algorithm. Later versions of crypt32.dll do. Therefore, we only // need to attempt to import the key without byte reversal if there aren't // any parameters present. //-------------------------------------------------------------------------- BOOL WINAPI SP3ImportEncryptKey( IN HCRYPTPROV hCryptProv, IN DWORD dwKeySpec, IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt, IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey, IN PBYTE pbEncodedKey, IN DWORD cbEncodedKey, OUT HCRYPTKEY *phEncryptKey ) { BOOL fResult; HCRYPTKEY hEncryptKey = 0; HCRYPTKEY hUserKey = 0; DWORD dwAlgIdEncrypt; DWORD dwAlgIdPubKey; PBYTE pbCspKey = NULL; DWORD cbCspKey; PUBLICKEYSTRUC *ppks; PSIMPLEBLOBHEADER psbh; PCCRYPT_OID_INFO pOIDInfo; // Check if more than just the NULL parameters if (2 < paiEncrypt->Parameters.cbData) { fResult = FALSE; goto DefaultImport; } // Map the ASN algorithm identifier to the CSP ALG_ID. if (NULL == (pOIDInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, paiEncrypt->pszObjId, CRYPT_ENCRYPT_ALG_OID_GROUP_ID))) goto GetEncryptAlgidError; dwAlgIdEncrypt = pOIDInfo->Algid; // Create the CSP encrypted symmetric key structure WITHOUT BYTE REVERSAL. dwAlgIdPubKey = CALG_RSA_KEYX; cbCspKey = cbEncodedKey + sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER); if (NULL == (pbCspKey = (PBYTE)SP3Alloc( cbCspKey))) goto OutOfMemory; ppks = (PUBLICKEYSTRUC *)pbCspKey; ppks->bType = SIMPLEBLOB; ppks->bVersion = CUR_BLOB_VERSION; ppks->reserved = 0; ppks->aiKeyAlg = dwAlgIdEncrypt; psbh = (PSIMPLEBLOBHEADER)(ppks + 1); psbh->aiEncAlg = dwAlgIdPubKey; // NO BYTE REVERSAL as done in SP3. memcpy( (PBYTE)(psbh+1), pbEncodedKey, cbEncodedKey); if (0 != dwKeySpec) { // Get private key to use. if (!CryptGetUserKey( hCryptProv, dwKeySpec, &hUserKey)) { hUserKey = 0; goto GetUserKeyFailed; } } // Try importing as an NT4.0 SP3 encypted key that wasn't byte // reversed and with zero salt. fResult = CryptImportKey( hCryptProv, pbCspKey, cbCspKey, hUserKey, 0, // dwFlags &hEncryptKey); if (!fResult && hUserKey) { // Try without using the specified user key. fResult = CryptImportKey( hCryptProv, pbCspKey, cbCspKey, 0, // hUserKey 0, // dwFlags &hEncryptKey); } if (!fResult) goto ImportKeyFailed; fResult = TRUE; CommonReturn: if (pbCspKey) SP3Free(pbCspKey); if (hUserKey) { DWORD dwError = GetLastError(); CryptDestroyKey(hUserKey); SetLastError(dwError); } DefaultImport: if (!fResult && pfnDefaultImportEncryptKey) // Try importing using the default return pfnDefaultImportEncryptKey( hCryptProv, dwKeySpec, paiEncrypt, paiPubKey, pbEncodedKey, cbEncodedKey, phEncryptKey); else { *phEncryptKey = hEncryptKey; return fResult; } GetEncryptAlgidError: OutOfMemory: GetUserKeyFailed: ImportKeyFailed: hEncryptKey = 0; fResult = FALSE; goto CommonReturn; } //+------------------------------------------------------------------------- // SP3 generation of the encryption key. // // The SP3 version of crypt32.dll didn't include the IV octet string for the // encryption algorithm. Also, the encryption key had zero salt instead // of no salt. // // For SP3 compatible generation, the caller must pass in a non-NULL // hCryptProv and set pvEncryptAuxInfo to point to a // CMSG_SP3_COMPATIBLE_AUX_INFO data structure with the // CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG set. //-------------------------------------------------------------------------- BOOL WINAPI SP3GenEncryptKey( IN OUT HCRYPTPROV *phCryptProv, IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt, IN PVOID pvEncryptAuxInfo, IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo, IN PFN_CMSG_ALLOC pfnAlloc, OUT HCRYPTKEY *phEncryptKey, OUT PBYTE *ppbEncryptParameters, OUT PDWORD pcbEncryptParameters ) { HCRYPTPROV hCryptProv; PCMSG_SP3_COMPATIBLE_AUX_INFO pSP3AuxInfo = (PCMSG_SP3_COMPATIBLE_AUX_INFO) pvEncryptAuxInfo; PCCRYPT_OID_INFO pOIDInfo; DWORD dwAlgIdEncrypt; hCryptProv = *phCryptProv; if (0 == hCryptProv || NULL == pSP3AuxInfo || sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO) > pSP3AuxInfo->cbSize || 0 == (pSP3AuxInfo->dwFlags & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG)) { // Let SP3ExportEncryptKey() know this will be a default export TlsSetValue(iSP3TLS, NULL); if (pfnDefaultGenEncryptKey) // Generate using the default return pfnDefaultGenEncryptKey( phCryptProv, paiEncrypt, pvEncryptAuxInfo, pPublicKeyInfo, pfnAlloc, phEncryptKey, ppbEncryptParameters, pcbEncryptParameters ); else { // We don't have a default *phEncryptKey = 0; SetLastError((DWORD) E_UNEXPECTED); return FALSE; } } // Let SP3ExportEncryptKey() know this will be a SP3 compatible export. TlsSetValue(iSP3TLS, SP3_TLS_POINTER); // Map the ASN algorithm identifier to the CSP ALG_ID. if (NULL == (pOIDInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY, paiEncrypt->pszObjId, CRYPT_ENCRYPT_ALG_OID_GROUP_ID))) { *phEncryptKey = 0; return FALSE; } dwAlgIdEncrypt = pOIDInfo->Algid; // Since CRYPT_NO_SALT flag isn't set, uses zero salt if (!CryptGenKey( hCryptProv, dwAlgIdEncrypt, CRYPT_EXPORTABLE, phEncryptKey)) { *phEncryptKey = 0; return FALSE; } return TRUE; } //+------------------------------------------------------------------------- // SP3 export of the encryption key. // // The SP3 version of crypt32.dll encoded the encrypted symmetric key as // little endian instead of as big endian. //-------------------------------------------------------------------------- BOOL WINAPI SP3ExportEncryptKey( IN HCRYPTPROV hCryptProv, IN HCRYPTKEY hEncryptKey, IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo, OUT PBYTE pbData, IN OUT PDWORD pcbData ) { BOOL fResult; DWORD dwError = ERROR_SUCCESS; HCRYPTKEY hPubKey = NULL; PBYTE pb = NULL; DWORD cb; if (SP3_TLS_POINTER != TlsGetValue(iSP3TLS)) { if (pfnDefaultExportEncryptKey) // Export using the default function return pfnDefaultExportEncryptKey( hCryptProv, hEncryptKey, pPublicKeyInfo, pbData, pcbData ); else { // We don't have a default *pcbData = 0; SetLastError((DWORD) E_UNEXPECTED); return FALSE; } } // SP3 compatible export and encode if (!CryptImportPublicKeyInfo( hCryptProv, X509_ASN_ENCODING, pPublicKeyInfo, &hPubKey)) goto ImportKeyError; if (!CryptExportKey( hEncryptKey, hPubKey, SIMPLEBLOB, 0, // dwFlags NULL, &cb)) goto ExportKeySizeError; if (NULL == (pb = (PBYTE) SP3Alloc(cb))) goto ExportKeyAllocError; if (!CryptExportKey( hEncryptKey, hPubKey, SIMPLEBLOB, 0, // dwFlags pb, &cb)) goto ExportKeyError; cb -= sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER); fResult = TRUE; if (pbData) { if (*pcbData < cb) { SetLastError((DWORD) ERROR_MORE_DATA); fResult = FALSE; } else if (0 < cb) { // Don't byte reverse memcpy(pbData, pb + (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)), cb); } } CommonReturn: *pcbData = cb; if (pb) SP3Free(pb); if (hPubKey) CryptDestroyKey(hPubKey); SetLastError(dwError); return fResult; ImportKeyError: ExportKeySizeError: ExportKeyAllocError: ExportKeyError: dwError = GetLastError(); cb = 0; fResult = FALSE; goto CommonReturn; } #ifdef CMS_PKCS7 BOOL WINAPI CryptMsgDllGenContentEncryptKey( IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo, IN DWORD dwFlags, IN OPTIONAL void *pvReserved ) { BOOL fResult; HCRYPTOIDFUNCSET hGenContentFuncSet; HCRYPTOIDFUNCADDR hFuncAddr; PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY pfnDefaultGenContent; if (NULL == (hGenContentFuncSet = CryptInitOIDFunctionSet( CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC, 0))) return FALSE; // Get the default gen content encrypt key function which we will call if (!CryptGetOIDFunctionAddress( hGenContentFuncSet, X509_ASN_ENCODING, CMSG_DEFAULT_INSTALLABLE_FUNC_OID, CRYPT_GET_INSTALLED_OID_FUNC_FLAG, (void **) &pfnDefaultGenContent, &hFuncAddr)) return FALSE; fResult = pfnDefaultGenContent( pContentEncryptInfo, dwFlags, pvReserved ); CryptFreeOIDFunctionAddress(hFuncAddr, 0); return fResult; } BOOL WINAPI CryptMsgDllExportKeyTrans( IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo, IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo, IN OUT PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo, IN DWORD dwFlags, IN OPTIONAL void *pvReserved ) { BOOL fResult; HCRYPTOIDFUNCSET hExportKeyTransFuncSet; HCRYPTOIDFUNCADDR hFuncAddr; PFN_CMSG_EXPORT_KEY_TRANS pfnDefaultExportKeyTrans; if (NULL == (hExportKeyTransFuncSet = CryptInitOIDFunctionSet( CMSG_OID_EXPORT_KEY_TRANS_FUNC, 0))) return FALSE; // Get the default export key trans function which we will call if (!CryptGetOIDFunctionAddress( hExportKeyTransFuncSet, X509_ASN_ENCODING, CMSG_DEFAULT_INSTALLABLE_FUNC_OID, CRYPT_GET_INSTALLED_OID_FUNC_FLAG, (void **) &pfnDefaultExportKeyTrans, &hFuncAddr)) return FALSE; fResult = pfnDefaultExportKeyTrans( pContentEncryptInfo, pKeyTransEncodeInfo, pKeyTransEncryptInfo, dwFlags, pvReserved ); CryptFreeOIDFunctionAddress(hFuncAddr, 0); return fResult; } BOOL WINAPI CryptMsgDllImportKeyTrans( IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm, IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara, IN DWORD dwFlags, IN OPTIONAL void *pvReserved, OUT HCRYPTKEY *phContentEncryptKey ) { BOOL fResult; HCRYPTOIDFUNCSET hImportKeyTransFuncSet; HCRYPTOIDFUNCADDR hFuncAddr; PFN_CMSG_IMPORT_KEY_TRANS pfnDefaultImportKeyTrans; if (NULL == (hImportKeyTransFuncSet = CryptInitOIDFunctionSet( CMSG_OID_IMPORT_KEY_TRANS_FUNC, 0))) return FALSE; // Get the default import key trans function which we will call if (!CryptGetOIDFunctionAddress( hImportKeyTransFuncSet, X509_ASN_ENCODING, CMSG_DEFAULT_INSTALLABLE_FUNC_OID, CRYPT_GET_INSTALLED_OID_FUNC_FLAG, (void **) &pfnDefaultImportKeyTrans, &hFuncAddr)) return FALSE; fResult = pfnDefaultImportKeyTrans( pContentEncryptionAlgorithm, pKeyTransDecryptPara, dwFlags, pvReserved, phContentEncryptKey ); CryptFreeOIDFunctionAddress(hFuncAddr, 0); return fResult; } BOOL WINAPI NotImplCryptMsgDllImportKeyTrans( IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm, IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara, IN DWORD dwFlags, IN OPTIONAL void *pvReserved, OUT HCRYPTKEY *phContentEncryptKey ) { SetLastError((DWORD) E_NOTIMPL); return FALSE; } #endif // CMS_PKCS7