Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1017 lines
31 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: sp3crmsg.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //+-------------------------------------------------------------------------
  11. // File: sp3crmsg.cpp
  12. //
  13. // Contents: Installable OID functions providing backwards compatiblity
  14. // with the way the NT4.0 SP3 and IE 3.02 versions of crypt32.dll
  15. // encrypted the symmetric key in a PKCS #7 EnvelopedData message.
  16. //
  17. // The SP3 version of crypt32.dll failed to byte reverse the
  18. // encrypted symmetric key. It also added zero salt instead
  19. // of no salt.
  20. //
  21. // Functions: DllMain
  22. // DllRegisterServer
  23. // DllUnregisterServer
  24. // SP3ImportEncryptKey
  25. // SP3GenEncryptKey
  26. // SP3ExportEncryptKey
  27. #ifdef CMS_PKCS7
  28. // DllInstall
  29. // CryptMsgDllGenContentEncryptKey
  30. // CryptMsgDllExportKeyTrans
  31. // CryptMsgDllImportKeyTrans
  32. // NotImplCryptMsgDllImportKeyTrans
  33. #endif // CMS_PKCS7
  34. //--------------------------------------------------------------------------
  35. #define CMS_PKCS7 1
  36. #include <windows.h>
  37. #include <wincrypt.h>
  38. #include "sp3crmsg.h"
  39. // memory management
  40. #define SP3Alloc(cb) ((void*)LocalAlloc(LPTR, cb))
  41. #define SP3Free(pv) (LocalFree((HLOCAL)pv))
  42. // The Thread Local Storage (TLS) referenced by iSP3TLS has pointer of
  43. // ((void *) 0x1) if SP3 compatible encryption is enabled. Otherwise, its 0.
  44. static DWORD iSP3TLS = 0xFFFFFFFF;
  45. #define SP3_TLS_POINTER ((void *) 0x1)
  46. typedef struct _SIMPLEBLOBHEADER {
  47. ALG_ID aiEncAlg;
  48. } SIMPLEBLOBHEADER, *PSIMPLEBLOBHEADER;
  49. typedef struct _OID_REG_ENTRY {
  50. LPCSTR pszOID;
  51. LPCSTR pszOverrideFuncName;
  52. } OID_REG_ENTRY, *POID_REG_ENTRY;
  53. //+-------------------------------------------------------------------------
  54. // ImportEncryptKey OID Installable Functions
  55. //--------------------------------------------------------------------------
  56. static HCRYPTOIDFUNCSET hImportEncryptKeyFuncSet;
  57. static PFN_CMSG_IMPORT_ENCRYPT_KEY pfnDefaultImportEncryptKey = NULL;
  58. BOOL
  59. WINAPI
  60. SP3ImportEncryptKey(
  61. IN HCRYPTPROV hCryptProv,
  62. IN DWORD dwKeySpec,
  63. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  64. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  65. IN PBYTE pbEncodedKey,
  66. IN DWORD cbEncodedKey,
  67. OUT HCRYPTKEY *phEncryptKey);
  68. static const CRYPT_OID_FUNC_ENTRY ImportEncryptKeyFuncTable[] = {
  69. szOID_OIWSEC_desCBC, SP3ImportEncryptKey,
  70. szOID_RSA_RC2CBC, SP3ImportEncryptKey,
  71. szOID_RSA_RC4, SP3ImportEncryptKey
  72. };
  73. #define IMPORT_ENCRYPT_KEY_FUNC_COUNT (sizeof(ImportEncryptKeyFuncTable) / \
  74. sizeof(ImportEncryptKeyFuncTable[0]))
  75. static const OID_REG_ENTRY ImportEncryptKeyRegTable[] = {
  76. szOID_OIWSEC_desCBC, "SP3ImportEncryptKey",
  77. szOID_RSA_RC2CBC, "SP3ImportEncryptKey",
  78. szOID_RSA_RC4, "SP3ImportEncryptKey"
  79. };
  80. #define IMPORT_ENCRYPT_KEY_REG_COUNT (sizeof(ImportEncryptKeyRegTable) / \
  81. sizeof(ImportEncryptKeyRegTable[0]))
  82. //+-------------------------------------------------------------------------
  83. // GenEncryptKey OID Installable Functions
  84. //--------------------------------------------------------------------------
  85. static HCRYPTOIDFUNCSET hGenEncryptKeyFuncSet;
  86. static PFN_CMSG_GEN_ENCRYPT_KEY pfnDefaultGenEncryptKey = NULL;
  87. BOOL
  88. WINAPI
  89. SP3GenEncryptKey(
  90. IN OUT HCRYPTPROV *phCryptProv,
  91. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  92. IN PVOID pvEncryptAuxInfo,
  93. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  94. IN PFN_CMSG_ALLOC pfnAlloc,
  95. OUT HCRYPTKEY *phEncryptKey,
  96. OUT PBYTE *ppbEncryptParameters,
  97. OUT PDWORD pcbEncryptParameters);
  98. static const CRYPT_OID_FUNC_ENTRY GenEncryptKeyFuncTable[] = {
  99. szOID_OIWSEC_desCBC, SP3GenEncryptKey,
  100. szOID_RSA_RC2CBC, SP3GenEncryptKey,
  101. szOID_RSA_RC4, SP3GenEncryptKey
  102. };
  103. #define GEN_ENCRYPT_KEY_FUNC_COUNT (sizeof(GenEncryptKeyFuncTable) / \
  104. sizeof(GenEncryptKeyFuncTable[0]))
  105. static const OID_REG_ENTRY GenEncryptKeyRegTable[] = {
  106. szOID_OIWSEC_desCBC, "SP3GenEncryptKey",
  107. szOID_RSA_RC2CBC, "SP3GenEncryptKey",
  108. szOID_RSA_RC4, "SP3GenEncryptKey"
  109. };
  110. #define GEN_ENCRYPT_KEY_REG_COUNT (sizeof(GenEncryptKeyRegTable) / \
  111. sizeof(GenEncryptKeyRegTable[0]))
  112. //+-------------------------------------------------------------------------
  113. // ExportEncryptKey OID Installable Functions
  114. //--------------------------------------------------------------------------
  115. static HCRYPTOIDFUNCSET hExportEncryptKeyFuncSet;
  116. static PFN_CMSG_EXPORT_ENCRYPT_KEY pfnDefaultExportEncryptKey = NULL;
  117. BOOL
  118. WINAPI
  119. SP3ExportEncryptKey(
  120. IN HCRYPTPROV hCryptProv,
  121. IN HCRYPTKEY hEncryptKey,
  122. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  123. OUT PBYTE pbData,
  124. IN OUT PDWORD pcbData);
  125. static const CRYPT_OID_FUNC_ENTRY ExportEncryptKeyFuncTable[] = {
  126. szOID_RSA_RSA, SP3ExportEncryptKey
  127. };
  128. #define EXPORT_ENCRYPT_KEY_FUNC_COUNT (sizeof(ExportEncryptKeyFuncTable) / \
  129. sizeof(ExportEncryptKeyFuncTable[0]))
  130. static const OID_REG_ENTRY ExportEncryptKeyRegTable[] = {
  131. szOID_RSA_RSA, "SP3ExportEncryptKey"
  132. };
  133. #define EXPORT_ENCRYPT_KEY_REG_COUNT (sizeof(ExportEncryptKeyRegTable) / \
  134. sizeof(ExportEncryptKeyRegTable[0]))
  135. static char szCrypt32[]="crypt32.dll";
  136. // First post IE4.0 versions of crypt32.dll start with "5.101.1681.1"
  137. static DWORD dwLowVersion = (1681 << 16) | 1;
  138. static DWORD dwHighVersion = (5 << 16) | 101;
  139. static BOOL IsPostIE4Crypt32()
  140. {
  141. BOOL fPostIE4 = FALSE; // default to IE4
  142. DWORD dwHandle = 0;
  143. DWORD cbInfo;
  144. void *pvInfo = NULL;
  145. VS_FIXEDFILEINFO *pFixedFileInfo = NULL; // not allocated
  146. UINT ccFixedFileInfo = 0;
  147. if (0 == (cbInfo = GetFileVersionInfoSizeA(szCrypt32, &dwHandle)))
  148. goto ErrorReturn;
  149. if (NULL == (pvInfo = SP3Alloc(cbInfo)))
  150. goto ErrorReturn;
  151. if (!GetFileVersionInfoA(
  152. szCrypt32,
  153. 0, // dwHandle, ignored
  154. cbInfo,
  155. pvInfo
  156. ))
  157. goto ErrorReturn;
  158. if (!VerQueryValueA(
  159. pvInfo,
  160. "\\", // VS_FIXEDFILEINFO
  161. (void **) &pFixedFileInfo,
  162. &ccFixedFileInfo
  163. ))
  164. goto ErrorReturn;
  165. if (pFixedFileInfo->dwFileVersionMS > dwHighVersion ||
  166. (pFixedFileInfo->dwFileVersionMS == dwHighVersion &&
  167. pFixedFileInfo->dwFileVersionLS >= dwLowVersion))
  168. fPostIE4 = TRUE;
  169. CommonReturn:
  170. if (pvInfo)
  171. SP3Free(pvInfo);
  172. return fPostIE4;
  173. ErrorReturn:
  174. goto CommonReturn;
  175. }
  176. static HRESULT HError()
  177. {
  178. DWORD dw = GetLastError();
  179. HRESULT hr;
  180. if ( dw <= 0xFFFF )
  181. hr = HRESULT_FROM_WIN32 ( dw );
  182. else
  183. hr = dw;
  184. if ( ! FAILED ( hr ) )
  185. {
  186. // somebody failed a call without properly setting an error condition
  187. hr = E_UNEXPECTED;
  188. }
  189. return hr;
  190. }
  191. STDAPI DllRegisterServer(void)
  192. {
  193. int i;
  194. DWORD dwFlags = CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG;
  195. for (i = 0; i < IMPORT_ENCRYPT_KEY_REG_COUNT; i++) {
  196. if (!CryptRegisterOIDFunction(
  197. X509_ASN_ENCODING,
  198. CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
  199. ImportEncryptKeyRegTable[i].pszOID,
  200. L"sp3crmsg.dll",
  201. ImportEncryptKeyRegTable[i].pszOverrideFuncName
  202. ))
  203. return HError();
  204. if (!CryptSetOIDFunctionValue(
  205. X509_ASN_ENCODING,
  206. CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
  207. ImportEncryptKeyRegTable[i].pszOID,
  208. CRYPT_OID_REG_FLAGS_VALUE_NAME,
  209. REG_DWORD,
  210. (BYTE *) &dwFlags,
  211. sizeof(dwFlags)
  212. ))
  213. return HError();
  214. }
  215. for (i = 0; i < GEN_ENCRYPT_KEY_REG_COUNT; i++) {
  216. if (!CryptRegisterOIDFunction(
  217. X509_ASN_ENCODING,
  218. CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
  219. GenEncryptKeyRegTable[i].pszOID,
  220. L"sp3crmsg.dll",
  221. GenEncryptKeyRegTable[i].pszOverrideFuncName
  222. ))
  223. return HError();
  224. if (!CryptSetOIDFunctionValue(
  225. X509_ASN_ENCODING,
  226. CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
  227. GenEncryptKeyRegTable[i].pszOID,
  228. CRYPT_OID_REG_FLAGS_VALUE_NAME,
  229. REG_DWORD,
  230. (BYTE *) &dwFlags,
  231. sizeof(dwFlags)
  232. ))
  233. return HError();
  234. }
  235. for (i = 0; i < EXPORT_ENCRYPT_KEY_REG_COUNT; i++) {
  236. if (!CryptRegisterOIDFunction(
  237. X509_ASN_ENCODING,
  238. CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
  239. ExportEncryptKeyRegTable[i].pszOID,
  240. L"sp3crmsg.dll",
  241. ExportEncryptKeyRegTable[i].pszOverrideFuncName
  242. ))
  243. return HError();
  244. if (!CryptSetOIDFunctionValue(
  245. X509_ASN_ENCODING,
  246. CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
  247. ExportEncryptKeyRegTable[i].pszOID,
  248. CRYPT_OID_REG_FLAGS_VALUE_NAME,
  249. REG_DWORD,
  250. (BYTE *) &dwFlags,
  251. sizeof(dwFlags)
  252. ))
  253. return HError();
  254. }
  255. return S_OK;
  256. }
  257. STDAPI DllUnregisterServer(void)
  258. {
  259. HRESULT hr = S_OK;
  260. int i;
  261. for (i = 0; i < IMPORT_ENCRYPT_KEY_REG_COUNT; i++) {
  262. if (!CryptUnregisterOIDFunction(
  263. X509_ASN_ENCODING,
  264. CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
  265. ImportEncryptKeyRegTable[i].pszOID
  266. )) {
  267. if (ERROR_FILE_NOT_FOUND != GetLastError())
  268. hr = HError();
  269. }
  270. }
  271. for (i = 0; i < GEN_ENCRYPT_KEY_REG_COUNT; i++) {
  272. if (!CryptUnregisterOIDFunction(
  273. X509_ASN_ENCODING,
  274. CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
  275. GenEncryptKeyRegTable[i].pszOID
  276. )) {
  277. if (ERROR_FILE_NOT_FOUND != GetLastError())
  278. hr = HError();
  279. }
  280. }
  281. for (i = 0; i < EXPORT_ENCRYPT_KEY_REG_COUNT; i++) {
  282. if (!CryptUnregisterOIDFunction(
  283. X509_ASN_ENCODING,
  284. CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
  285. ExportEncryptKeyRegTable[i].pszOID
  286. )) {
  287. if (ERROR_FILE_NOT_FOUND != GetLastError())
  288. hr = HError();
  289. }
  290. }
  291. #ifdef CMS_PKCS7
  292. if (!CryptUnregisterOIDFunction(
  293. X509_ASN_ENCODING,
  294. CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC,
  295. szOID_RSA_RC2CBC
  296. )) {
  297. if (ERROR_FILE_NOT_FOUND != GetLastError())
  298. hr = HError();
  299. }
  300. if (!CryptUnregisterOIDFunction(
  301. X509_ASN_ENCODING,
  302. CMSG_OID_EXPORT_KEY_TRANS_FUNC,
  303. szOID_RSA_RSA
  304. )) {
  305. if (ERROR_FILE_NOT_FOUND != GetLastError())
  306. hr = HError();
  307. }
  308. if (!CryptUnregisterOIDFunction(
  309. X509_ASN_ENCODING,
  310. CMSG_OID_IMPORT_KEY_TRANS_FUNC,
  311. szOID_RSA_RSA "!" szOID_RSA_RC2CBC
  312. )) {
  313. if (ERROR_FILE_NOT_FOUND != GetLastError())
  314. hr = HError();
  315. }
  316. if (!CryptUnregisterOIDFunction(
  317. X509_ASN_ENCODING,
  318. CMSG_OID_IMPORT_KEY_TRANS_FUNC,
  319. szOID_RSA_RC2CBC
  320. )) {
  321. if (ERROR_FILE_NOT_FOUND != GetLastError())
  322. hr = HError();
  323. }
  324. #endif // CMS_PKCS7
  325. return hr;
  326. }
  327. #ifdef CMS_PKCS7
  328. //+---------------------------------------------------------------------------
  329. //
  330. // Function: DllInstall
  331. //
  332. // Synopsis: dll installation entry point
  333. //
  334. //----------------------------------------------------------------------------
  335. STDAPI DllInstall (BOOL fRegister, LPCSTR pszCommand)
  336. {
  337. if (!fRegister)
  338. return DllUnregisterServer();
  339. if (!CryptRegisterOIDFunction(
  340. X509_ASN_ENCODING,
  341. CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC,
  342. szOID_RSA_RC2CBC,
  343. L"sp3crmsg.dll",
  344. NULL // pszOverrideFuncName
  345. ))
  346. return HError();
  347. if (!CryptRegisterOIDFunction(
  348. X509_ASN_ENCODING,
  349. CMSG_OID_EXPORT_KEY_TRANS_FUNC,
  350. szOID_RSA_RSA,
  351. L"sp3crmsg.dll",
  352. NULL // pszOverrideFuncName
  353. ))
  354. return HError();
  355. if (!CryptRegisterOIDFunction(
  356. X509_ASN_ENCODING,
  357. CMSG_OID_IMPORT_KEY_TRANS_FUNC,
  358. szOID_RSA_RSA "!" szOID_RSA_RC2CBC,
  359. L"sp3crmsg.dll",
  360. "NotImplCryptMsgDllImportKeyTrans"
  361. ))
  362. return HError();
  363. if (!CryptRegisterOIDFunction(
  364. X509_ASN_ENCODING,
  365. CMSG_OID_IMPORT_KEY_TRANS_FUNC,
  366. szOID_RSA_RC2CBC,
  367. L"sp3crmsg.dll",
  368. NULL // pszOverrideFuncName
  369. ))
  370. return HError();
  371. return S_OK;
  372. }
  373. #endif // CMS_PKCS7
  374. //+-------------------------------------------------------------------------
  375. // Function: DllMain
  376. //
  377. // Synopsis: Process/Thread attach/detach
  378. //
  379. // At process attach install the SP3 compatible version of
  380. // CryptMsgDllImportEncryptKey, CryptMsgDllGenEncryptKey and
  381. // CryptMsgDllExportEncryptKey.
  382. //--------------------------------------------------------------------------
  383. BOOL
  384. WINAPI
  385. DllMain(
  386. HMODULE hInst,
  387. ULONG ulReason,
  388. LPVOID lpReserved)
  389. {
  390. BOOL fResult;
  391. HCRYPTOIDFUNCADDR hFuncAddr;
  392. switch (ulReason) {
  393. case DLL_PROCESS_ATTACH:
  394. #if 0
  395. // Post IE 4.0 releases of crypt32.dll already have the SP3
  396. // backwards compatible fix.
  397. if (IsPostIE4Crypt32())
  398. return TRUE;
  399. #endif
  400. if (NULL == (hImportEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  401. CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
  402. 0)))
  403. goto ErrorReturn;
  404. if (NULL == (hGenEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  405. CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
  406. 0)))
  407. goto ErrorReturn;
  408. if (NULL == (hExportEncryptKeyFuncSet = CryptInitOIDFunctionSet(
  409. CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
  410. 0)))
  411. goto ErrorReturn;
  412. // Get the default import encrypt key function which we will call if
  413. // unable to do a successful import without byte reversing the
  414. // encrypted symmetric key.
  415. if (CryptGetOIDFunctionAddress(
  416. hImportEncryptKeyFuncSet,
  417. X509_ASN_ENCODING,
  418. szOID_RSA_RC2CBC,
  419. CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
  420. (void **) &pfnDefaultImportEncryptKey,
  421. &hFuncAddr))
  422. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  423. #if 0
  424. if (!CryptInstallOIDFunctionAddress(
  425. hInst,
  426. X509_ASN_ENCODING,
  427. CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC,
  428. IMPORT_ENCRYPT_KEY_FUNC_COUNT,
  429. ImportEncryptKeyFuncTable,
  430. CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags
  431. ))
  432. goto ErrorReturn;
  433. #endif
  434. // Get the default gen and export encrypt key functions which we will
  435. // call if pvEncryptionAuxInfo points to a
  436. // CMSG_SP3_COMPATIBLE_AUX_INFO data structure.
  437. if (CryptGetOIDFunctionAddress(
  438. hGenEncryptKeyFuncSet,
  439. X509_ASN_ENCODING,
  440. szOID_RSA_RC2CBC,
  441. CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
  442. (void **) &pfnDefaultGenEncryptKey,
  443. &hFuncAddr))
  444. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  445. if (CryptGetOIDFunctionAddress(
  446. hExportEncryptKeyFuncSet,
  447. X509_ASN_ENCODING,
  448. szOID_RSA_RSA,
  449. CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
  450. (void **) &pfnDefaultExportEncryptKey,
  451. &hFuncAddr))
  452. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  453. #if 0
  454. if (!CryptInstallOIDFunctionAddress(
  455. hInst,
  456. X509_ASN_ENCODING,
  457. CMSG_OID_GEN_ENCRYPT_KEY_FUNC,
  458. GEN_ENCRYPT_KEY_FUNC_COUNT,
  459. GenEncryptKeyFuncTable,
  460. CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags
  461. ))
  462. goto ErrorReturn;
  463. if (!CryptInstallOIDFunctionAddress(
  464. hInst,
  465. X509_ASN_ENCODING,
  466. CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC,
  467. EXPORT_ENCRYPT_KEY_FUNC_COUNT,
  468. ExportEncryptKeyFuncTable,
  469. CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG // dwFlags
  470. ))
  471. goto ErrorReturn;
  472. #endif
  473. // Allocate TLS which contains a pointer of ((void *) 0x1) for SP3
  474. // compatible encryption. This pointer will be passed from
  475. // SP3GenEncryptKey() to SP3ExportEncryptKey().
  476. //
  477. // If not SP3 encryption, the pointer is NULL.
  478. if ((iSP3TLS = TlsAlloc()) == 0xFFFFFFFF)
  479. goto ErrorReturn;
  480. break;
  481. case DLL_PROCESS_DETACH:
  482. if (iSP3TLS != 0xFFFFFFFF) {
  483. TlsFree(iSP3TLS);
  484. iSP3TLS = 0xFFFFFFFF;
  485. }
  486. break;
  487. case DLL_THREAD_DETACH:
  488. default:
  489. break;
  490. }
  491. fResult = TRUE;
  492. CommonReturn:
  493. return fResult;
  494. ErrorReturn:
  495. fResult = FALSE;
  496. goto CommonReturn;
  497. }
  498. //+-------------------------------------------------------------------------
  499. // SP3 import of the encryption key.
  500. //
  501. // The SP3 version of crypt32.dll didn't include any parameters for the
  502. // encryption algorithm. Later versions of crypt32.dll do. Therefore, we only
  503. // need to attempt to import the key without byte reversal if there aren't
  504. // any parameters present.
  505. //--------------------------------------------------------------------------
  506. BOOL
  507. WINAPI
  508. SP3ImportEncryptKey(
  509. IN HCRYPTPROV hCryptProv,
  510. IN DWORD dwKeySpec,
  511. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  512. IN PCRYPT_ALGORITHM_IDENTIFIER paiPubKey,
  513. IN PBYTE pbEncodedKey,
  514. IN DWORD cbEncodedKey,
  515. OUT HCRYPTKEY *phEncryptKey
  516. )
  517. {
  518. BOOL fResult;
  519. HCRYPTKEY hEncryptKey = 0;
  520. HCRYPTKEY hUserKey = 0;
  521. DWORD dwAlgIdEncrypt;
  522. DWORD dwAlgIdPubKey;
  523. PBYTE pbCspKey = NULL;
  524. DWORD cbCspKey;
  525. PUBLICKEYSTRUC *ppks;
  526. PSIMPLEBLOBHEADER psbh;
  527. PCCRYPT_OID_INFO pOIDInfo;
  528. // Check if more than just the NULL parameters
  529. if (2 < paiEncrypt->Parameters.cbData) {
  530. fResult = FALSE;
  531. goto DefaultImport;
  532. }
  533. // Map the ASN algorithm identifier to the CSP ALG_ID.
  534. if (NULL == (pOIDInfo = CryptFindOIDInfo(
  535. CRYPT_OID_INFO_OID_KEY,
  536. paiEncrypt->pszObjId,
  537. CRYPT_ENCRYPT_ALG_OID_GROUP_ID)))
  538. goto GetEncryptAlgidError;
  539. dwAlgIdEncrypt = pOIDInfo->Algid;
  540. // Create the CSP encrypted symmetric key structure WITHOUT BYTE REVERSAL.
  541. dwAlgIdPubKey = CALG_RSA_KEYX;
  542. cbCspKey = cbEncodedKey + sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER);
  543. if (NULL == (pbCspKey = (PBYTE)SP3Alloc( cbCspKey)))
  544. goto OutOfMemory;
  545. ppks = (PUBLICKEYSTRUC *)pbCspKey;
  546. ppks->bType = SIMPLEBLOB;
  547. ppks->bVersion = CUR_BLOB_VERSION;
  548. ppks->reserved = 0;
  549. ppks->aiKeyAlg = dwAlgIdEncrypt;
  550. psbh = (PSIMPLEBLOBHEADER)(ppks + 1);
  551. psbh->aiEncAlg = dwAlgIdPubKey;
  552. // NO BYTE REVERSAL as done in SP3.
  553. memcpy( (PBYTE)(psbh+1), pbEncodedKey, cbEncodedKey);
  554. if (0 != dwKeySpec) {
  555. // Get private key to use.
  556. if (!CryptGetUserKey(
  557. hCryptProv,
  558. dwKeySpec,
  559. &hUserKey)) {
  560. hUserKey = 0;
  561. goto GetUserKeyFailed;
  562. }
  563. }
  564. // Try importing as an NT4.0 SP3 encypted key that wasn't byte
  565. // reversed and with zero salt.
  566. fResult = CryptImportKey(
  567. hCryptProv,
  568. pbCspKey,
  569. cbCspKey,
  570. hUserKey,
  571. 0, // dwFlags
  572. &hEncryptKey);
  573. if (!fResult && hUserKey) {
  574. // Try without using the specified user key.
  575. fResult = CryptImportKey(
  576. hCryptProv,
  577. pbCspKey,
  578. cbCspKey,
  579. 0, // hUserKey
  580. 0, // dwFlags
  581. &hEncryptKey);
  582. }
  583. if (!fResult)
  584. goto ImportKeyFailed;
  585. fResult = TRUE;
  586. CommonReturn:
  587. if (pbCspKey)
  588. SP3Free(pbCspKey);
  589. if (hUserKey) {
  590. DWORD dwError = GetLastError();
  591. CryptDestroyKey(hUserKey);
  592. SetLastError(dwError);
  593. }
  594. DefaultImport:
  595. if (!fResult && pfnDefaultImportEncryptKey)
  596. // Try importing using the default
  597. return pfnDefaultImportEncryptKey(
  598. hCryptProv,
  599. dwKeySpec,
  600. paiEncrypt,
  601. paiPubKey,
  602. pbEncodedKey,
  603. cbEncodedKey,
  604. phEncryptKey);
  605. else {
  606. *phEncryptKey = hEncryptKey;
  607. return fResult;
  608. }
  609. GetEncryptAlgidError:
  610. OutOfMemory:
  611. GetUserKeyFailed:
  612. ImportKeyFailed:
  613. hEncryptKey = 0;
  614. fResult = FALSE;
  615. goto CommonReturn;
  616. }
  617. //+-------------------------------------------------------------------------
  618. // SP3 generation of the encryption key.
  619. //
  620. // The SP3 version of crypt32.dll didn't include the IV octet string for the
  621. // encryption algorithm. Also, the encryption key had zero salt instead
  622. // of no salt.
  623. //
  624. // For SP3 compatible generation, the caller must pass in a non-NULL
  625. // hCryptProv and set pvEncryptAuxInfo to point to a
  626. // CMSG_SP3_COMPATIBLE_AUX_INFO data structure with the
  627. // CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG set.
  628. //--------------------------------------------------------------------------
  629. BOOL
  630. WINAPI
  631. SP3GenEncryptKey(
  632. IN OUT HCRYPTPROV *phCryptProv,
  633. IN PCRYPT_ALGORITHM_IDENTIFIER paiEncrypt,
  634. IN PVOID pvEncryptAuxInfo,
  635. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  636. IN PFN_CMSG_ALLOC pfnAlloc,
  637. OUT HCRYPTKEY *phEncryptKey,
  638. OUT PBYTE *ppbEncryptParameters,
  639. OUT PDWORD pcbEncryptParameters
  640. )
  641. {
  642. HCRYPTPROV hCryptProv;
  643. PCMSG_SP3_COMPATIBLE_AUX_INFO pSP3AuxInfo =
  644. (PCMSG_SP3_COMPATIBLE_AUX_INFO) pvEncryptAuxInfo;
  645. PCCRYPT_OID_INFO pOIDInfo;
  646. DWORD dwAlgIdEncrypt;
  647. hCryptProv = *phCryptProv;
  648. if (0 == hCryptProv || NULL == pSP3AuxInfo ||
  649. sizeof(CMSG_SP3_COMPATIBLE_AUX_INFO) > pSP3AuxInfo->cbSize ||
  650. 0 == (pSP3AuxInfo->dwFlags & CMSG_SP3_COMPATIBLE_ENCRYPT_FLAG)) {
  651. // Let SP3ExportEncryptKey() know this will be a default export
  652. TlsSetValue(iSP3TLS, NULL);
  653. if (pfnDefaultGenEncryptKey)
  654. // Generate using the default
  655. return pfnDefaultGenEncryptKey(
  656. phCryptProv,
  657. paiEncrypt,
  658. pvEncryptAuxInfo,
  659. pPublicKeyInfo,
  660. pfnAlloc,
  661. phEncryptKey,
  662. ppbEncryptParameters,
  663. pcbEncryptParameters
  664. );
  665. else {
  666. // We don't have a default
  667. *phEncryptKey = 0;
  668. SetLastError((DWORD) E_UNEXPECTED);
  669. return FALSE;
  670. }
  671. }
  672. // Let SP3ExportEncryptKey() know this will be a SP3 compatible export.
  673. TlsSetValue(iSP3TLS, SP3_TLS_POINTER);
  674. // Map the ASN algorithm identifier to the CSP ALG_ID.
  675. if (NULL == (pOIDInfo = CryptFindOIDInfo(
  676. CRYPT_OID_INFO_OID_KEY,
  677. paiEncrypt->pszObjId,
  678. CRYPT_ENCRYPT_ALG_OID_GROUP_ID))) {
  679. *phEncryptKey = 0;
  680. return FALSE;
  681. }
  682. dwAlgIdEncrypt = pOIDInfo->Algid;
  683. // Since CRYPT_NO_SALT flag isn't set, uses zero salt
  684. if (!CryptGenKey(
  685. hCryptProv,
  686. dwAlgIdEncrypt,
  687. CRYPT_EXPORTABLE,
  688. phEncryptKey)) {
  689. *phEncryptKey = 0;
  690. return FALSE;
  691. }
  692. return TRUE;
  693. }
  694. //+-------------------------------------------------------------------------
  695. // SP3 export of the encryption key.
  696. //
  697. // The SP3 version of crypt32.dll encoded the encrypted symmetric key as
  698. // little endian instead of as big endian.
  699. //--------------------------------------------------------------------------
  700. BOOL
  701. WINAPI
  702. SP3ExportEncryptKey(
  703. IN HCRYPTPROV hCryptProv,
  704. IN HCRYPTKEY hEncryptKey,
  705. IN PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  706. OUT PBYTE pbData,
  707. IN OUT PDWORD pcbData
  708. )
  709. {
  710. BOOL fResult;
  711. DWORD dwError = ERROR_SUCCESS;
  712. HCRYPTKEY hPubKey = NULL;
  713. PBYTE pb = NULL;
  714. DWORD cb;
  715. if (SP3_TLS_POINTER != TlsGetValue(iSP3TLS)) {
  716. if (pfnDefaultExportEncryptKey)
  717. // Export using the default function
  718. return pfnDefaultExportEncryptKey(
  719. hCryptProv,
  720. hEncryptKey,
  721. pPublicKeyInfo,
  722. pbData,
  723. pcbData
  724. );
  725. else {
  726. // We don't have a default
  727. *pcbData = 0;
  728. SetLastError((DWORD) E_UNEXPECTED);
  729. return FALSE;
  730. }
  731. }
  732. // SP3 compatible export and encode
  733. if (!CryptImportPublicKeyInfo(
  734. hCryptProv,
  735. X509_ASN_ENCODING,
  736. pPublicKeyInfo,
  737. &hPubKey))
  738. goto ImportKeyError;
  739. if (!CryptExportKey(
  740. hEncryptKey,
  741. hPubKey,
  742. SIMPLEBLOB,
  743. 0, // dwFlags
  744. NULL,
  745. &cb))
  746. goto ExportKeySizeError;
  747. if (NULL == (pb = (PBYTE) SP3Alloc(cb)))
  748. goto ExportKeyAllocError;
  749. if (!CryptExportKey(
  750. hEncryptKey,
  751. hPubKey,
  752. SIMPLEBLOB,
  753. 0, // dwFlags
  754. pb,
  755. &cb))
  756. goto ExportKeyError;
  757. cb -= sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER);
  758. fResult = TRUE;
  759. if (pbData) {
  760. if (*pcbData < cb) {
  761. SetLastError((DWORD) ERROR_MORE_DATA);
  762. fResult = FALSE;
  763. } else if (0 < cb) {
  764. // Don't byte reverse
  765. memcpy(pbData,
  766. pb + (sizeof(PUBLICKEYSTRUC) + sizeof(SIMPLEBLOBHEADER)), cb);
  767. }
  768. }
  769. CommonReturn:
  770. *pcbData = cb;
  771. if (pb)
  772. SP3Free(pb);
  773. if (hPubKey)
  774. CryptDestroyKey(hPubKey);
  775. SetLastError(dwError);
  776. return fResult;
  777. ImportKeyError:
  778. ExportKeySizeError:
  779. ExportKeyAllocError:
  780. ExportKeyError:
  781. dwError = GetLastError();
  782. cb = 0;
  783. fResult = FALSE;
  784. goto CommonReturn;
  785. }
  786. #ifdef CMS_PKCS7
  787. BOOL
  788. WINAPI
  789. CryptMsgDllGenContentEncryptKey(
  790. IN OUT PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  791. IN DWORD dwFlags,
  792. IN OPTIONAL void *pvReserved
  793. )
  794. {
  795. BOOL fResult;
  796. HCRYPTOIDFUNCSET hGenContentFuncSet;
  797. HCRYPTOIDFUNCADDR hFuncAddr;
  798. PFN_CMSG_GEN_CONTENT_ENCRYPT_KEY pfnDefaultGenContent;
  799. if (NULL == (hGenContentFuncSet = CryptInitOIDFunctionSet(
  800. CMSG_OID_GEN_CONTENT_ENCRYPT_KEY_FUNC, 0)))
  801. return FALSE;
  802. // Get the default gen content encrypt key function which we will call
  803. if (!CryptGetOIDFunctionAddress(
  804. hGenContentFuncSet,
  805. X509_ASN_ENCODING,
  806. CMSG_DEFAULT_INSTALLABLE_FUNC_OID,
  807. CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
  808. (void **) &pfnDefaultGenContent,
  809. &hFuncAddr))
  810. return FALSE;
  811. fResult = pfnDefaultGenContent(
  812. pContentEncryptInfo,
  813. dwFlags,
  814. pvReserved
  815. );
  816. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  817. return fResult;
  818. }
  819. BOOL
  820. WINAPI
  821. CryptMsgDllExportKeyTrans(
  822. IN PCMSG_CONTENT_ENCRYPT_INFO pContentEncryptInfo,
  823. IN PCMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO pKeyTransEncodeInfo,
  824. IN OUT PCMSG_KEY_TRANS_ENCRYPT_INFO pKeyTransEncryptInfo,
  825. IN DWORD dwFlags,
  826. IN OPTIONAL void *pvReserved
  827. )
  828. {
  829. BOOL fResult;
  830. HCRYPTOIDFUNCSET hExportKeyTransFuncSet;
  831. HCRYPTOIDFUNCADDR hFuncAddr;
  832. PFN_CMSG_EXPORT_KEY_TRANS pfnDefaultExportKeyTrans;
  833. if (NULL == (hExportKeyTransFuncSet = CryptInitOIDFunctionSet(
  834. CMSG_OID_EXPORT_KEY_TRANS_FUNC, 0)))
  835. return FALSE;
  836. // Get the default export key trans function which we will call
  837. if (!CryptGetOIDFunctionAddress(
  838. hExportKeyTransFuncSet,
  839. X509_ASN_ENCODING,
  840. CMSG_DEFAULT_INSTALLABLE_FUNC_OID,
  841. CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
  842. (void **) &pfnDefaultExportKeyTrans,
  843. &hFuncAddr))
  844. return FALSE;
  845. fResult = pfnDefaultExportKeyTrans(
  846. pContentEncryptInfo,
  847. pKeyTransEncodeInfo,
  848. pKeyTransEncryptInfo,
  849. dwFlags,
  850. pvReserved
  851. );
  852. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  853. return fResult;
  854. }
  855. BOOL
  856. WINAPI
  857. CryptMsgDllImportKeyTrans(
  858. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  859. IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
  860. IN DWORD dwFlags,
  861. IN OPTIONAL void *pvReserved,
  862. OUT HCRYPTKEY *phContentEncryptKey
  863. )
  864. {
  865. BOOL fResult;
  866. HCRYPTOIDFUNCSET hImportKeyTransFuncSet;
  867. HCRYPTOIDFUNCADDR hFuncAddr;
  868. PFN_CMSG_IMPORT_KEY_TRANS pfnDefaultImportKeyTrans;
  869. if (NULL == (hImportKeyTransFuncSet = CryptInitOIDFunctionSet(
  870. CMSG_OID_IMPORT_KEY_TRANS_FUNC, 0)))
  871. return FALSE;
  872. // Get the default import key trans function which we will call
  873. if (!CryptGetOIDFunctionAddress(
  874. hImportKeyTransFuncSet,
  875. X509_ASN_ENCODING,
  876. CMSG_DEFAULT_INSTALLABLE_FUNC_OID,
  877. CRYPT_GET_INSTALLED_OID_FUNC_FLAG,
  878. (void **) &pfnDefaultImportKeyTrans,
  879. &hFuncAddr))
  880. return FALSE;
  881. fResult = pfnDefaultImportKeyTrans(
  882. pContentEncryptionAlgorithm,
  883. pKeyTransDecryptPara,
  884. dwFlags,
  885. pvReserved,
  886. phContentEncryptKey
  887. );
  888. CryptFreeOIDFunctionAddress(hFuncAddr, 0);
  889. return fResult;
  890. }
  891. BOOL
  892. WINAPI
  893. NotImplCryptMsgDllImportKeyTrans(
  894. IN PCRYPT_ALGORITHM_IDENTIFIER pContentEncryptionAlgorithm,
  895. IN PCMSG_CTRL_KEY_TRANS_DECRYPT_PARA pKeyTransDecryptPara,
  896. IN DWORD dwFlags,
  897. IN OPTIONAL void *pvReserved,
  898. OUT HCRYPTKEY *phContentEncryptKey
  899. )
  900. {
  901. SetLastError((DWORD) E_NOTIMPL);
  902. return FALSE;
  903. }
  904. #endif // CMS_PKCS7