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.

6773 lines
186 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : nt_key.c //
  3. // DESCRIPTION : Crypto CP interfaces: //
  4. // CPGenKey //
  5. // CPDeriveKey //
  6. // CPExportKey //
  7. // CPImportKey //
  8. // CPDestroyKey //
  9. // CPGetUserKey //
  10. // CPSetKeyParam //
  11. // CPGetKeyParam //
  12. // AUTHOR : //
  13. // HISTORY : //
  14. // Jan 25 1995 larrys Changed from Nametag //
  15. // Feb 16 1995 larrys Fix problem for 944 build //
  16. // Feb 21 1995 larrys Added SPECIAL_KEY //
  17. // Feb 23 1995 larrys Changed NTag_SetLastError to SetLastError //
  18. // Mar 08 1995 larrys Fixed a few problems //
  19. // Mar 23 1995 larrys Added variable key length //
  20. // Apr 7 1995 larrys Removed CryptConfigure //
  21. // Apr 17 1995 larrys Added 1024 key gen //
  22. // Apr 19 1995 larrys Changed CRYPT_EXCH_PUB to AT_KEYEXCHANGE //
  23. // May 10 1995 larrys added private api calls //
  24. // May 17 1995 larrys added key data for DES test //
  25. // Jul 20 1995 larrys Changed export of PUBLICKEYBLOB //
  26. // Jul 21 1995 larrys Fixed Export of AUTHENTICATEDBLOB //
  27. // Aug 03 1995 larrys Allow CryptG(S)etKeyParam for Public keys & //
  28. // Removed CPTranslate //
  29. // Aug 10 1995 larrys Fixed a few problems in CryptGetKeyParam //
  30. // Aug 11 1995 larrys Return no key for CryptGetUserKey //
  31. // Aug 14 1995 larrys Removed key exchange stuff //
  32. // Aug 17 1995 larrys Removed a error //
  33. // Aug 18 1995 larrys Changed NTE_BAD_LEN to ERROR_MORE_DATA //
  34. // Aug 30 1995 larrys Removed RETURNASHVALUE from CryptGetHashValue //
  35. // Aug 31 1995 larrys Fixed CryptExportKey if pbData == NULL //
  36. // Sep 05 1995 larrys Fixed bug # 30 //
  37. // Sep 05 1995 larrys Fixed bug # 31 //
  38. // Sep 11 1995 larrys Fixed bug # 34 //
  39. // Sep 12 1995 larrys Removed 2 DWORDS from exported keys //
  40. // Sep 14 1995 Jeffspel/ramas Merged STT onto CSP //
  41. // Sep 18 1995 larrys Changed def KP_PERMISSIONS to 0xffffffff //
  42. // Oct 02 1995 larrys Fixed bug 43 return error for importkey on hPubkey //
  43. // Oct 03 1995 larrys Fixed bug 37 call InflateKey from SetKeyParam //
  44. // Oct 03 1995 larrys Fixed bug 36, removed OFB from SetKeyParam //
  45. // Oct 03 1995 larrys Fixed bug 38, check key type in SetKeyParam //
  46. // Oct 13 1995 larrys Added CPG/setProv/HashParam //
  47. // Oct 13 1995 larrys Added code for CryptSetHashValue //
  48. // Oct 16 1995 larrys Changes for CryptGetHashParam //
  49. // Oct 23 1995 larrys Added code for GetProvParam PP_CONTAINER //
  50. // Oct 27 1995 rajeshk RandSeed Stuff added hUID to PKCS2Encrypt+ others //
  51. // Nov 3 1995 larrys Merge changes for NT checkin //
  52. // Nov 9 1995 larrys Bug fix 10686 //
  53. // Nov 30 1995 larrys Bug fix //
  54. // Dec 11 1995 larrys Added WIN96 password cache //
  55. // Feb 29 1996 rajeshk Added Check for SetHashParam for HASHVALUE //
  56. // May 15 1996 larrys Added private key export //
  57. // May 28 1996 larrys Fix bug 88 //
  58. // Jun 6 1996 a-johnb Added support for SSL 3.0 signatures //
  59. // Aug 28 1996 mattt Changed enum to calculate size from #defined sizes //
  60. // Sep 13 1996 mattt Compat w/RSABase 88-bit 0 salt, FIsLegalKey() //
  61. // Sep 16 1996 mattt Added KP_KEYLEN ability //
  62. // Sep 16 1996 jeffspel Added triple DES functionality //
  63. // Oct 14 1996 jeffspel Changed GenRandoms to NewGenRandoms //
  64. // Apr 29 1997 jeffspel Key storage ability GetProvParam, PStore support //
  65. // Apr 29 1997 jeffspel Added EnumAlgsEx tp GetProvParam //
  66. // May 23 1997 jeffspel Added provider type checking //
  67. // Jul 15 1997 jeffspel Added ability to decrypt with large RC2 keys //
  68. // Jul 28 1997 jeffspel Added ability to delete a persisted key //
  69. // Sep 09 1997 jeffspel Added PP_KEYSET_TYPE to CPGetProvParam //
  70. // Sep 12 1997 jeffspel Added Opaque blob support //
  71. // May 4 2000 dbarlow Error code return cleanup //
  72. // //
  73. // Copyright (C) 1993 - 2000 Microsoft Corporation //
  74. // All Rights Reserved //
  75. /////////////////////////////////////////////////////////////////////////////
  76. #include "precomp.h"
  77. #include "nt_rsa.h"
  78. #include "nt_blobs.h"
  79. #include "swnt_pk.h"
  80. #include "mac.h"
  81. #include "ntagimp1.h"
  82. #include "tripldes.h"
  83. #include "ntagum.h"
  84. #include "randlib.h"
  85. #ifdef CSP_USE_SSL3
  86. #include "ssl3.h"
  87. #endif
  88. #include "protstor.h"
  89. #include "sgccheck.h"
  90. #include "aes.h"
  91. extern CSP_STRINGS g_Strings;
  92. #ifndef CSP_USE_AES
  93. #define UnsupportedSymKey(pKey) ((CALG_RC4 != pKey->Algid) && \
  94. (CALG_RC2 != pKey->Algid) && \
  95. (CALG_DES != pKey->Algid) && \
  96. (CALG_3DES != pKey->Algid) && \
  97. (CALG_3DES_112 != pKey->Algid))
  98. #else
  99. #define UnsupportedSymKey(pKey) ((CALG_RC4 != pKey->Algid) && \
  100. (CALG_RC2 != pKey->Algid) && \
  101. (CALG_DES != pKey->Algid) && \
  102. (CALG_3DES != pKey->Algid) && \
  103. (CALG_3DES_112 != pKey->Algid) && \
  104. (CALG_AES_128 != pKey->Algid) && \
  105. (CALG_AES_192 != pKey->Algid) && \
  106. (CALG_AES_256 != pKey->Algid))
  107. #endif
  108. #define NTAG_REG_KEY_LOC "Software\\Microsoft\\Cryptography\\UserKeys"
  109. #define NTAG_MACH_REG_KEY_LOC "Software\\Microsoft\\Cryptography\\MachineKeys"
  110. extern DWORD
  111. InflateKey(
  112. IN PNTAGKeyList pTmpKey);
  113. /*static*/ DWORD
  114. CopyKey(
  115. IN PNTAGKeyList pOldKey,
  116. OUT PNTAGKeyList *ppNewKey);
  117. extern DWORD
  118. SymEncrypt(
  119. IN PNTAGKeyList pKey,
  120. IN BOOL fFinal,
  121. IN OUT BYTE *pbData,
  122. IN OUT DWORD *pcbData,
  123. IN DWORD cbBuf);
  124. extern DWORD
  125. SymDecrypt(
  126. IN PNTAGKeyList pKey,
  127. IN PNTAGHashList pHash,
  128. IN BOOL fFinal,
  129. IN OUT BYTE *pbData,
  130. IN OUT DWORD *pcbData);
  131. extern DWORD
  132. BlockEncrypt(
  133. void EncFun(BYTE *In, BYTE *Out, void *key, int op),
  134. PNTAGKeyList pKey,
  135. int BlockLen,
  136. BOOL Final,
  137. BYTE *pbData,
  138. DWORD *pdwDataLen,
  139. DWORD dwBufLen);
  140. static BYTE rgbSymmetricKeyWrapIV[8]
  141. = {0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05};
  142. //
  143. // Set the permissions on the key
  144. //
  145. /*static*/ void
  146. SetInitialKeyPermissions(
  147. PNTAGKeyList pKey)
  148. {
  149. if (CRYPT_EXPORTABLE == pKey->Rights)
  150. {
  151. pKey->Permissions |= CRYPT_EXPORT;
  152. }
  153. // UNDONE - set the appopropriate permission with the appropriate
  154. // algorithm
  155. pKey->Permissions |= CRYPT_ENCRYPT | CRYPT_DECRYPT| CRYPT_READ |
  156. CRYPT_WRITE | CRYPT_MAC;
  157. }
  158. /* MakeNewKey
  159. *
  160. * Helper routine for ImportKey, GenKey
  161. *
  162. * Allocate a new key record, fill in the data and copy in the key
  163. * bytes.
  164. */
  165. DWORD
  166. MakeNewKey(
  167. ALG_ID aiKeyAlg,
  168. DWORD dwRights,
  169. DWORD dwKeyLen,
  170. HCRYPTPROV hUID,
  171. BYTE *pbKeyData,
  172. BOOL fUsePassedKeyBuffer,
  173. BOOL fPreserveExactKey,
  174. PNTAGKeyList *ppKeyList)
  175. {
  176. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  177. PNTAGKeyList pKey = NULL;
  178. *ppKeyList = NULL;
  179. // allocate space for the key record
  180. pKey = (PNTAGKeyList)_nt_malloc(sizeof(NTAGKeyList));
  181. if (NULL == pKey)
  182. {
  183. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  184. goto ErrorExit;
  185. }
  186. if (!fUsePassedKeyBuffer)
  187. {
  188. pKey->pKeyValue = (BYTE *)_nt_malloc((size_t)dwKeyLen);
  189. if (NULL == pKey->pKeyValue)
  190. {
  191. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  192. goto ErrorExit;
  193. }
  194. }
  195. pKey->Algid = aiKeyAlg;
  196. pKey->Rights = dwRights;
  197. pKey->cbDataLen = 0;
  198. pKey->pData = NULL;
  199. pKey->hUID = hUID;
  200. memset(pKey->IV, 0, MAX_BLOCKLEN);
  201. memset(pKey->FeedBack, 0, MAX_BLOCKLEN);
  202. pKey->InProgress = FALSE;
  203. pKey->cbSaltLen = 0;
  204. pKey->Padding = PKCS5_PADDING;
  205. pKey->Mode = CRYPT_MODE_CBC;
  206. pKey->ModeBits = 0;
  207. SetInitialKeyPermissions(pKey);
  208. pKey->cbKeyLen = dwKeyLen;
  209. if (pbKeyData != NULL)
  210. {
  211. if (fUsePassedKeyBuffer)
  212. pKey->pKeyValue = pbKeyData;
  213. else
  214. memcpy(pKey->pKeyValue, pbKeyData, (size_t)dwKeyLen);
  215. }
  216. // Handle special cases
  217. switch (aiKeyAlg)
  218. {
  219. case CALG_RC2:
  220. // for RC2 set a default effective key length
  221. pKey->EffectiveKeyLen = RC2_DEFAULT_EFFECTIVE_KEYLEN;
  222. pKey->dwBlockLen = RC2_BLOCKLEN;
  223. break;
  224. case CALG_DES:
  225. if (DES_KEYSIZE != pKey->cbKeyLen)
  226. {
  227. dwReturn = (DWORD)NTE_BAD_FLAGS;
  228. goto ErrorExit;
  229. }
  230. if (!fPreserveExactKey)
  231. desparityonkey(pKey->pKeyValue, pKey->cbKeyLen);
  232. pKey->dwBlockLen = DES_BLOCKLEN;
  233. break;
  234. case CALG_3DES_112:
  235. if (DES_KEYSIZE * 2 != pKey->cbKeyLen)
  236. {
  237. dwReturn = (DWORD)NTE_BAD_FLAGS;
  238. goto ErrorExit;
  239. }
  240. if (!fPreserveExactKey)
  241. desparityonkey(pKey->pKeyValue, pKey->cbKeyLen);
  242. pKey->dwBlockLen = DES_BLOCKLEN;
  243. break;
  244. case CALG_3DES:
  245. if (DES_KEYSIZE * 3 != pKey->cbKeyLen)
  246. {
  247. dwReturn = (DWORD)NTE_BAD_FLAGS;
  248. goto ErrorExit;
  249. }
  250. if (!fPreserveExactKey)
  251. desparityonkey(pKey->pKeyValue, pKey->cbKeyLen);
  252. pKey->dwBlockLen = DES_BLOCKLEN;
  253. break;
  254. #ifdef CSP_USE_AES
  255. case CALG_AES_128:
  256. pKey->dwBlockLen = CRYPT_AES128_BLKLEN;
  257. break;
  258. case CALG_AES_192:
  259. pKey->dwBlockLen = CRYPT_AES192_BLKLEN;
  260. break;
  261. case CALG_AES_256:
  262. pKey->dwBlockLen = CRYPT_AES256_BLKLEN;
  263. break;
  264. #endif
  265. default:
  266. pKey->dwBlockLen = 0;
  267. }
  268. *ppKeyList = pKey;
  269. return ERROR_SUCCESS;
  270. ErrorExit:
  271. if (NULL != pKey)
  272. _nt_free (pKey, sizeof(NTAGKeyList));
  273. return dwReturn;
  274. }
  275. /* FreeNewKey
  276. *
  277. * Use for cleanup on abort of key build operations.
  278. *
  279. */
  280. void
  281. FreeNewKey(
  282. PNTAGKeyList pOldKey)
  283. {
  284. if (pOldKey->pKeyValue)
  285. _nt_free(pOldKey->pKeyValue, pOldKey->cbKeyLen);
  286. if (pOldKey->pData)
  287. _nt_free(pOldKey->pData, pOldKey->cbDataLen);
  288. _nt_free(pOldKey, sizeof(NTAGKeyList));
  289. }
  290. /* FIsLegalKeySize
  291. *
  292. * Check that the length of the key is legal (essentially
  293. * complies with export).
  294. *
  295. */
  296. BOOL
  297. FIsLegalKeySize(
  298. IN DWORD dwCspTypeId,
  299. IN ALG_ID Algid,
  300. IN DWORD cbKey,
  301. IN BOOL fRC2BigKeyOK,
  302. OUT BOOL *pfPubKey)
  303. {
  304. BOOL fRet = FALSE;
  305. *pfPubKey = FALSE;
  306. switch (Algid)
  307. {
  308. #ifdef CSP_USE_RC2
  309. case CALG_RC2:
  310. if (!fRC2BigKeyOK)
  311. {
  312. if (!IsLegalLength(g_AlgTables[dwCspTypeId], Algid,
  313. cbKey * 8, NULL))
  314. goto ErrorExit;
  315. }
  316. break;
  317. #endif
  318. #ifdef CSP_USE_DES
  319. case CALG_DES:
  320. if ((DES_KEYSIZE != cbKey) && ((DES_KEYSIZE - 1) != cbKey))
  321. goto ErrorExit;
  322. break;
  323. #endif
  324. #ifdef CSP_USE_3DES
  325. case CALG_3DES_112:
  326. if ((DES2_KEYSIZE != cbKey) && ((DES2_KEYSIZE - 2) != cbKey))
  327. goto ErrorExit;
  328. break;
  329. case CALG_3DES:
  330. if ((DES3_KEYSIZE != cbKey) && ((DES3_KEYSIZE - 3) != cbKey))
  331. goto ErrorExit;
  332. break;
  333. #endif
  334. case CALG_RSA_SIGN:
  335. case CALG_RSA_KEYX:
  336. *pfPubKey = TRUE;
  337. // Fall through intentionally.
  338. default:
  339. if (!IsLegalLength(g_AlgTables[dwCspTypeId], Algid, cbKey * 8, NULL))
  340. goto ErrorExit;
  341. }
  342. fRet = TRUE;
  343. ErrorExit:
  344. // not of regulation size
  345. return fRet;
  346. }
  347. #ifdef USE_SGC
  348. /* FIsLegalSGCKeySize
  349. *
  350. * Check that the length of the key is SGC legal (essentially
  351. * complies with export).
  352. *
  353. */
  354. BOOL
  355. FIsLegalSGCKeySize(
  356. IN ALG_ID Algid,
  357. IN DWORD cbKey,
  358. IN BOOL fRC2BigKeyOK,
  359. IN BOOL fGenKey,
  360. OUT BOOL *pfPubKey)
  361. {
  362. BOOL fSts = FALSE;
  363. if (!fGenKey)
  364. {
  365. if (!FIsLegalKeySize(POLICY_MS_SCHANNEL, Algid, cbKey, fRC2BigKeyOK,
  366. pfPubKey))
  367. goto ErrorExit;
  368. }
  369. else
  370. {
  371. switch (Algid)
  372. {
  373. #ifdef CSP_USE_RC2
  374. case CALG_RC2:
  375. if (!fRC2BigKeyOK)
  376. goto ErrorExit;
  377. break;
  378. #endif
  379. #ifdef CSP_USE_SSL3
  380. case CALG_SSL3_MASTER:
  381. case CALG_TLS1_MASTER:
  382. case CALG_PCT1_MASTER:
  383. case CALG_SSL2_MASTER:
  384. if (!FIsLegalKeySize(POLICY_MS_SCHANNEL, Algid, cbKey,
  385. fRC2BigKeyOK, pfPubKey))
  386. goto ErrorExit;
  387. break;
  388. case CALG_SCHANNEL_MAC_KEY:
  389. break;
  390. #endif
  391. case CALG_RSA_KEYX:
  392. if (!FIsLegalKeySize(POLICY_MS_SCHANNEL, Algid, cbKey,
  393. fRC2BigKeyOK, pfPubKey))
  394. goto ErrorExit;
  395. break;
  396. default:
  397. goto ErrorExit;
  398. }
  399. }
  400. fSts = TRUE;
  401. ErrorExit:
  402. return fSts;
  403. }
  404. #endif
  405. /* FIsLegalKey
  406. *
  407. * Check that the length of the key is legal (essentially
  408. * complies with export).
  409. *
  410. */
  411. BOOL
  412. FIsLegalKey(
  413. IN PNTAGUserList pTmpUser,
  414. IN PNTAGKeyList pKey,
  415. IN BOOL fRC2BigKeyOK)
  416. {
  417. BOOL fPubKey;
  418. BOOL fRet = FALSE;
  419. if (pKey == NULL)
  420. goto ErrorExit;
  421. #ifdef USE_SGC
  422. // check if the provider is an SChannel provider and if so if the
  423. // SGC flag is set then use the FIsLegalSGCKeySize function
  424. if ((PROV_RSA_SCHANNEL == pTmpUser->dwProvType)
  425. && (0 != pTmpUser->dwSGCFlags))
  426. {
  427. if (!FIsLegalSGCKeySize(pKey->Algid, pKey->cbKeyLen,
  428. fRC2BigKeyOK, FALSE, &fPubKey))
  429. {
  430. goto ErrorExit;
  431. }
  432. }
  433. else
  434. #endif
  435. {
  436. // 4th parameter, dwFlags, is used for SGC Exch keys so just
  437. // pass zero in this case
  438. if (!FIsLegalKeySize(pTmpUser->dwCspTypeId,
  439. pKey->Algid, pKey->cbKeyLen,
  440. fRC2BigKeyOK, &fPubKey))
  441. {
  442. goto ErrorExit;
  443. }
  444. }
  445. fRet = TRUE;
  446. ErrorExit:
  447. return fRet;
  448. }
  449. /* FIsLegalImportSymKey
  450. *
  451. * Verify that imported symmetric keys meet the size restrictions
  452. * of the CSP in use. In addition, require all DES-variant
  453. * keys to be of the full required size, including parity bits.
  454. */
  455. BOOL
  456. FIsLegalImportSymKey(
  457. IN PNTAGUserList pTmpUser,
  458. IN PNTAGKeyList pKey,
  459. IN BOOL fRC2BigKeyOK)
  460. {
  461. BOOL fRet = FALSE;
  462. switch (pKey->Algid)
  463. {
  464. #ifdef CSP_USE_RC2
  465. case CALG_RC2:
  466. if (!fRC2BigKeyOK)
  467. {
  468. if (!IsLegalLength(g_AlgTables[pTmpUser->dwCspTypeId], pKey->Algid,
  469. pKey->cbKeyLen * 8, NULL))
  470. goto ErrorExit;
  471. }
  472. break;
  473. #endif
  474. #ifdef CSP_USE_DES
  475. case CALG_DES:
  476. if (DES_KEYSIZE != pKey->cbKeyLen)
  477. goto ErrorExit;
  478. break;
  479. #endif
  480. #ifdef CSP_USE_3DES
  481. case CALG_3DES_112:
  482. if (DES2_KEYSIZE != pKey->cbKeyLen)
  483. goto ErrorExit;
  484. break;
  485. case CALG_3DES:
  486. if (DES3_KEYSIZE != pKey->cbKeyLen)
  487. goto ErrorExit;
  488. break;
  489. #endif
  490. case CALG_RSA_SIGN:
  491. case CALG_RSA_KEYX:
  492. goto ErrorExit;
  493. default:
  494. if (!IsLegalLength(g_AlgTables[pTmpUser->dwCspTypeId], pKey->Algid,
  495. pKey->cbKeyLen * 8, NULL))
  496. goto ErrorExit;
  497. }
  498. fRet = TRUE;
  499. ErrorExit:
  500. return fRet;
  501. }
  502. /*static*/ DWORD
  503. MakeKeyRSABaseCompatible(
  504. HCRYPTPROV hUID,
  505. HCRYPTKEY hKey)
  506. {
  507. CRYPT_DATA_BLOB sSaltData;
  508. BYTE rgbZeroSalt[11];
  509. BOOL fSts;
  510. ZeroMemory(rgbZeroSalt, 11);
  511. sSaltData.pbData = rgbZeroSalt;
  512. sSaltData.cbData = sizeof(rgbZeroSalt);
  513. fSts = CPSetKeyParam(hUID, hKey, KP_SALT_EX, (PBYTE)&sSaltData, 0);
  514. if (!fSts)
  515. return GetLastError();
  516. return ERROR_SUCCESS;
  517. }
  518. typedef struct
  519. {
  520. DWORD magic; /* Should always be RSA2 */
  521. DWORD bitlen; // bit size of key
  522. DWORD pubexp; // public exponent
  523. } EXPORT_PRV_KEY, FAR *PEXPORT_PRV_KEY;
  524. /* GetLengthOfPrivateKeyForExport
  525. *
  526. * Get the length of the private key
  527. * blob from the public key.
  528. *
  529. */
  530. /*static*/ void
  531. GetLengthOfPrivateKeyForExport(
  532. IN BSAFE_PUB_KEY *pPubKey,
  533. OUT PDWORD pcbBlob)
  534. {
  535. DWORD cbHalfModLen;
  536. cbHalfModLen = (pPubKey->bitlen + 15) / 16;
  537. *pcbBlob = sizeof(EXPORT_PRV_KEY) + 9 * cbHalfModLen;
  538. }
  539. /* PreparePrivateKeyForExport
  540. *
  541. * Massage the key from the registry
  542. * into an exportable format.
  543. *
  544. */
  545. /*static*/ BOOL
  546. PreparePrivateKeyForExport(
  547. IN BSAFE_PRV_KEY *pPrvKey,
  548. OUT PBYTE pbBlob,
  549. IN OUT PDWORD pcbBlob)
  550. {
  551. PEXPORT_PRV_KEY pExportKey;
  552. DWORD cbHalfModLen;
  553. DWORD cbBlobLen;
  554. DWORD cbTmpLen;
  555. DWORD cbHalfTmpLen;
  556. PBYTE pbIn;
  557. PBYTE pbOut;
  558. cbHalfModLen = (pPrvKey->bitlen + 15) / 16;
  559. cbBlobLen = sizeof(EXPORT_PRV_KEY) + 9 * cbHalfModLen;
  560. // figure out the number of overflow bytes which are in the private
  561. // key structure
  562. cbTmpLen = (sizeof(DWORD) * 2)
  563. - (((pPrvKey->bitlen + 7) / 8) % (sizeof(DWORD) * 2));
  564. if ((sizeof(DWORD) * 2) != cbTmpLen)
  565. cbTmpLen += sizeof(DWORD) * 2;
  566. cbHalfTmpLen = cbTmpLen / 2;
  567. if (NULL == pbBlob)
  568. {
  569. *pcbBlob = cbBlobLen;
  570. return TRUE;
  571. }
  572. if (*pcbBlob < cbBlobLen)
  573. {
  574. *pcbBlob = cbBlobLen;
  575. return FALSE;
  576. }
  577. // take most of the header info
  578. pExportKey = (PEXPORT_PRV_KEY)pbBlob;
  579. pExportKey->magic = pPrvKey->magic;
  580. pExportKey->bitlen = pPrvKey->bitlen;
  581. pExportKey->pubexp = pPrvKey->pubexp;
  582. pbIn = (PBYTE)pPrvKey + sizeof(BSAFE_PRV_KEY);
  583. pbOut = pbBlob + sizeof(EXPORT_PRV_KEY);
  584. // copy all the private key info
  585. CopyMemory(pbOut, pbIn, pExportKey->bitlen / 8);
  586. pbIn += pExportKey->bitlen / 8 + cbTmpLen;
  587. pbOut += pExportKey->bitlen / 8;
  588. CopyMemory(pbOut, pbIn, cbHalfModLen);
  589. pbIn += cbHalfModLen + cbHalfTmpLen;
  590. pbOut += cbHalfModLen;
  591. CopyMemory(pbOut, pbIn, cbHalfModLen);
  592. pbIn += cbHalfModLen + cbHalfTmpLen;
  593. pbOut += cbHalfModLen;
  594. CopyMemory(pbOut, pbIn, cbHalfModLen);
  595. pbIn += cbHalfModLen + cbHalfTmpLen;
  596. pbOut += cbHalfModLen;
  597. CopyMemory(pbOut, pbIn, cbHalfModLen);
  598. pbIn += cbHalfModLen + cbHalfTmpLen;
  599. pbOut += cbHalfModLen;
  600. CopyMemory(pbOut, pbIn, cbHalfModLen);
  601. pbIn += cbHalfModLen + cbHalfTmpLen;
  602. pbOut += cbHalfModLen;
  603. CopyMemory(pbOut, pbIn, pExportKey->bitlen / 8);
  604. *pcbBlob = cbBlobLen;
  605. return TRUE;
  606. }
  607. /* PreparePrivateKeyForImport
  608. *
  609. * Massage the incoming into a form acceptable for
  610. * the registry.
  611. *
  612. */
  613. /*static*/ BOOL
  614. PreparePrivateKeyForImport(
  615. IN PBYTE pbBlob,
  616. OUT BSAFE_PRV_KEY *pPrvKey,
  617. IN OUT PDWORD pPrvKeyLen,
  618. OUT BSAFE_PUB_KEY *pPubKey,
  619. IN OUT PDWORD pPubKeyLen)
  620. {
  621. PEXPORT_PRV_KEY pExportKey = (PEXPORT_PRV_KEY)pbBlob;
  622. DWORD cbHalfModLen;
  623. DWORD cbPub;
  624. DWORD cbPrv;
  625. PBYTE pbIn;
  626. PBYTE pbOut;
  627. DWORD cbTmpLen;
  628. DWORD cbHalfTmpLen;
  629. if (RSA2 != pExportKey->magic)
  630. return FALSE;
  631. // figure out the number of overflow bytes which are in the private
  632. // key structure
  633. cbTmpLen = (sizeof(DWORD) * 2)
  634. - (((pExportKey->bitlen + 7) / 8) % (sizeof(DWORD) * 2));
  635. if ((sizeof(DWORD) * 2) != cbTmpLen)
  636. cbTmpLen += sizeof(DWORD) * 2;
  637. cbHalfTmpLen = cbTmpLen / 2;
  638. cbHalfModLen = (pExportKey->bitlen + 15) / 16;
  639. cbPub = sizeof(BSAFE_PUB_KEY) + (pExportKey->bitlen / 8) + cbTmpLen;
  640. cbPrv = sizeof(BSAFE_PRV_KEY) + (cbHalfModLen + cbHalfTmpLen) * 10;
  641. if ((NULL == pPrvKey) || (NULL == pPubKey))
  642. {
  643. *pPubKeyLen = cbPub;
  644. *pPrvKeyLen = cbPrv;
  645. return TRUE;
  646. }
  647. if ((*pPubKeyLen < cbPub) || (*pPrvKeyLen < cbPrv))
  648. {
  649. *pPubKeyLen = cbPub;
  650. *pPrvKeyLen = cbPrv;
  651. return FALSE;
  652. }
  653. // form the public key
  654. ZeroMemory(pPubKey, *pPubKeyLen);
  655. pPubKey->magic = RSA1;
  656. pPubKey->bitlen = pExportKey->bitlen;
  657. pPubKey->keylen = (pExportKey->bitlen / 8) + cbTmpLen;
  658. pPubKey->datalen = (pExportKey->bitlen+7)/8 - 1;
  659. pPubKey->pubexp = pExportKey->pubexp;
  660. pbIn = pbBlob + sizeof(EXPORT_PRV_KEY);
  661. pbOut = (PBYTE)pPubKey + sizeof(BSAFE_PUB_KEY);
  662. CopyMemory(pbOut, pbIn, pExportKey->bitlen / 8);
  663. // form the private key
  664. ZeroMemory(pPrvKey, *pPrvKeyLen);
  665. pPrvKey->magic = pExportKey->magic;
  666. pPrvKey->keylen = pPubKey->keylen;
  667. pPrvKey->bitlen = pExportKey->bitlen;
  668. pPrvKey->datalen = pPubKey->datalen;
  669. pPrvKey->pubexp = pExportKey->pubexp;
  670. pbOut = (PBYTE)pPrvKey + sizeof(BSAFE_PRV_KEY);
  671. CopyMemory(pbOut, pbIn, pExportKey->bitlen / 8);
  672. pbOut += pExportKey->bitlen / 8 + cbTmpLen;
  673. pbIn += pExportKey->bitlen / 8;
  674. CopyMemory(pbOut, pbIn, cbHalfModLen);
  675. pbOut += cbHalfModLen + cbHalfTmpLen;
  676. pbIn += cbHalfModLen;
  677. CopyMemory(pbOut, pbIn, cbHalfModLen);
  678. pbOut += cbHalfModLen + cbHalfTmpLen;
  679. pbIn += cbHalfModLen;
  680. CopyMemory(pbOut, pbIn, cbHalfModLen);
  681. pbOut += cbHalfModLen + cbHalfTmpLen;
  682. pbIn += cbHalfModLen;
  683. CopyMemory(pbOut, pbIn, cbHalfModLen);
  684. pbOut += cbHalfModLen + cbHalfTmpLen;
  685. pbIn += cbHalfModLen;
  686. CopyMemory(pbOut, pbIn, cbHalfModLen);
  687. pbOut += cbHalfModLen + cbHalfTmpLen;
  688. pbIn += cbHalfModLen;
  689. CopyMemory(pbOut, pbIn, pExportKey->bitlen / 8);
  690. *pPubKeyLen = cbPub;
  691. *pPrvKeyLen = cbPrv;
  692. return TRUE;
  693. }
  694. /*static*/ BOOL
  695. ValidKeyAlgid(
  696. PNTAGUserList pTmpUser,
  697. ALG_ID Algid)
  698. {
  699. if (ALG_CLASS_HASH == GET_ALG_CLASS(Algid))
  700. return FALSE;
  701. return IsLegalAlgorithm(g_AlgTables[pTmpUser->dwCspTypeId],
  702. Algid, NULL);
  703. }
  704. #ifdef USE_SGC
  705. /*
  706. - GetSGCDefaultKeyLength
  707. -
  708. * Purpose:
  709. * Returns the default key size in pcbKey.
  710. *
  711. * Parameters:
  712. * IN Algid - For the key to be created
  713. * OUT pcbKey - Size of the key in bytes to generate
  714. * OUT pfPubKey- TRUE if the Algid is a pub key
  715. *
  716. * Returns: TRUE on success, FALSE on failure.
  717. */
  718. /*static*/ BOOL
  719. GetSGCDefaultKeyLength(
  720. IN ALG_ID Algid,
  721. OUT DWORD *pcbKey,
  722. OUT BOOL *pfPubKey)
  723. {
  724. BOOL fRet = FALSE;
  725. *pfPubKey = FALSE;
  726. // determine which crypt algorithm is to be used
  727. switch (Algid)
  728. {
  729. #ifdef CSP_USE_SSL3
  730. case CALG_SSL3_MASTER:
  731. case CALG_TLS1_MASTER:
  732. *pcbKey = SSL3_MASTER_KEYSIZE;
  733. break;
  734. case CALG_PCT1_MASTER:
  735. *pcbKey = PCT1_MASTER_KEYSIZE;
  736. break;
  737. case CALG_SSL2_MASTER:
  738. *pcbKey = SSL2_MASTER_KEYSIZE;
  739. break;
  740. #endif
  741. case CALG_RSA_KEYX:
  742. *pcbKey = SGC_RSA_DEF_EXCH_MODLEN;
  743. *pfPubKey = TRUE;
  744. break;
  745. default:
  746. goto ErrorExit;
  747. }
  748. fRet = TRUE;
  749. ErrorExit:
  750. return fRet;
  751. }
  752. #endif
  753. /*
  754. - GetDefaultKeyLength
  755. -
  756. * Purpose:
  757. * Returns the default key size in pcbKey.
  758. *
  759. * Parameters:
  760. * IN pTmpUser- The context info
  761. * IN Algid - For the key to be created
  762. * OUT pcbKey - Size of the key in bytes to generate
  763. * OUT pfPubKey- TRUE if the Algid is a pub key
  764. *
  765. * Returns: TRUE on success, FALSE on failure.
  766. */
  767. /*static*/ BOOL
  768. GetDefaultKeyLength(
  769. IN PNTAGUserList pTmpUser,
  770. IN ALG_ID Algid,
  771. OUT DWORD *pcbKey,
  772. OUT BOOL *pfPubKey)
  773. {
  774. BOOL fRet = FALSE;
  775. DWORD cbits;
  776. *pfPubKey = FALSE;
  777. // determine which crypt algorithm is to be used
  778. switch (Algid)
  779. {
  780. #ifdef CSP_USE_SSL3
  781. case CALG_SSL3_MASTER:
  782. case CALG_TLS1_MASTER:
  783. *pcbKey = SSL3_MASTER_KEYSIZE;
  784. break;
  785. case CALG_PCT1_MASTER:
  786. *pcbKey = PCT1_MASTER_KEYSIZE;
  787. break;
  788. case CALG_SSL2_MASTER:
  789. *pcbKey = SSL2_MASTER_KEYSIZE;
  790. break;
  791. #endif
  792. case CALG_RSA_KEYX:
  793. case CALG_RSA_SIGN:
  794. *pfPubKey = TRUE;
  795. // Fall through intentionally.
  796. default:
  797. if (!GetDefaultLength(g_AlgTables[pTmpUser->dwCspTypeId],
  798. Algid, NULL, &cbits))
  799. goto ErrorExit;
  800. *pcbKey = cbits / 8;
  801. }
  802. fRet = TRUE;
  803. ErrorExit:
  804. return fRet;
  805. }
  806. /*
  807. - CheckKeyLength
  808. -
  809. * Purpose:
  810. * Checks the settable key length and if it is OK then
  811. * returns that as the size of key to use (pcbKey). If
  812. * no key length is in dwFlags then the default key size
  813. * is returned (pcbKey). If a settable key size is
  814. * specified but is not legal then a failure occurs.
  815. *
  816. * Parameters:
  817. * IN Algid - For the key to be created
  818. * IN dwFlags - Flag value with possible key size
  819. * OUT pcbKey - Size of the key in bytes to generate
  820. * OUT pfPubKey- TRUE if the Algid is a pub key
  821. *
  822. * Returns: A DWORD status code.
  823. */
  824. /*static*/ DWORD
  825. CheckKeyLength(
  826. IN PNTAGUserList pTmpUser,
  827. IN ALG_ID Algid,
  828. IN DWORD dwFlags,
  829. OUT DWORD *pcbKey,
  830. OUT BOOL *pfPubKey)
  831. {
  832. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  833. DWORD cBits;
  834. DWORD cbKey = 0;
  835. cBits = dwFlags >> 16;
  836. if (cBits)
  837. {
  838. // settable key sizes must be divisible by 8 (by bytes)
  839. if (0 != (cBits % 8))
  840. {
  841. dwReturn = (DWORD)NTE_BAD_FLAGS;
  842. goto ErrorExit;
  843. }
  844. // check if requested size is legal
  845. cbKey = cBits / 8;
  846. #ifdef USE_SGC
  847. if ((PROV_RSA_SCHANNEL == pTmpUser->dwProvType) &&
  848. (0 != pTmpUser->dwSGCFlags))
  849. {
  850. if (!FIsLegalSGCKeySize(Algid, cbKey,
  851. FALSE, TRUE, pfPubKey))
  852. {
  853. dwReturn = (DWORD)NTE_BAD_FLAGS;
  854. goto ErrorExit;
  855. }
  856. }
  857. else
  858. #endif
  859. {
  860. if (!FIsLegalKeySize(pTmpUser->dwCspTypeId,
  861. Algid, cbKey,
  862. FALSE, pfPubKey))
  863. {
  864. dwReturn = (DWORD)NTE_BAD_FLAGS;
  865. goto ErrorExit;
  866. }
  867. }
  868. *pcbKey = cbKey;
  869. }
  870. else
  871. {
  872. #ifdef USE_SGC
  873. if ((PROV_RSA_SCHANNEL == pTmpUser->dwProvType) &&
  874. (0 != pTmpUser->dwSGCFlags))
  875. {
  876. if (!GetSGCDefaultKeyLength(Algid, pcbKey, pfPubKey))
  877. {
  878. dwReturn = (DWORD)NTE_BAD_ALGID;
  879. goto ErrorExit;
  880. }
  881. }
  882. else
  883. #endif
  884. {
  885. if (!GetDefaultKeyLength(pTmpUser, Algid, pcbKey, pfPubKey))
  886. {
  887. dwReturn = (DWORD)NTE_BAD_ALGID;
  888. goto ErrorExit;
  889. }
  890. }
  891. }
  892. dwReturn = ERROR_SUCCESS;
  893. ErrorExit:
  894. return dwReturn;
  895. }
  896. #ifdef USE_SGC
  897. /*
  898. - CheckSGCSimpleForExport
  899. -
  900. * Purpose:
  901. * Check if the SGC key values in the context against the
  902. * passed in values to see if an simple blob export with
  903. * this key is allowed.
  904. *
  905. *
  906. * Parameters:
  907. * IN hUID - Handle to a CSP
  908. * IN Algid - Algorithm identifier
  909. * IN dwFlags - Flags values
  910. * OUT phKey - Handle to a generated key
  911. *
  912. * Returns:
  913. */
  914. /*static*/ BOOL
  915. CheckSGCSimpleForExport(
  916. IN PNTAGUserList pTmpUser,
  917. IN BSAFE_PUB_KEY *pBsafePubKey)
  918. {
  919. BOOL fRet = FALSE;
  920. BYTE *pb;
  921. pb = ((BYTE*)pBsafePubKey) + sizeof(BSAFE_PUB_KEY);
  922. if (((pBsafePubKey->bitlen / 8) != pTmpUser->cbSGCKeyMod)
  923. || (pBsafePubKey->pubexp != pTmpUser->dwSGCKeyExpo)
  924. || (0 != memcmp(pb, pTmpUser->pbSGCKeyMod, pTmpUser->cbSGCKeyMod)))
  925. {
  926. goto ErrorExit;
  927. }
  928. fRet = TRUE;
  929. ErrorExit:
  930. return fRet;
  931. }
  932. #endif
  933. /*
  934. - CPGenKey
  935. -
  936. * Purpose:
  937. * Generate cryptographic keys
  938. *
  939. *
  940. * Parameters:
  941. * IN hUID - Handle to a CSP
  942. * IN Algid - Algorithm identifier
  943. * IN dwFlags - Flags values
  944. * OUT phKey - Handle to a generated key
  945. *
  946. * Returns:
  947. */
  948. BOOL WINAPI
  949. CPGenKey(
  950. IN HCRYPTPROV hUID,
  951. IN ALG_ID Algid,
  952. IN DWORD dwFlags,
  953. OUT HCRYPTKEY * phKey)
  954. {
  955. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  956. PNTAGUserList pTmpUser;
  957. PNTAGKeyList pTmpKey = NULL;
  958. DWORD dwRights = 0;
  959. BYTE rgbRandom[MAX_KEY_SIZE];
  960. int localAlgid;
  961. DWORD cbKey;
  962. BOOL fPubKey = FALSE;
  963. BOOL fRet;
  964. DWORD dwSts;
  965. EntryPoint
  966. if ((dwFlags & ~(CRYPT_EXPORTABLE | CRYPT_USER_PROTECTED |
  967. CRYPT_CREATE_SALT | CRYPT_NO_SALT |
  968. KEY_LENGTH_MASK | CRYPT_SGCKEY | CRYPT_ARCHIVABLE)) != 0)
  969. {
  970. dwReturn = (DWORD)NTE_BAD_FLAGS;
  971. goto ErrorExit;
  972. }
  973. switch (Algid)
  974. {
  975. case AT_KEYEXCHANGE:
  976. localAlgid = CALG_RSA_KEYX;
  977. break;
  978. case AT_SIGNATURE:
  979. localAlgid = CALG_RSA_SIGN;
  980. break;
  981. default:
  982. if (0 != (dwFlags & CRYPT_ARCHIVABLE))
  983. {
  984. dwReturn = (DWORD)NTE_BAD_FLAGS;
  985. goto ErrorExit;
  986. }
  987. localAlgid = Algid;
  988. break;
  989. }
  990. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  991. if (NULL == pTmpUser)
  992. {
  993. dwReturn = (DWORD)NTE_BAD_UID;
  994. goto ErrorExit;
  995. }
  996. if ((CRYPT_USER_PROTECTED & dwFlags) && (CRYPT_VERIFYCONTEXT & pTmpUser->Rights))
  997. {
  998. dwReturn = (DWORD)NTE_SILENT_CONTEXT;
  999. goto ErrorExit;
  1000. }
  1001. if (!ValidKeyAlgid(pTmpUser, localAlgid))
  1002. {
  1003. dwReturn = (DWORD)NTE_BAD_ALGID;
  1004. goto ErrorExit;
  1005. }
  1006. // check if the size of the key is set in the dwFlags parameter
  1007. dwSts = CheckKeyLength(pTmpUser, localAlgid, dwFlags, &cbKey, &fPubKey);
  1008. if (ERROR_SUCCESS != dwSts)
  1009. {
  1010. dwReturn = dwSts;
  1011. goto ErrorExit;
  1012. }
  1013. if (fPubKey)
  1014. {
  1015. dwSts = ReGenKey(hUID,
  1016. dwFlags,
  1017. (localAlgid == CALG_RSA_KEYX)
  1018. ? NTPK_USE_EXCH
  1019. : NTPK_USE_SIG,
  1020. phKey,
  1021. cbKey * 8);
  1022. if (ERROR_SUCCESS != dwSts)
  1023. {
  1024. dwReturn = dwSts;
  1025. goto ErrorExit;
  1026. }
  1027. }
  1028. else
  1029. {
  1030. // Force the full key lengths on DES algorithms.
  1031. if (CALG_DES == localAlgid)
  1032. cbKey = DES_KEYSIZE;
  1033. else if (CALG_3DES_112 == localAlgid)
  1034. cbKey = DES2_KEYSIZE;
  1035. else if (CALG_3DES == localAlgid)
  1036. cbKey = DES3_KEYSIZE;
  1037. // generate the random key
  1038. dwSts = FIPS186GenRandom(&pTmpUser->hRNGDriver,
  1039. &pTmpUser->ContInfo.pbRandom,
  1040. &pTmpUser->ContInfo.ContLens.cbRandom,
  1041. rgbRandom, cbKey);
  1042. if (ERROR_SUCCESS != dwSts)
  1043. {
  1044. dwReturn = dwSts; // NTE_FAIL
  1045. goto ErrorExit;
  1046. }
  1047. if ((CALG_DES == localAlgid) || (CALG_3DES_112 == localAlgid) ||
  1048. (CALG_3DES == localAlgid))
  1049. {
  1050. if (dwFlags & CRYPT_CREATE_SALT)
  1051. {
  1052. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1053. goto ErrorExit;
  1054. }
  1055. }
  1056. #ifdef CSP_USE_SSL3
  1057. else if (CALG_SSL3_MASTER == localAlgid)
  1058. {
  1059. // set the first byte to 0x03 and the second to 0x00
  1060. rgbRandom[0] = 0x03;
  1061. rgbRandom[1] = 0x00;
  1062. }
  1063. else if (CALG_TLS1_MASTER == localAlgid)
  1064. {
  1065. // set the first byte to 0x03 and the second to 0x01
  1066. rgbRandom[0] = 0x03;
  1067. rgbRandom[1] = 0x01;
  1068. }
  1069. #endif
  1070. // check if the key is CRYPT_EXPORTABLE
  1071. if (dwFlags & CRYPT_EXPORTABLE)
  1072. dwRights = CRYPT_EXPORTABLE;
  1073. dwSts = MakeNewKey(localAlgid, dwRights, cbKey, hUID, rgbRandom,
  1074. FALSE, FALSE, &pTmpKey);
  1075. if (ERROR_SUCCESS != dwSts)
  1076. {
  1077. dwReturn = dwSts;
  1078. goto ErrorExit;
  1079. }
  1080. if (dwFlags & CRYPT_CREATE_SALT)
  1081. {
  1082. if ((POLICY_MS_DEF == pTmpUser->dwCspTypeId)
  1083. || (POLICY_MS_STRONG == pTmpUser->dwCspTypeId))
  1084. {
  1085. pTmpKey->cbSaltLen = DEFAULT_WEAK_SALT_LENGTH;
  1086. }
  1087. else
  1088. {
  1089. pTmpKey->cbSaltLen = DEFAULT_STRONG_SALT_LENGTH;
  1090. }
  1091. dwSts = FIPS186GenRandom(&pTmpUser->hRNGDriver,
  1092. &pTmpUser->ContInfo.pbRandom,
  1093. &pTmpUser->ContInfo.ContLens.cbRandom,
  1094. pTmpKey->rgbSalt, pTmpKey->cbSaltLen);
  1095. if (ERROR_SUCCESS != dwSts)
  1096. {
  1097. dwReturn = dwSts; // NTE_FAIL
  1098. goto ErrorExit;
  1099. }
  1100. }
  1101. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  1102. if (ERROR_SUCCESS != dwSts)
  1103. {
  1104. dwReturn = dwSts;
  1105. goto ErrorExit;
  1106. }
  1107. // if 40bit key + no mention of salt, set zeroized salt for RSABase compatibility
  1108. if ((5 == cbKey) && (!(dwFlags & CRYPT_NO_SALT)) &&
  1109. (!(dwFlags & CRYPT_CREATE_SALT)) &&
  1110. (CALG_SSL3_MASTER != Algid) && (CALG_TLS1_MASTER != Algid) &&
  1111. (CALG_PCT1_MASTER != Algid) && (CALG_SSL2_MASTER != Algid))
  1112. {
  1113. dwSts = MakeKeyRSABaseCompatible(hUID, *phKey);
  1114. if (ERROR_SUCCESS != dwSts)
  1115. {
  1116. dwReturn = dwSts;
  1117. goto ErrorExit;
  1118. }
  1119. }
  1120. }
  1121. dwReturn = ERROR_SUCCESS;
  1122. ErrorExit:
  1123. fRet = (ERROR_SUCCESS == dwReturn);
  1124. if (!fRet)
  1125. {
  1126. if (pTmpKey)
  1127. FreeNewKey(pTmpKey);
  1128. SetLastError(dwReturn);
  1129. }
  1130. return fRet;
  1131. }
  1132. /*
  1133. - CPDeriveKey
  1134. -
  1135. * Purpose:
  1136. * Derive cryptographic keys from base data
  1137. *
  1138. *
  1139. * Parameters:
  1140. * IN hUID - Handle to a CSP
  1141. * IN Algid - Algorithm identifier
  1142. * IN hBaseData - Handle to hash of base data
  1143. * IN dwFlags - Flags values
  1144. * OUT phKey - Handle to a generated key
  1145. *
  1146. * Returns:
  1147. */
  1148. BOOL WINAPI
  1149. CPDeriveKey(
  1150. IN HCRYPTPROV hUID,
  1151. IN ALG_ID Algid,
  1152. IN HCRYPTHASH hBaseData,
  1153. IN DWORD dwFlags,
  1154. OUT HCRYPTKEY * phKey)
  1155. {
  1156. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1157. PNTAGUserList pTmpUser = NULL;
  1158. PNTAGKeyList pTmpKey = NULL;
  1159. DWORD dwRights = 0;
  1160. BYTE rgbRandom[MAX_KEY_SIZE];
  1161. BYTE rgbBaseVal[MAX_KEY_SIZE];
  1162. HCRYPTHASH h1 = 0;
  1163. HCRYPTHASH h2 = 0;
  1164. BYTE rgbBuff1[64];
  1165. BYTE rgbBuff2[64];
  1166. BYTE rgbHash1[NT_HASH_BYTES];
  1167. BYTE rgbHash2[NT_HASH_BYTES];
  1168. DWORD cb1;
  1169. DWORD cb2;
  1170. DWORD i;
  1171. PNTAGHashList pTmpHash;
  1172. DWORD temp;
  1173. BOOL fPubKey = FALSE;
  1174. DWORD cbKey;
  1175. BOOL fRet;
  1176. DWORD dwSts;
  1177. EntryPoint
  1178. if ((dwFlags & ~(CRYPT_EXPORTABLE |
  1179. CRYPT_CREATE_SALT | CRYPT_NO_SALT | CRYPT_SERVER |
  1180. KEY_LENGTH_MASK)) != 0)
  1181. {
  1182. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1183. goto ErrorExit;
  1184. }
  1185. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  1186. if (NULL == pTmpUser)
  1187. {
  1188. dwReturn = (DWORD)NTE_BAD_UID;
  1189. goto ErrorExit;
  1190. }
  1191. if (!ValidKeyAlgid(pTmpUser, Algid))
  1192. {
  1193. dwReturn = (DWORD)NTE_BAD_ALGID;
  1194. goto ErrorExit;
  1195. }
  1196. dwSts = NTLValidate(hBaseData, hUID, HASH_HANDLE, &pTmpHash);
  1197. if (ERROR_SUCCESS != dwSts)
  1198. {
  1199. // NTLValidate doesn't know what error to set
  1200. // so it set NTE_FAIL -- fix it up.
  1201. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_HASH : dwSts;
  1202. goto ErrorExit;
  1203. }
  1204. #ifdef CSP_USE_SSL3
  1205. // if the hash is for secure channel usage then go to that derive function
  1206. if (CALG_SCHANNEL_MASTER_HASH == pTmpHash->Algid)
  1207. {
  1208. dwReturn = SecureChannelDeriveKey(pTmpUser, pTmpHash, Algid,
  1209. dwFlags, phKey);
  1210. goto ErrorExit;
  1211. }
  1212. #endif // CSP_USE_SSL3
  1213. // check if the size of the key is set in the dwFlags parameter
  1214. dwSts = CheckKeyLength(pTmpUser, Algid, dwFlags, &cbKey, &fPubKey);
  1215. if (ERROR_SUCCESS != dwSts)
  1216. {
  1217. dwReturn = dwSts;
  1218. goto ErrorExit;
  1219. }
  1220. // Force the full key lengths on DES algorithms.
  1221. if (CALG_DES == Algid)
  1222. cbKey = DES_KEYSIZE;
  1223. else if (CALG_3DES_112 == Algid)
  1224. cbKey = DES2_KEYSIZE;
  1225. else if (CALG_3DES == Algid)
  1226. cbKey = DES3_KEYSIZE;
  1227. if (fPubKey)
  1228. {
  1229. dwReturn = (DWORD)NTE_BAD_ALGID;
  1230. goto ErrorExit;
  1231. }
  1232. if (pTmpHash->HashFlags & HF_VALUE_SET)
  1233. {
  1234. dwReturn = (DWORD)NTE_BAD_HASH;
  1235. goto ErrorExit;
  1236. }
  1237. memset(rgbBaseVal, 0, MAX_KEY_SIZE);
  1238. temp = MAX_KEY_SIZE;
  1239. if (!CPGetHashParam(hUID, hBaseData, HP_HASHVAL, rgbBaseVal, &temp, 0))
  1240. {
  1241. dwReturn = GetLastError();
  1242. goto ErrorExit;
  1243. }
  1244. #ifdef CSP_USE_3DES
  1245. if (CALG_3DES == Algid)
  1246. {
  1247. // the hash value is not long enough so we must expand it
  1248. if (!CPCreateHash(hUID, pTmpHash->Algid, 0, 0, &h1))
  1249. {
  1250. dwReturn = GetLastError();
  1251. goto ErrorExit;
  1252. }
  1253. if (!CPCreateHash(hUID, pTmpHash->Algid, 0, 0, &h2))
  1254. {
  1255. dwReturn = GetLastError();
  1256. goto ErrorExit;
  1257. }
  1258. // set up the two buffers to be hashed
  1259. memset(rgbBuff1, 0x36, sizeof(rgbBuff1));
  1260. memset(rgbBuff2, 0x5C, sizeof(rgbBuff2));
  1261. for (i=0;i<temp;i++)
  1262. {
  1263. rgbBuff1[i] ^= rgbBaseVal[i];
  1264. rgbBuff2[i] ^= rgbBaseVal[i];
  1265. }
  1266. // hash the two buffers
  1267. if (!CPHashData(hUID, h1, rgbBuff1, sizeof(rgbBuff1), 0))
  1268. {
  1269. dwReturn = GetLastError();
  1270. goto ErrorExit;
  1271. }
  1272. if (!CPHashData(hUID, h2, rgbBuff2, sizeof(rgbBuff2), 0))
  1273. {
  1274. dwReturn = GetLastError();
  1275. goto ErrorExit;
  1276. }
  1277. // finish the hashes and copy them into BaseVal
  1278. memset(rgbHash1, 0, sizeof(rgbHash1));
  1279. cb1 = sizeof(rgbHash1);
  1280. if (!CPGetHashParam(hUID, h1, HP_HASHVAL, rgbHash1, &cb1, 0))
  1281. {
  1282. dwReturn = GetLastError();
  1283. goto ErrorExit;
  1284. }
  1285. memcpy(rgbBaseVal, rgbHash1, cb1);
  1286. memset(rgbHash2, 0, sizeof(rgbHash2));
  1287. cb2 = sizeof(rgbHash2);
  1288. if (!CPGetHashParam(hUID, h2, HP_HASHVAL, rgbHash2, &cb2, 0))
  1289. {
  1290. dwReturn = GetLastError();
  1291. goto ErrorExit;
  1292. }
  1293. memcpy(rgbBaseVal + cb1, rgbHash2, cb2);
  1294. }
  1295. #endif
  1296. memcpy(rgbRandom, rgbBaseVal, cbKey);
  1297. // check if the key is CRYPT_EXPORTABLE
  1298. if (dwFlags & CRYPT_EXPORTABLE)
  1299. dwRights = CRYPT_EXPORTABLE;
  1300. dwSts = MakeNewKey(Algid, dwRights, cbKey, hUID, rgbRandom,
  1301. FALSE, FALSE, &pTmpKey);
  1302. if (ERROR_SUCCESS != dwSts)
  1303. {
  1304. dwReturn = dwSts;
  1305. goto ErrorExit;
  1306. }
  1307. if (dwFlags & CRYPT_CREATE_SALT)
  1308. {
  1309. if ((POLICY_MS_DEF == pTmpUser->dwCspTypeId)
  1310. || (POLICY_MS_STRONG == pTmpUser->dwCspTypeId))
  1311. {
  1312. pTmpKey->cbSaltLen = DEFAULT_WEAK_SALT_LENGTH;
  1313. }
  1314. else
  1315. {
  1316. pTmpKey->cbSaltLen = DEFAULT_STRONG_SALT_LENGTH;
  1317. }
  1318. memcpy(pTmpKey->rgbSalt, rgbBaseVal+cbKey, pTmpKey->cbSaltLen);
  1319. }
  1320. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  1321. if (ERROR_SUCCESS != dwSts)
  1322. {
  1323. dwReturn = dwSts;
  1324. goto ErrorExit;
  1325. }
  1326. // if 40bit key + no mention of salt, set zeroized salt for RSABase
  1327. // compatibility
  1328. if ((5 == cbKey) && (!(dwFlags & CRYPT_NO_SALT)) &&
  1329. (!(dwFlags & CRYPT_CREATE_SALT)))
  1330. {
  1331. dwSts = MakeKeyRSABaseCompatible(hUID, *phKey);
  1332. if (ERROR_SUCCESS != dwSts)
  1333. {
  1334. dwReturn = dwSts;
  1335. goto ErrorExit;
  1336. }
  1337. }
  1338. dwReturn = ERROR_SUCCESS;
  1339. ErrorExit:
  1340. fRet = (ERROR_SUCCESS == dwReturn);
  1341. if (pTmpUser && h1)
  1342. CPDestroyHash(hUID, h1);
  1343. if (pTmpUser && h2)
  1344. CPDestroyHash(hUID, h2);
  1345. if (!fRet)
  1346. {
  1347. if (NULL != pTmpKey)
  1348. FreeNewKey(pTmpKey);
  1349. SetLastError(dwReturn);
  1350. }
  1351. return fRet;
  1352. }
  1353. /*static*/ DWORD
  1354. ExportOpaqueBlob(
  1355. PNTAGKeyList pKey,
  1356. BYTE *pbData,
  1357. DWORD *pcbData)
  1358. {
  1359. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1360. DWORD cb = 0;
  1361. PNTAGPackedKeyList pPackedKey;
  1362. // make sure the key is a symmetric key
  1363. if ((CALG_RSA_SIGN == pKey->Algid) || (CALG_RSA_KEYX == pKey->Algid))
  1364. {
  1365. dwReturn = (DWORD)NTE_BAD_KEY;
  1366. goto ErrorExit;
  1367. }
  1368. // calculate the length of the blob
  1369. cb = sizeof(BLOBHEADER) +
  1370. sizeof(NTAGPackedKeyList) +
  1371. pKey->cbKeyLen +
  1372. pKey->cbDataLen;
  1373. if (pbData == NULL || *pcbData < cb)
  1374. {
  1375. *pcbData = cb;
  1376. if (pbData == NULL)
  1377. dwReturn = ERROR_SUCCESS;
  1378. else
  1379. dwReturn = ERROR_MORE_DATA;
  1380. goto ErrorExit;
  1381. }
  1382. // set up the blob
  1383. pPackedKey = (PNTAGPackedKeyList)(pbData + sizeof(BLOBHEADER));
  1384. memset(pPackedKey, 0, sizeof(NTAGPackedKeyList));
  1385. pPackedKey->Algid = pKey->Algid;
  1386. pPackedKey->Rights = pKey->Rights;
  1387. memcpy(pPackedKey->IV, pKey->IV, sizeof(pKey->IV));
  1388. memcpy(pPackedKey->FeedBack, pKey->FeedBack, sizeof(pKey->FeedBack));
  1389. pPackedKey->InProgress = pKey->InProgress;
  1390. pPackedKey->cbSaltLen = pKey->cbSaltLen;
  1391. memcpy(pPackedKey->rgbSalt, pKey->rgbSalt, sizeof(pKey->rgbSalt));
  1392. pPackedKey->Padding = pKey->Padding;
  1393. pPackedKey->Mode = pKey->Mode;
  1394. pPackedKey->ModeBits = pKey->ModeBits;
  1395. pPackedKey->Permissions = pKey->Permissions;
  1396. pPackedKey->EffectiveKeyLen = pKey->EffectiveKeyLen;
  1397. pPackedKey->dwBlockLen = pKey->dwBlockLen;
  1398. if (pKey->pKeyValue)
  1399. {
  1400. memcpy((PBYTE)pPackedKey + sizeof(NTAGPackedKeyList),
  1401. pKey->pKeyValue,
  1402. pKey->cbKeyLen);
  1403. pPackedKey->cbKeyLen = pKey->cbKeyLen;
  1404. }
  1405. if(pKey->pData)
  1406. {
  1407. memcpy((PBYTE)pPackedKey + sizeof(NTAGPackedKeyList) + pPackedKey->cbKeyLen,
  1408. pKey->pData,
  1409. pKey->cbDataLen);
  1410. pPackedKey->cbDataLen = pKey->cbDataLen;
  1411. }
  1412. *pcbData = cb;
  1413. dwReturn = ERROR_SUCCESS;
  1414. ErrorExit:
  1415. return dwReturn;
  1416. }
  1417. /*
  1418. - GetRC4KeyForSymWrap
  1419. -
  1420. * Purpose:
  1421. * RC4 or more precisely stream ciphers are not supported by the CMS spec
  1422. * on symmetric key wrapping so we had to do something proprietary since
  1423. * we want to support RC4 for applications other than SMIME
  1424. *
  1425. *
  1426. * Parameters:
  1427. * IN pTmpUser - Pointer to the context
  1428. * IN pbSalt - Pointer to the 8 byte salt buffer
  1429. * IN pKey - Pointer to the orignial key
  1430. * OUT ppNewKey - Pointer to a pointer to the new key
  1431. */
  1432. /*static*/ DWORD
  1433. GetRC4KeyForSymWrap(
  1434. IN BYTE *pbSalt,
  1435. IN PNTAGKeyList pKey,
  1436. OUT PNTAGKeyList *ppNewKey)
  1437. {
  1438. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1439. DWORD dwSts;
  1440. // duplicate the key
  1441. dwSts = CopyKey(pKey, ppNewKey);
  1442. if (ERROR_SUCCESS != dwSts)
  1443. {
  1444. dwReturn = dwSts;
  1445. goto ErrorExit;
  1446. }
  1447. // set the value as salt + current salt
  1448. (*ppNewKey)->cbSaltLen += 8;
  1449. memcpy((*ppNewKey)->rgbSalt + ((*ppNewKey)->cbSaltLen - 8), pbSalt, 8);
  1450. dwSts = InflateKey(*ppNewKey);
  1451. if (ERROR_SUCCESS != dwSts)
  1452. {
  1453. dwReturn = dwSts;
  1454. goto ErrorExit;
  1455. }
  1456. dwReturn = ERROR_SUCCESS;
  1457. ErrorExit:
  1458. return dwReturn;
  1459. }
  1460. /*
  1461. - GetSymmetricKeyChecksum
  1462. -
  1463. * Purpose:
  1464. * Calculates the checksum for a symmetric key which is to be
  1465. * wrapped with another symmetric key. This should meet the
  1466. * CMS specification
  1467. *
  1468. *
  1469. * Parameters:
  1470. * IN pKey - Pointer to the key
  1471. * OUT pbChecksum - Pointer to the 8 byte checksum
  1472. */
  1473. /*static*/ void
  1474. GetSymmetricKeyChecksum(
  1475. IN BYTE *pbKey,
  1476. IN DWORD cbKey,
  1477. OUT BYTE *pbChecksum)
  1478. {
  1479. A_SHA_CTX SHACtx;
  1480. BYTE rgb[A_SHA_DIGEST_LEN];
  1481. A_SHAInit(&SHACtx);
  1482. A_SHAUpdate(&SHACtx, pbKey, cbKey);
  1483. A_SHAFinal(&SHACtx, rgb);
  1484. memcpy(pbChecksum, rgb, 8);
  1485. }
  1486. /*
  1487. - WrapSymKey
  1488. -
  1489. * Purpose:
  1490. * Wrap a symmetric key with another symmetric key. This should
  1491. * meet the CMS specification for symmetric key wrapping.
  1492. *
  1493. * Parameters:
  1494. * IN pTmpUser - Pointer to the user context
  1495. * IN pKey - Pointer to the key to be wrapped
  1496. * IN pWrapKey - Pointer to the key to be used for wrapping
  1497. * IN OUT pbBlob - Pointer to the resulting blob (may be NULL
  1498. * to get the length)
  1499. * IN OUT pcbBlob - Pointer to the length of the blob buffer
  1500. */
  1501. /*static*/ DWORD
  1502. WrapSymKey(
  1503. IN PNTAGUserList pTmpUser,
  1504. IN PNTAGKeyList pKey,
  1505. IN PNTAGKeyList pWrapKey,
  1506. IN OUT BYTE *pbBlob,
  1507. IN OUT DWORD *pcbBlob)
  1508. {
  1509. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1510. DWORD cb = 0;
  1511. DWORD cbIndex = 0;
  1512. DWORD cbPad = 0;
  1513. BLOBHEADER *pBlobHdr;
  1514. ALG_ID *pAlgid;
  1515. BYTE rgbTmp1[49]; // 1 length + 8 padding + 8 checksum + 8 IV + 24 max key
  1516. BYTE rgbTmp2[49]; // 1 length + 8 padding + 8 checksum + 8 IV + 24 max key
  1517. BYTE rgbIV[8];
  1518. PNTAGKeyList pLocalWrapKey = NULL;
  1519. BOOL fAlloc = FALSE;
  1520. DWORD i;
  1521. DWORD dwSts;
  1522. memset(rgbTmp1, 0, sizeof(rgbTmp1));
  1523. memset(rgbTmp2, 0, sizeof(rgbTmp2));
  1524. memset(rgbIV, 0, sizeof(rgbIV));
  1525. // both keys must be supported symmetric keys
  1526. if (UnsupportedSymKey(pKey) || UnsupportedSymKey(pWrapKey))
  1527. {
  1528. dwReturn = (DWORD)NTE_BAD_KEY;
  1529. goto ErrorExit;
  1530. }
  1531. #ifdef CSP_USE_AES
  1532. // For now, punt on supporting AES algs in this scenario
  1533. if (CALG_AES_128 == pWrapKey->Algid ||
  1534. CALG_AES_192 == pWrapKey->Algid ||
  1535. CALG_AES_256 == pWrapKey->Algid ||
  1536. CALG_AES_128 == pKey->Algid ||
  1537. CALG_AES_192 == pKey->Algid ||
  1538. CALG_AES_256 == pKey->Algid)
  1539. {
  1540. dwReturn = (DWORD)NTE_BAD_KEY;
  1541. goto ErrorExit;
  1542. }
  1543. #endif
  1544. if ((!FIsLegalKey(pTmpUser, pKey, FALSE)) ||
  1545. (!FIsLegalKey(pTmpUser, pWrapKey, FALSE)))
  1546. {
  1547. dwReturn = (DWORD)NTE_BAD_KEY;
  1548. goto ErrorExit;
  1549. }
  1550. // Check if we should do an auto-inflate
  1551. if (pWrapKey->pData == NULL)
  1552. {
  1553. dwSts = InflateKey(pWrapKey);
  1554. if (ERROR_SUCCESS != dwSts)
  1555. {
  1556. dwReturn = dwSts;
  1557. goto ErrorExit;
  1558. }
  1559. }
  1560. // calculate how long the encrypted data is going to be.
  1561. if ((CALG_RC4 == pKey->Algid) || (CALG_RC2 == pKey->Algid)) // variable key lengths
  1562. {
  1563. // 1 byte for length, up to 8 bytes for pad and 8 bytes
  1564. // for the checksum and 8 bytes for the IV
  1565. cbPad = 8 - ((pKey->cbKeyLen + 1) % 8);
  1566. cb += pKey->cbKeyLen + 9 + cbPad + 8;
  1567. // place the length in the buffer
  1568. rgbTmp1[0] = (BYTE)pKey->cbKeyLen;
  1569. cbIndex += 1;
  1570. }
  1571. else
  1572. {
  1573. // up to 8 bytes for salt and 8 bytes for the checksum and 8 bytes
  1574. // for the IV
  1575. cb += pKey->cbKeyLen + 16;
  1576. }
  1577. // check if just looking for a length
  1578. if (NULL == pbBlob)
  1579. {
  1580. *pcbBlob = cb + sizeof(BLOBHEADER) + sizeof(ALG_ID);
  1581. dwReturn = ERROR_SUCCESS;
  1582. goto ErrorExit;
  1583. }
  1584. else if (*pcbBlob < (cb + sizeof(BLOBHEADER) + sizeof(ALG_ID)))
  1585. {
  1586. *pcbBlob = cb + sizeof(BLOBHEADER) + sizeof(ALG_ID);
  1587. dwReturn = ERROR_MORE_DATA;
  1588. goto ErrorExit;
  1589. }
  1590. // copy the key data
  1591. memcpy(rgbTmp1 + cbIndex, pKey->pKeyValue, pKey->cbKeyLen);
  1592. cbIndex += pKey->cbKeyLen;
  1593. // generate random pad
  1594. if (cbPad)
  1595. {
  1596. dwSts = FIPS186GenRandom(&pTmpUser->hRNGDriver,
  1597. &pTmpUser->ContInfo.pbRandom,
  1598. &pTmpUser->ContInfo.ContLens.cbRandom,
  1599. rgbTmp1 + cbIndex, cbPad);
  1600. if (ERROR_SUCCESS != dwSts)
  1601. {
  1602. dwReturn = dwSts;
  1603. goto ErrorExit;
  1604. }
  1605. cbIndex += cbPad;
  1606. }
  1607. // get the checksum
  1608. GetSymmetricKeyChecksum(rgbTmp1, cbIndex, rgbTmp1 + cbIndex);
  1609. cbIndex += 8;
  1610. dwSts = FIPS186GenRandom(&pTmpUser->hRNGDriver,
  1611. &pTmpUser->ContInfo.pbRandom,
  1612. &pTmpUser->ContInfo.ContLens.cbRandom,
  1613. rgbIV, 8);
  1614. if (ERROR_SUCCESS != dwSts)
  1615. {
  1616. dwReturn = dwSts;
  1617. goto ErrorExit;
  1618. }
  1619. // set the IV if the algorithm is not RC4
  1620. if (CALG_RC4 != pWrapKey->Algid)
  1621. {
  1622. memcpy(pWrapKey->IV, rgbIV, 8);
  1623. pWrapKey->InProgress = FALSE;
  1624. pLocalWrapKey = pWrapKey;
  1625. }
  1626. else
  1627. {
  1628. // RC4 ()or more precisely stream ciphers) are not supported by the
  1629. // CMS spec for symmetric key wrapping. Therefore we had to do
  1630. // something proprietary to support RC4 for applications other
  1631. // than SMIME.
  1632. dwSts = GetRC4KeyForSymWrap(rgbIV,
  1633. pWrapKey,
  1634. &pLocalWrapKey);
  1635. if (ERROR_SUCCESS != dwSts)
  1636. {
  1637. dwReturn = dwSts;
  1638. goto ErrorExit;
  1639. }
  1640. fAlloc = TRUE;
  1641. }
  1642. // encrypt the key blob data
  1643. dwSts = SymEncrypt(pLocalWrapKey, FALSE, rgbTmp1, &cbIndex, cbIndex);
  1644. if (ERROR_SUCCESS != dwSts)
  1645. {
  1646. dwReturn = dwSts;
  1647. goto ErrorExit;
  1648. }
  1649. // concatenate the initial ciphertext with the IV
  1650. memcpy(rgbTmp2, rgbIV, 8);
  1651. memcpy(rgbTmp2 + 8, rgbTmp1, cbIndex);
  1652. cbIndex += 8;
  1653. // byte reverse the ciphertext + IV buffer
  1654. for (i = 0; i < cbIndex; i++)
  1655. rgbTmp1[i] = rgbTmp2[cbIndex - (i + 1)];
  1656. // encrypt the key blob data again with the hardcoded IV
  1657. if (CALG_RC4 != pWrapKey->Algid)
  1658. {
  1659. memcpy(pWrapKey->IV, rgbSymmetricKeyWrapIV, 8);
  1660. pWrapKey->InProgress = FALSE;
  1661. }
  1662. else
  1663. {
  1664. if (fAlloc && pLocalWrapKey)
  1665. {
  1666. FreeNewKey(pLocalWrapKey);
  1667. pLocalWrapKey = NULL;
  1668. fAlloc = FALSE;
  1669. }
  1670. // RC4 (or more precisely stream ciphers) are not supported by the
  1671. // CMS spec for symmetric key wrapping. Therefore we had to do
  1672. // something proprietary to support RC4 for applications other
  1673. // than SMIME
  1674. dwSts = GetRC4KeyForSymWrap(rgbSymmetricKeyWrapIV,
  1675. pWrapKey,
  1676. &pLocalWrapKey);
  1677. if (ERROR_SUCCESS != dwSts)
  1678. {
  1679. dwReturn = dwSts;
  1680. goto ErrorExit;
  1681. }
  1682. fAlloc = TRUE;
  1683. }
  1684. dwSts = SymEncrypt(pLocalWrapKey, FALSE, rgbTmp1, &cbIndex, cbIndex);
  1685. if (ERROR_SUCCESS != dwSts)
  1686. {
  1687. dwReturn = dwSts;
  1688. goto ErrorExit;
  1689. }
  1690. // set the header info
  1691. pBlobHdr = (BLOBHEADER*)pbBlob;
  1692. pBlobHdr->aiKeyAlg = pKey->Algid;
  1693. pAlgid = (ALG_ID*)(pbBlob + sizeof(BLOBHEADER));
  1694. *pAlgid = pWrapKey->Algid;
  1695. memcpy(pbBlob + sizeof(BLOBHEADER) + sizeof(ALG_ID),
  1696. rgbTmp1, cbIndex);
  1697. *pcbBlob = cbIndex + sizeof(BLOBHEADER) + sizeof(ALG_ID);
  1698. dwReturn = ERROR_SUCCESS;
  1699. ErrorExit:
  1700. if (fAlloc && pLocalWrapKey)
  1701. FreeNewKey(pLocalWrapKey);
  1702. memset(rgbTmp1, 0, sizeof(rgbTmp1));
  1703. memset(rgbTmp2, 0, sizeof(rgbTmp2));
  1704. memset(rgbIV, 0, sizeof(rgbIV));
  1705. return dwReturn;
  1706. }
  1707. /*
  1708. - UnWrapSymKey
  1709. -
  1710. * Purpose:
  1711. * Unwrap a symmetric key with another symmetric key. This should
  1712. * meet the CMS specification for symmetric key wrapping.
  1713. *
  1714. * Parameters:
  1715. * IN pTmpUser - Pointer to the user context
  1716. * IN pWrapKey - Pointer to the key to be used for unwrapping
  1717. * IN pbBlob - Pointer to the blob to be unwrapped
  1718. * IN cbBlob - The length of the blob buffer
  1719. * OUT phKey - Handle to the unwrapped key
  1720. */
  1721. /*static*/ DWORD
  1722. UnWrapSymKey(
  1723. IN HCRYPTPROV hUID,
  1724. IN PNTAGUserList pTmpUser,
  1725. IN PNTAGKeyList pWrapKey,
  1726. IN BYTE *pbBlob,
  1727. IN DWORD cbBlob,
  1728. IN DWORD dwFlags,
  1729. OUT HCRYPTKEY *phKey)
  1730. {
  1731. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1732. DWORD cb = 0;
  1733. DWORD cbIndex = 0;
  1734. DWORD cbKey = 0;
  1735. BYTE rgbChecksum[8];
  1736. BLOBHEADER *pBlobHdr = (BLOBHEADER*)pbBlob;
  1737. ALG_ID *pAlgid;
  1738. BYTE rgbTmp1[49]; // 1 length + 8 padding + 8 checksum + 8 IV + 24 max key
  1739. BYTE rgbTmp2[49]; // 1 length + 8 padding + 8 checksum + 8 IV + 24 max key
  1740. DWORD dwRights = 0;
  1741. PNTAGKeyList pTmpKey = NULL;
  1742. PNTAGKeyList pLocalWrapKey = NULL;
  1743. BOOL fAlloc = FALSE;
  1744. DWORD i;
  1745. BOOL fPubKey;
  1746. DWORD dwSts;
  1747. memset(rgbTmp1, 0, sizeof(rgbTmp1));
  1748. memset(rgbTmp2, 0, sizeof(rgbTmp2));
  1749. cb = cbBlob - (sizeof(BLOBHEADER) + sizeof(ALG_ID));
  1750. if ((sizeof(rgbTmp1) < cb) || (0 != (cb % 8)))
  1751. {
  1752. dwReturn = (DWORD)NTE_BAD_DATA;
  1753. goto ErrorExit;
  1754. }
  1755. // both keys must be supported symmetric keys
  1756. if (UnsupportedSymKey(pWrapKey) || UnsupportedSymKey(pWrapKey))
  1757. {
  1758. dwReturn = (DWORD)NTE_BAD_KEY;
  1759. goto ErrorExit;
  1760. }
  1761. #ifdef CSP_USE_AES
  1762. // For now, punt on supporting AES algs in this scenario
  1763. if (CALG_AES_128 == pWrapKey->Algid ||
  1764. CALG_AES_192 == pWrapKey->Algid ||
  1765. CALG_AES_256 == pWrapKey->Algid)
  1766. {
  1767. dwReturn = (DWORD)NTE_BAD_KEY;
  1768. goto ErrorExit;
  1769. }
  1770. #endif
  1771. if (!FIsLegalKey(pTmpUser, pWrapKey, FALSE))
  1772. {
  1773. dwReturn = (DWORD)NTE_BAD_KEY;
  1774. goto ErrorExit;
  1775. }
  1776. // check the wrapping key ALG_ID
  1777. pAlgid = (ALG_ID*)(pbBlob + sizeof(BLOBHEADER));
  1778. if (pWrapKey->Algid != *pAlgid)
  1779. {
  1780. dwReturn = (DWORD)NTE_BAD_KEY;
  1781. goto ErrorExit;
  1782. }
  1783. // Check if we should do an auto-inflate
  1784. if (pWrapKey->pData == NULL)
  1785. {
  1786. dwSts = InflateKey(pWrapKey);
  1787. if (ERROR_SUCCESS != dwSts)
  1788. {
  1789. dwReturn = dwSts;
  1790. goto ErrorExit;
  1791. }
  1792. }
  1793. // set the hardcoded IV
  1794. if (CALG_RC4 != pWrapKey->Algid)
  1795. {
  1796. memcpy(pWrapKey->IV, rgbSymmetricKeyWrapIV, 8);
  1797. pWrapKey->InProgress = FALSE;
  1798. pLocalWrapKey = pWrapKey;
  1799. }
  1800. else
  1801. {
  1802. // RC4 (or more precisely, stream ciphers) are not supported by the
  1803. // CMS spec for symmetric key wrapping. Therefore we had to do
  1804. // something proprietary to support RC4 for applications other
  1805. // than SMIME.
  1806. dwSts = GetRC4KeyForSymWrap(rgbSymmetricKeyWrapIV,
  1807. pWrapKey,
  1808. &pLocalWrapKey);
  1809. if (ERROR_SUCCESS != dwSts)
  1810. {
  1811. dwReturn = dwSts;
  1812. goto ErrorExit;
  1813. }
  1814. fAlloc = TRUE;
  1815. }
  1816. memcpy(rgbTmp1, pbBlob + sizeof(BLOBHEADER) + sizeof(ALG_ID), cb);
  1817. // decrypt the key blob data
  1818. dwSts = SymDecrypt(pLocalWrapKey, 0, FALSE, rgbTmp1, &cb);
  1819. if (ERROR_SUCCESS != dwSts)
  1820. {
  1821. dwReturn = dwSts;
  1822. goto ErrorExit;
  1823. }
  1824. // byte reverse the plaintext + IV buffer
  1825. for (i = 0; i < cb; i++)
  1826. rgbTmp2[i] = rgbTmp1[cb - (i + 1)];
  1827. // set the IV if the algorithm is not RC4
  1828. cb -= 8;
  1829. if (CALG_RC4 != pWrapKey->Algid)
  1830. {
  1831. memcpy(pWrapKey->IV, rgbTmp2, 8);
  1832. pWrapKey->InProgress = FALSE;
  1833. }
  1834. else
  1835. {
  1836. if (fAlloc && pLocalWrapKey)
  1837. {
  1838. FreeNewKey(pLocalWrapKey);
  1839. pLocalWrapKey = NULL;
  1840. fAlloc = FALSE;
  1841. }
  1842. // RC4 (or more precisely, stream ciphers) are not supported by the
  1843. // CMS spec for symmetric key wrapping. Therefore we had to do
  1844. // something proprietary to support RC4 for applications other
  1845. // than SMIME.
  1846. dwSts = GetRC4KeyForSymWrap(rgbTmp2, pWrapKey, &pLocalWrapKey);
  1847. if (ERROR_SUCCESS != dwSts)
  1848. {
  1849. dwReturn = dwSts;
  1850. goto ErrorExit;
  1851. }
  1852. fAlloc = TRUE;
  1853. }
  1854. // decrypt the key blob data again
  1855. dwSts = SymDecrypt(pLocalWrapKey, 0, FALSE, rgbTmp2 + 8, &cb);
  1856. if (ERROR_SUCCESS != dwSts)
  1857. {
  1858. dwReturn = dwSts;
  1859. goto ErrorExit;
  1860. }
  1861. // check the length of the key
  1862. switch (pBlobHdr->aiKeyAlg)
  1863. {
  1864. case CALG_RC2: // variable key lengths
  1865. case CALG_RC4:
  1866. cbKey = (DWORD)rgbTmp2[8];
  1867. cbIndex += 1;
  1868. break;
  1869. case CALG_DES: // Ignore the default length, and use the full DES length.
  1870. case CALG_DESX:
  1871. case CALG_CYLINK_MEK:
  1872. cbKey = DES_KEYSIZE;
  1873. break;
  1874. case CALG_3DES_112:
  1875. cbKey = DES_KEYSIZE * 2;
  1876. break;
  1877. case CALG_3DES:
  1878. cbKey = DES_KEYSIZE * 3;
  1879. break;
  1880. default:
  1881. if (!GetDefaultKeyLength(pTmpUser, pBlobHdr->aiKeyAlg,
  1882. &cbKey, &fPubKey))
  1883. {
  1884. dwReturn = (DWORD)NTE_BAD_ALGID;
  1885. goto ErrorExit;
  1886. }
  1887. }
  1888. // get the checksum and make sure it matches
  1889. cb -= 8;
  1890. GetSymmetricKeyChecksum(rgbTmp2 + 8, cb, rgbChecksum);
  1891. if (0 != memcmp(rgbChecksum, rgbTmp2 + 8 + cb, sizeof(rgbChecksum)))
  1892. {
  1893. dwReturn = (DWORD)NTE_BAD_DATA;
  1894. goto ErrorExit;
  1895. }
  1896. // check if the key is to be exportable
  1897. if (dwFlags & CRYPT_EXPORTABLE)
  1898. dwRights = CRYPT_EXPORTABLE;
  1899. dwSts = MakeNewKey(pBlobHdr->aiKeyAlg, dwRights, cbKey, hUID,
  1900. rgbTmp2 + cbIndex + 8, FALSE, TRUE, &pTmpKey);
  1901. if (ERROR_SUCCESS != dwSts)
  1902. {
  1903. dwReturn = dwSts;
  1904. goto ErrorExit;
  1905. }
  1906. // check keylength...
  1907. if (!FIsLegalKey(pTmpUser, pTmpKey, TRUE))
  1908. {
  1909. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1910. goto ErrorExit;
  1911. }
  1912. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  1913. if (ERROR_SUCCESS != dwSts)
  1914. {
  1915. dwReturn = dwSts;
  1916. goto ErrorExit;
  1917. }
  1918. // if 40 bit key + no mention of salt, set zeroized salt for
  1919. // RSABase compatibility
  1920. if ((5 == pTmpKey->cbKeyLen) && (0 == (dwFlags & CRYPT_NO_SALT)))
  1921. {
  1922. dwSts = MakeKeyRSABaseCompatible(hUID, *phKey);
  1923. if (ERROR_SUCCESS != dwSts)
  1924. {
  1925. dwReturn = dwSts;
  1926. goto ErrorExit;
  1927. }
  1928. }
  1929. pTmpKey = NULL;
  1930. dwReturn = ERROR_SUCCESS;
  1931. ErrorExit:
  1932. if (fAlloc && pLocalWrapKey)
  1933. FreeNewKey(pLocalWrapKey);
  1934. memset(rgbTmp1, 0, sizeof(rgbTmp1));
  1935. memset(rgbTmp2, 0, sizeof(rgbTmp2));
  1936. if (NULL != pTmpKey)
  1937. FreeNewKey(pTmpKey);
  1938. return dwReturn;
  1939. }
  1940. /*
  1941. - CPExportKey
  1942. -
  1943. * Purpose:
  1944. * Export cryptographic keys out of a CSP in a secure manner
  1945. *
  1946. *
  1947. * Parameters:
  1948. * IN hUID - Handle to the CSP user
  1949. * IN hKey - Handle to the key to export
  1950. * IN hPubKey - Handle to the exchange public key value of
  1951. * the destination user
  1952. * IN dwBlobType - Type of key blob to be exported
  1953. * IN dwFlags - Flags values
  1954. * OUT pbData - Key blob data
  1955. * OUT pdwDataLen - Length of key blob in bytes
  1956. *
  1957. * Returns:
  1958. */
  1959. BOOL WINAPI
  1960. CPExportKey(
  1961. IN HCRYPTPROV hUID,
  1962. IN HCRYPTKEY hKey,
  1963. IN HCRYPTKEY hPubKey,
  1964. IN DWORD dwBlobType,
  1965. IN DWORD dwFlags,
  1966. OUT BYTE *pbData,
  1967. OUT DWORD *pdwDataLen)
  1968. {
  1969. // return codes
  1970. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  1971. BOOL fRet;
  1972. // miscellaneous variables
  1973. DWORD dwLen;
  1974. NTSimpleBlob *pSimpleHeader;
  1975. BLOBHEADER *pPreHeader;
  1976. BLOBHEADER shScratch;
  1977. RSAPUBKEY *pExpPubKey;
  1978. BSAFE_PUB_KEY *pBsafePubKey;
  1979. BSAFE_PUB_KEY *pPublicKey;
  1980. DWORD PubKeyLen;
  1981. BSAFE_PRV_KEY *pPrvKey = NULL;
  1982. DWORD PrvKeyLen = 0;
  1983. DWORD cbPrivateBlob = 0;
  1984. PBYTE pbPrivateBlob = NULL;
  1985. DWORD cb = 0;
  1986. BOOL fExportable = FALSE;
  1987. DWORD dwSts;
  1988. // temporary variables for pointing to user and key records
  1989. PNTAGKeyList pTmpKey;
  1990. PNTAGKeyList pPubKey;
  1991. PNTAGUserList pTmpUser;
  1992. EntryPoint
  1993. if (0 != (dwFlags & ~(CRYPT_SSL2_FALLBACK
  1994. | CRYPT_DESTROYKEY
  1995. | CRYPT_OAEP)))
  1996. {
  1997. dwReturn = (DWORD)NTE_BAD_FLAGS;
  1998. goto ErrorExit;
  1999. }
  2000. if (pdwDataLen == NULL)
  2001. {
  2002. dwReturn = ERROR_INVALID_PARAMETER;
  2003. goto ErrorExit;
  2004. }
  2005. if (((PUBLICKEYBLOB == dwBlobType) || (OPAQUEKEYBLOB == dwBlobType)
  2006. || (PLAINTEXTKEYBLOB == dwBlobType))
  2007. && (0 != hPubKey))
  2008. {
  2009. dwReturn = (DWORD)NTE_BAD_PUBLIC_KEY;
  2010. goto ErrorExit;
  2011. }
  2012. // check the user identification
  2013. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  2014. if (NULL == pTmpUser)
  2015. {
  2016. dwReturn = (DWORD)NTE_BAD_UID;
  2017. goto ErrorExit;
  2018. }
  2019. // check if the user is just looking for a length. If so,
  2020. // use a scratchpad to construct a pseudoblob.
  2021. if ((pbData != NULL) && (*pdwDataLen > sizeof(BLOBHEADER)))
  2022. pPreHeader = (BLOBHEADER *)pbData;
  2023. else
  2024. pPreHeader = &shScratch;
  2025. pPreHeader->bType = (BYTE)(dwBlobType & 0xff);
  2026. pPreHeader->bVersion = CUR_BLOB_VERSION;
  2027. pPreHeader->reserved = 0;
  2028. dwSts = NTLValidate((HNTAG)hKey, hUID, HNTAG_TO_HTYPE(hKey), &pTmpKey);
  2029. if (ERROR_SUCCESS != dwSts)
  2030. {
  2031. dwReturn = (NTE_FAIL == dwSts) ? (DWORD)NTE_BAD_KEY : dwSts;
  2032. goto ErrorExit;
  2033. }
  2034. if ((dwBlobType != PUBLICKEYBLOB) &&
  2035. (0 == (pTmpKey->Rights & (CRYPT_EXPORTABLE | CRYPT_ARCHIVABLE))))
  2036. {
  2037. dwReturn = (DWORD)NTE_BAD_KEY_STATE;
  2038. goto ErrorExit;
  2039. }
  2040. pPreHeader->aiKeyAlg = pTmpKey->Algid;
  2041. switch (dwBlobType)
  2042. {
  2043. case PUBLICKEYBLOB:
  2044. {
  2045. if ((HNTAG_TO_HTYPE(hKey) != SIGPUBKEY_HANDLE) &&
  2046. (HNTAG_TO_HTYPE(hKey) != EXCHPUBKEY_HANDLE))
  2047. {
  2048. dwReturn = (DWORD)NTE_BAD_KEY;
  2049. goto ErrorExit;
  2050. }
  2051. pBsafePubKey = (BSAFE_PUB_KEY *) pTmpKey->pKeyValue;
  2052. if (pBsafePubKey == NULL)
  2053. {
  2054. dwReturn = (DWORD)NTE_NO_KEY;
  2055. goto ErrorExit;
  2056. }
  2057. //
  2058. // Subtract off 2 extra DWORD needed by RSA code
  2059. //
  2060. dwLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
  2061. ((pBsafePubKey->bitlen + 7) / 8);
  2062. // Check user buffer size
  2063. if (pbData == NULL || *pdwDataLen < dwLen)
  2064. {
  2065. *pdwDataLen = dwLen;
  2066. if (pbData == NULL)
  2067. dwReturn = ERROR_SUCCESS;
  2068. else
  2069. dwReturn = ERROR_MORE_DATA;
  2070. goto ErrorExit;
  2071. }
  2072. pExpPubKey = (RSAPUBKEY *) (pbData + sizeof(BLOBHEADER));
  2073. pExpPubKey->magic = pBsafePubKey->magic;
  2074. pExpPubKey->bitlen = pBsafePubKey->bitlen;
  2075. pExpPubKey->pubexp = pBsafePubKey->pubexp;
  2076. memcpy((BYTE *) pbData + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
  2077. (BYTE *) pBsafePubKey + sizeof(BSAFE_PUB_KEY),
  2078. ((pBsafePubKey->bitlen + 7) / 8));
  2079. break;
  2080. }
  2081. case PRIVATEKEYBLOB:
  2082. {
  2083. DWORD dwBlockLen = 0;
  2084. BOOL fSigKey;
  2085. LPWSTR szPrompt;
  2086. cb = sizeof(DWORD);
  2087. if (HNTAG_TO_HTYPE(hKey) == SIGPUBKEY_HANDLE)
  2088. {
  2089. fSigKey = TRUE;
  2090. szPrompt = g_Strings.pwszExportPrivSig;
  2091. pPublicKey = (BSAFE_PUB_KEY*)pTmpUser->ContInfo.pbSigPub;
  2092. PubKeyLen = pTmpUser->ContInfo.ContLens.cbSigPub;
  2093. }
  2094. else if (HNTAG_TO_HTYPE(hKey) == EXCHPUBKEY_HANDLE)
  2095. {
  2096. fSigKey = FALSE;
  2097. szPrompt = g_Strings.pwszExportPrivExch;
  2098. pPublicKey = (BSAFE_PUB_KEY*)pTmpUser->ContInfo.pbExchPub;
  2099. PubKeyLen = pTmpUser->ContInfo.ContLens.cbExchPub;
  2100. }
  2101. else
  2102. {
  2103. dwReturn = (DWORD)NTE_BAD_KEY;
  2104. goto ErrorExit;
  2105. }
  2106. // make sure the public key is available and appropriate
  2107. if ((pPublicKey == NULL)
  2108. || (PubKeyLen != pTmpKey->cbKeyLen)
  2109. || (0 != memcmp((PBYTE)pPublicKey, pTmpKey->pKeyValue, PubKeyLen)))
  2110. {
  2111. dwReturn = (DWORD)NTE_BAD_KEY;
  2112. goto ErrorExit;
  2113. }
  2114. GetLengthOfPrivateKeyForExport(pPublicKey, &cbPrivateBlob);
  2115. if (hPubKey)
  2116. {
  2117. if (!CPGetKeyParam(hUID, hPubKey, KP_BLOCKLEN,
  2118. (PBYTE)&dwBlockLen, &cb, 0))
  2119. {
  2120. dwReturn = (DWORD)NTE_BAD_KEY;
  2121. goto ErrorExit;
  2122. }
  2123. // convert to byte count
  2124. dwBlockLen /= 8;
  2125. }
  2126. // Check user buffer size
  2127. if (pbData == NULL)
  2128. {
  2129. *pdwDataLen = sizeof(BLOBHEADER) + cbPrivateBlob + dwBlockLen;
  2130. dwReturn = ERROR_SUCCESS;
  2131. goto ErrorExit;
  2132. }
  2133. else if (*pdwDataLen < (sizeof(BLOBHEADER)
  2134. + cbPrivateBlob + dwBlockLen))
  2135. {
  2136. *pdwDataLen = sizeof(BLOBHEADER) + cbPrivateBlob + dwBlockLen;
  2137. dwReturn = ERROR_MORE_DATA;
  2138. goto ErrorExit;
  2139. }
  2140. // if the context being used is a Verify context then the key is not
  2141. // in persisted storage and therefore is in memory
  2142. if (0 == (pTmpUser->Rights & CRYPT_VERIFYCONTEXT))
  2143. {
  2144. // always read the private key from storage when exporting
  2145. dwSts= UnprotectPrivKey(pTmpUser, szPrompt, fSigKey, TRUE);
  2146. if (ERROR_SUCCESS != dwSts)
  2147. {
  2148. dwReturn = dwSts; // NTE_BAD_KEYSET
  2149. goto ErrorExit;
  2150. }
  2151. }
  2152. if (fSigKey)
  2153. {
  2154. PrvKeyLen = pTmpUser->SigPrivLen;
  2155. pPrvKey = (BSAFE_PRV_KEY*)pTmpUser->pSigPrivKey;
  2156. fExportable = pTmpUser->ContInfo.fSigExportable;
  2157. }
  2158. else
  2159. {
  2160. PrvKeyLen = pTmpUser->ExchPrivLen;
  2161. pPrvKey = (BSAFE_PRV_KEY*)pTmpUser->pExchPrivKey;
  2162. fExportable = pTmpUser->ContInfo.fExchExportable;
  2163. }
  2164. if (pPrvKey == NULL)
  2165. {
  2166. dwReturn = (DWORD)NTE_NO_KEY;
  2167. goto ErrorExit;
  2168. }
  2169. if (!fExportable && (0 == (CRYPT_ARCHIVABLE & pTmpKey->Rights)))
  2170. {
  2171. dwReturn = (DWORD)NTE_BAD_KEY;
  2172. goto ErrorExit;
  2173. }
  2174. if (!PreparePrivateKeyForExport(pPrvKey, NULL, &cbPrivateBlob))
  2175. {
  2176. dwReturn = (DWORD)NTE_BAD_KEY;
  2177. goto ErrorExit;
  2178. }
  2179. // allocate memory for the private key blob
  2180. cb = cbPrivateBlob + dwBlockLen;
  2181. pbPrivateBlob = _nt_malloc(cb);
  2182. if (NULL == pbPrivateBlob)
  2183. {
  2184. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  2185. goto ErrorExit;
  2186. }
  2187. if (!PreparePrivateKeyForExport(pPrvKey,
  2188. pbPrivateBlob, &cbPrivateBlob))
  2189. {
  2190. // ?BUGBUG? Fix this
  2191. dwReturn = (DWORD)NTE_BAD_KEY;
  2192. goto ErrorExit;
  2193. }
  2194. if (hPubKey)
  2195. {
  2196. dwSts = LocalEncrypt(hUID, hPubKey, 0, TRUE, 0, pbPrivateBlob,
  2197. &cbPrivateBlob, cb, FALSE);
  2198. if (ERROR_SUCCESS != dwSts)
  2199. {
  2200. dwReturn = dwSts;
  2201. goto ErrorExit;
  2202. }
  2203. }
  2204. dwLen = sizeof(BLOBHEADER) + cbPrivateBlob;
  2205. CopyMemory(pbData + sizeof(BLOBHEADER), pbPrivateBlob, cbPrivateBlob);
  2206. break;
  2207. }
  2208. case SIMPLEBLOB:
  2209. {
  2210. if (HNTAG_TO_HTYPE(hKey) != KEY_HANDLE)
  2211. {
  2212. dwReturn = (DWORD)NTE_BAD_KEY;
  2213. goto ErrorExit;
  2214. }
  2215. if (0 == hPubKey)
  2216. {
  2217. dwReturn = (DWORD)NTE_NO_KEY;
  2218. goto ErrorExit;
  2219. }
  2220. if (!FIsLegalKey(pTmpUser, pTmpKey, FALSE))
  2221. {
  2222. dwReturn = (DWORD)NTE_BAD_KEY;
  2223. goto ErrorExit;
  2224. }
  2225. #ifdef CSP_USE_SSL3
  2226. // if the SSL2_FALLBACK flag is set then make sure the key
  2227. // is an SSL2 master key
  2228. if (CRYPT_SSL2_FALLBACK & dwFlags)
  2229. {
  2230. if (CALG_SSL2_MASTER != pTmpKey->Algid)
  2231. {
  2232. dwReturn = (DWORD)NTE_BAD_KEY;
  2233. goto ErrorExit;
  2234. }
  2235. }
  2236. #endif
  2237. dwSts = NTLValidate((HNTAG)hPubKey, hUID, EXCHPUBKEY_HANDLE,
  2238. &pPubKey);
  2239. if (ERROR_SUCCESS != dwSts)
  2240. {
  2241. dwReturn = (NTE_FAIL == dwSts) ? (DWORD)NTE_BAD_KEY : dwSts;
  2242. goto ErrorExit;
  2243. }
  2244. pBsafePubKey = (BSAFE_PUB_KEY *) pPubKey->pKeyValue;
  2245. if (pBsafePubKey == NULL)
  2246. {
  2247. dwReturn = (DWORD)NTE_NO_KEY;
  2248. goto ErrorExit;
  2249. }
  2250. //
  2251. // Subtract off 8 bytes for 2 extra DWORD needed by RSA code
  2252. dwLen = sizeof(BLOBHEADER) + sizeof(NTSimpleBlob) +
  2253. (pBsafePubKey->bitlen + 7) / 8;
  2254. if (pbData == NULL || *pdwDataLen < dwLen)
  2255. {
  2256. *pdwDataLen = dwLen; // set what we need
  2257. if (pbData == NULL)
  2258. dwReturn = ERROR_SUCCESS;
  2259. else
  2260. dwReturn = ERROR_MORE_DATA;
  2261. goto ErrorExit;
  2262. }
  2263. pSimpleHeader = (NTSimpleBlob *) (pbData + sizeof(BLOBHEADER));
  2264. pSimpleHeader->aiEncAlg = CALG_RSA_KEYX;
  2265. #ifdef USE_SGC
  2266. // if this is the schannel provider and we are a verify context and
  2267. // the SGC flags are set and the key is large then make sure the
  2268. // key is the same as the SGC key
  2269. if ((PROV_RSA_SCHANNEL == pTmpUser->dwProvType) &&
  2270. (0 != pTmpUser->dwSGCFlags) &&
  2271. (pTmpUser->Rights & CRYPT_VERIFYCONTEXT) &&
  2272. (pBsafePubKey->bitlen > 1024))
  2273. {
  2274. if (!CheckSGCSimpleForExport(pTmpUser, pBsafePubKey))
  2275. {
  2276. dwReturn = (DWORD)NTE_BAD_KEY;
  2277. goto ErrorExit;
  2278. }
  2279. }
  2280. #endif
  2281. // perform the RSA encryption.
  2282. dwSts = RSAEncrypt(pTmpUser, pBsafePubKey, pTmpKey->pKeyValue,
  2283. pTmpKey->cbKeyLen, pTmpKey->pbParams,
  2284. pTmpKey->cbParams, dwFlags,
  2285. pbData + sizeof(BLOBHEADER) + sizeof(NTSimpleBlob));
  2286. if (ERROR_SUCCESS != dwSts)
  2287. {
  2288. dwReturn = dwSts;
  2289. goto ErrorExit;
  2290. }
  2291. break;
  2292. }
  2293. case OPAQUEKEYBLOB:
  2294. {
  2295. dwLen = *pdwDataLen;
  2296. dwSts = ExportOpaqueBlob(pTmpKey, pbData, &dwLen);
  2297. if (ERROR_SUCCESS != dwSts)
  2298. {
  2299. dwReturn = dwSts;
  2300. goto ErrorExit;
  2301. }
  2302. // if the destroy key flag is set then destroy the key
  2303. if (CRYPT_DESTROYKEY & dwFlags)
  2304. {
  2305. if (!CPDestroyKey(hUID, hKey))
  2306. {
  2307. dwReturn = GetLastError();
  2308. goto ErrorExit;
  2309. }
  2310. }
  2311. break;
  2312. }
  2313. case SYMMETRICWRAPKEYBLOB:
  2314. {
  2315. // get a pointer to the symmetric key to wrap with (the variable
  2316. // name pPubKey is a misnomer)
  2317. dwSts = NTLValidate((HNTAG)hPubKey,
  2318. hUID,
  2319. HNTAG_TO_HTYPE(hKey),
  2320. &pPubKey);
  2321. if (ERROR_SUCCESS != dwSts)
  2322. {
  2323. dwReturn = (NTE_FAIL == dwSts) ? (DWORD)NTE_BAD_KEY : dwSts;
  2324. goto ErrorExit;
  2325. }
  2326. dwSts = WrapSymKey(pTmpUser, pTmpKey, pPubKey, pbData, pdwDataLen);
  2327. if (ERROR_SUCCESS != dwSts)
  2328. {
  2329. dwReturn = dwSts;
  2330. goto ErrorExit;
  2331. }
  2332. dwLen = *pdwDataLen;
  2333. break;
  2334. }
  2335. case PLAINTEXTKEYBLOB:
  2336. {
  2337. if (HNTAG_TO_HTYPE(hKey) != KEY_HANDLE)
  2338. {
  2339. dwReturn = (DWORD)NTE_BAD_KEY;
  2340. goto ErrorExit;
  2341. }
  2342. if (! FIsLegalKey(pTmpUser, pTmpKey, FALSE))
  2343. {
  2344. dwReturn = (DWORD)NTE_BAD_KEY;
  2345. goto ErrorExit;
  2346. }
  2347. dwLen = sizeof(BLOBHEADER) + sizeof(DWORD) + pTmpKey->cbKeyLen;
  2348. if (NULL == pbData || *pdwDataLen < dwLen)
  2349. {
  2350. *pdwDataLen = dwLen;
  2351. if (NULL == pbData)
  2352. dwReturn = ERROR_SUCCESS;
  2353. else
  2354. dwReturn = ERROR_MORE_DATA;
  2355. goto ErrorExit;
  2356. }
  2357. pbData += sizeof(BLOBHEADER);
  2358. *((DWORD*)pbData) = pTmpKey->cbKeyLen;
  2359. pbData += sizeof(DWORD);
  2360. memcpy(pbData, pTmpKey->pKeyValue, pTmpKey->cbKeyLen);
  2361. *pdwDataLen = dwLen;
  2362. break;
  2363. }
  2364. default:
  2365. dwReturn = (DWORD)NTE_BAD_TYPE;
  2366. goto ErrorExit;
  2367. }
  2368. // set the size of the key blob
  2369. *pdwDataLen = dwLen;
  2370. dwReturn = ERROR_SUCCESS;
  2371. ErrorExit:
  2372. fRet = (ERROR_SUCCESS == dwReturn);
  2373. if (pbPrivateBlob)
  2374. _nt_free(pbPrivateBlob, cb);
  2375. if (!fRet)
  2376. SetLastError(dwReturn);
  2377. return fRet;
  2378. }
  2379. /*static*/ DWORD
  2380. ImportOpaqueBlob(
  2381. HCRYPTPROV hUID,
  2382. CONST BYTE *pbData,
  2383. DWORD cbData,
  2384. HCRYPTKEY *phKey)
  2385. {
  2386. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  2387. PNTAGKeyList pTmpKey = NULL;
  2388. PNTAGPackedKeyList pPackedKey;
  2389. DWORD cbRequired;
  2390. DWORD dwSts;
  2391. *phKey = 0;
  2392. // allocate a temporary key structure
  2393. pTmpKey = (PNTAGKeyList)_nt_malloc(sizeof(NTAGKeyList));
  2394. if (NULL == pTmpKey)
  2395. {
  2396. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  2397. goto ErrorExit;
  2398. }
  2399. // make sure we have enough data
  2400. cbRequired = sizeof(BLOBHEADER) +
  2401. sizeof(NTAGPackedKeyList);
  2402. if (cbData < cbRequired)
  2403. {
  2404. dwReturn = (DWORD)NTE_BAD_DATA;
  2405. goto ErrorExit;
  2406. }
  2407. // build key structure from packed key structure
  2408. pPackedKey = (PNTAGPackedKeyList)(pbData + sizeof(BLOBHEADER));
  2409. pTmpKey->hUID = hUID;
  2410. pTmpKey->Algid = pPackedKey->Algid;
  2411. pTmpKey->Rights = pPackedKey->Rights;
  2412. pTmpKey->cbKeyLen = pPackedKey->cbKeyLen;
  2413. pTmpKey->cbDataLen = pPackedKey->cbDataLen;
  2414. memcpy(pTmpKey->IV, pPackedKey->IV, sizeof(pTmpKey->IV));
  2415. memcpy(pTmpKey->FeedBack, pPackedKey->FeedBack, sizeof(pTmpKey->FeedBack));
  2416. pTmpKey->InProgress = pPackedKey->InProgress;
  2417. pTmpKey->cbSaltLen = pPackedKey->cbSaltLen;
  2418. memcpy(pTmpKey->rgbSalt, pPackedKey->rgbSalt, sizeof(pTmpKey->rgbSalt));
  2419. pTmpKey->Padding = pPackedKey->Padding;
  2420. pTmpKey->Mode = pPackedKey->Mode;
  2421. pTmpKey->ModeBits = pPackedKey->ModeBits;
  2422. pTmpKey->Permissions = pPackedKey->Permissions;
  2423. pTmpKey->EffectiveKeyLen = pPackedKey->EffectiveKeyLen;
  2424. pTmpKey->dwBlockLen = pPackedKey->dwBlockLen;
  2425. // make sure we still have enough data
  2426. cbRequired += pTmpKey->cbKeyLen +
  2427. pTmpKey->cbDataLen;
  2428. if (cbData < cbRequired)
  2429. {
  2430. dwReturn = (DWORD)NTE_BAD_DATA;
  2431. goto ErrorExit;
  2432. }
  2433. // allocate memory and copy the key value
  2434. if (0 < pTmpKey->cbKeyLen)
  2435. {
  2436. pTmpKey->pKeyValue = _nt_malloc(pTmpKey->cbKeyLen);
  2437. if (NULL == pTmpKey->pKeyValue)
  2438. {
  2439. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  2440. goto ErrorExit;
  2441. }
  2442. memcpy(pTmpKey->pKeyValue,
  2443. (PBYTE)pPackedKey + sizeof(NTAGPackedKeyList),
  2444. pTmpKey->cbKeyLen);
  2445. }
  2446. // allocate memory and copy the key data
  2447. if (0 < pTmpKey->cbDataLen)
  2448. {
  2449. pTmpKey->pData = _nt_malloc(pTmpKey->cbDataLen);
  2450. if (NULL == pTmpKey->pData)
  2451. {
  2452. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  2453. goto ErrorExit;
  2454. }
  2455. memcpy(pTmpKey->pData,
  2456. (PBYTE)pPackedKey + sizeof(NTAGPackedKeyList) + pTmpKey->cbKeyLen,
  2457. pTmpKey->cbDataLen);
  2458. }
  2459. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  2460. if (ERROR_SUCCESS != dwSts)
  2461. {
  2462. dwReturn = dwSts;
  2463. goto ErrorExit;
  2464. }
  2465. pTmpKey = NULL;
  2466. dwReturn = ERROR_SUCCESS;
  2467. ErrorExit:
  2468. if (NULL != pTmpKey)
  2469. FreeNewKey(pTmpKey);
  2470. return dwReturn;
  2471. }
  2472. /*
  2473. - CPImportKey
  2474. -
  2475. * Purpose:
  2476. * Import cryptographic keys
  2477. *
  2478. *
  2479. * Parameters:
  2480. * IN hUID - Handle to the CSP user
  2481. * IN pbData - Key blob data
  2482. * IN dwDataLen - Length of the key blob data
  2483. * IN hPubKey - Handle to the exchange public key value of
  2484. * the destination user
  2485. * IN dwFlags - Flags values
  2486. * OUT phKey - Pointer to the handle to the key which was
  2487. * Imported
  2488. *
  2489. * Returns:
  2490. */
  2491. BOOL WINAPI
  2492. CPImportKey(
  2493. IN HCRYPTPROV hUID,
  2494. IN CONST BYTE *pbData,
  2495. IN DWORD dwDataLen,
  2496. IN HCRYPTKEY hPubKey,
  2497. IN DWORD dwFlags,
  2498. OUT HCRYPTKEY *phKey)
  2499. {
  2500. // Status return variables
  2501. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  2502. BOOL fRet;
  2503. // miscellaneous variables
  2504. DWORD KeyBufLen;
  2505. CONST BYTE *pbEncPortion;
  2506. BLOBHEADER *ThisStdHeader = (BLOBHEADER *)pbData;
  2507. BSAFE_PRV_KEY *pBsafePrvKey = NULL;
  2508. BYTE *pKeyBuf = NULL;
  2509. DWORD dwRights = 0;
  2510. DWORD cbTmpLen;
  2511. DWORD dwSts;
  2512. // temporary variables for pointing to user and key records
  2513. PNTAGUserList pTmpUser = NULL;
  2514. PNTAGKeyList pTmpKey = NULL;
  2515. LPWSTR szPrompt;
  2516. BLOBHEADER *pPublic;
  2517. RSAPUBKEY *pImpPubKey;
  2518. BSAFE_PUB_KEY *pBsafePubKey;
  2519. PBYTE pbData2 = NULL;
  2520. DWORD cb;
  2521. DWORD *pcbPub;
  2522. BYTE **ppbPub;
  2523. DWORD *pcbPrv;
  2524. BYTE **ppbPrv;
  2525. BOOL *pfExportable;
  2526. BOOL fExch;
  2527. PEXPORT_PRV_KEY pExportKey;
  2528. BOOL fPubKey = FALSE;
  2529. NTSimpleBlob *ThisSB;
  2530. PNTAGKeyList pExPubKey = NULL;
  2531. BOOL fInCritSec = FALSE;
  2532. BYTE *pbParams = NULL;
  2533. DWORD cbParams = 0;
  2534. BOOL fAllowBigRC2Key = FALSE;
  2535. EntryPoint
  2536. // Validate user pointer
  2537. // count = *phKey;
  2538. if ((dwFlags & ~(CRYPT_USER_PROTECTED | CRYPT_EXPORTABLE |
  2539. CRYPT_NO_SALT | CRYPT_SGCKEY | CRYPT_OAEP |
  2540. CRYPT_IPSEC_HMAC_KEY)) != 0)
  2541. {
  2542. dwReturn = (DWORD)NTE_BAD_FLAGS;
  2543. goto ErrorExit;
  2544. }
  2545. if ((PUBLICKEYBLOB == ThisStdHeader->bType) && (0 != hPubKey))
  2546. {
  2547. dwReturn = ERROR_INVALID_PARAMETER;
  2548. goto ErrorExit;
  2549. }
  2550. // check the user identification
  2551. pTmpUser = (PNTAGUserList)NTLCheckList((HNTAG)hUID, USER_HANDLE);
  2552. if (NULL == pTmpUser)
  2553. {
  2554. dwReturn = (DWORD)NTE_BAD_UID;
  2555. goto ErrorExit;
  2556. }
  2557. if (ThisStdHeader->bVersion != CUR_BLOB_VERSION)
  2558. {
  2559. dwReturn = (DWORD)NTE_BAD_VER;
  2560. goto ErrorExit;
  2561. }
  2562. // Handy pointer for decrypting the blob...
  2563. pbEncPortion = pbData + sizeof(BLOBHEADER) + sizeof(NTSimpleBlob);
  2564. // determine which key blob is being imported
  2565. switch (ThisStdHeader->bType)
  2566. {
  2567. case PUBLICKEYBLOB:
  2568. pPublic = (BLOBHEADER *) pbData;
  2569. pImpPubKey = (RSAPUBKEY *)(pbData+sizeof(BLOBHEADER));
  2570. if ((pPublic->aiKeyAlg != CALG_RSA_KEYX) &&
  2571. (pPublic->aiKeyAlg != CALG_RSA_SIGN))
  2572. {
  2573. dwReturn =(DWORD)NTE_BAD_DATA;
  2574. goto ErrorExit;
  2575. }
  2576. cbTmpLen = (sizeof(DWORD) * 2) -
  2577. (((pImpPubKey->bitlen + 7) / 8) % (sizeof(DWORD) * 2));
  2578. if ((sizeof(DWORD) * 2) != cbTmpLen)
  2579. cbTmpLen += sizeof(DWORD) * 2;
  2580. dwSts = MakeNewKey(pPublic->aiKeyAlg,
  2581. 0,
  2582. sizeof(BSAFE_PUB_KEY)
  2583. + (pImpPubKey->bitlen / 8)
  2584. + cbTmpLen,
  2585. hUID,
  2586. 0,
  2587. FALSE,
  2588. TRUE,
  2589. &pTmpKey);
  2590. if (ERROR_SUCCESS != dwSts)
  2591. {
  2592. dwReturn = dwSts;
  2593. goto ErrorExit;
  2594. }
  2595. pBsafePubKey = (BSAFE_PUB_KEY *)pTmpKey->pKeyValue;
  2596. pBsafePubKey->magic = pImpPubKey->magic;
  2597. pBsafePubKey->keylen = (pImpPubKey->bitlen / 8) + cbTmpLen;
  2598. pBsafePubKey->bitlen = pImpPubKey->bitlen;
  2599. pBsafePubKey->datalen = (pImpPubKey->bitlen+7)/8 - 1;
  2600. pBsafePubKey->pubexp = pImpPubKey->pubexp;
  2601. memset((BYTE *) pBsafePubKey + sizeof(BSAFE_PUB_KEY),
  2602. '\0', pBsafePubKey->keylen);
  2603. memcpy((BYTE *) pBsafePubKey + sizeof(BSAFE_PUB_KEY),
  2604. (BYTE *) pPublic + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
  2605. (pImpPubKey->bitlen+7)/8);
  2606. dwSts = NTLMakeItem(phKey,
  2607. (BYTE) (pPublic->aiKeyAlg == CALG_RSA_KEYX
  2608. ? EXCHPUBKEY_HANDLE
  2609. : SIGPUBKEY_HANDLE),
  2610. (void *)pTmpKey);
  2611. if (ERROR_SUCCESS != dwSts)
  2612. {
  2613. dwReturn = dwSts;
  2614. goto ErrorExit;
  2615. }
  2616. break;
  2617. case PRIVATEKEYBLOB:
  2618. // wrap with a try since there is a critical section in here
  2619. __try
  2620. {
  2621. EnterCriticalSection(&pTmpUser->CritSec);
  2622. fInCritSec = TRUE;
  2623. pPublic = (BLOBHEADER *) pbData;
  2624. cb = dwDataLen - sizeof(BLOBHEADER);
  2625. pbData2 = _nt_malloc(cb);
  2626. if (NULL == pbData2)
  2627. {
  2628. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  2629. goto ErrorExit;
  2630. }
  2631. CopyMemory(pbData2, pbData + sizeof(BLOBHEADER), cb);
  2632. if (hPubKey)
  2633. {
  2634. dwSts = LocalDecrypt(hUID, hPubKey, 0, TRUE, 0,
  2635. pbData2, &cb, FALSE);
  2636. if (ERROR_SUCCESS != dwSts)
  2637. {
  2638. dwReturn = dwSts;
  2639. goto ErrorExit;
  2640. }
  2641. }
  2642. if (pPublic->aiKeyAlg == CALG_RSA_KEYX)
  2643. {
  2644. if (PROV_RSA_SIG == pTmpUser->dwProvType)
  2645. {
  2646. dwReturn = (DWORD)NTE_BAD_DATA;
  2647. goto ErrorExit;
  2648. }
  2649. pcbPub = &pTmpUser->ContInfo.ContLens.cbExchPub;
  2650. ppbPub = &pTmpUser->ContInfo.pbExchPub;
  2651. pcbPrv = &pTmpUser->ExchPrivLen;
  2652. ppbPrv = &pTmpUser->pExchPrivKey;
  2653. pfExportable = &pTmpUser->ContInfo.fExchExportable;
  2654. fExch = TRUE;
  2655. szPrompt = g_Strings.pwszImportPrivExch;
  2656. }
  2657. else if (pPublic->aiKeyAlg == CALG_RSA_SIGN)
  2658. {
  2659. if (PROV_RSA_SCHANNEL == pTmpUser->dwProvType)
  2660. {
  2661. dwReturn = (DWORD)NTE_BAD_DATA;
  2662. goto ErrorExit;
  2663. }
  2664. pcbPub = &pTmpUser->ContInfo.ContLens.cbSigPub;
  2665. ppbPub = &pTmpUser->ContInfo.pbSigPub;
  2666. pcbPrv = &pTmpUser->SigPrivLen;
  2667. ppbPrv = &pTmpUser->pSigPrivKey;
  2668. fExch = FALSE;
  2669. pfExportable = &pTmpUser->ContInfo.fSigExportable;
  2670. szPrompt = g_Strings.pwszImportPrivSig;
  2671. }
  2672. else
  2673. {
  2674. dwReturn = (DWORD)NTE_BAD_DATA;
  2675. goto ErrorExit;
  2676. }
  2677. // check the length of the key exchange key
  2678. pExportKey = (PEXPORT_PRV_KEY)pbData2;
  2679. #ifdef USE_SGC
  2680. // check if the provider is an SChannel provider and if so if the
  2681. // SGC flag is set then use the FIsLegalSGCKeySize function
  2682. if ((PROV_RSA_SCHANNEL == pTmpUser->dwProvType)
  2683. && (!(pTmpUser->Rights & CRYPT_VERIFYCONTEXT))
  2684. && (0 != pTmpUser->dwSGCFlags)) // make sure this is server side
  2685. {
  2686. if (!FIsLegalSGCKeySize(pPublic->aiKeyAlg,
  2687. pExportKey->bitlen / 8,
  2688. FALSE, FALSE, &fPubKey))
  2689. {
  2690. dwReturn = (DWORD)NTE_BAD_DATA;
  2691. goto ErrorExit;
  2692. }
  2693. }
  2694. else
  2695. #endif
  2696. {
  2697. if (!FIsLegalKeySize(pTmpUser->dwCspTypeId,
  2698. pPublic->aiKeyAlg,
  2699. pExportKey->bitlen / 8,
  2700. FALSE, &fPubKey))
  2701. {
  2702. dwReturn = (DWORD)NTE_BAD_DATA;
  2703. goto ErrorExit;
  2704. }
  2705. }
  2706. if (!fPubKey)
  2707. {
  2708. dwReturn = (DWORD)NTE_BAD_DATA;
  2709. goto ErrorExit;
  2710. }
  2711. if (*ppbPub)
  2712. {
  2713. ASSERT(*pcbPub);
  2714. ASSERT(*pcbPrv);
  2715. ASSERT(*ppbPrv);
  2716. _nt_free(*ppbPub, *pcbPub);
  2717. *ppbPub = NULL;
  2718. *pcbPub = 0;
  2719. _nt_free(*ppbPrv, *pcbPrv);
  2720. *ppbPrv = NULL;
  2721. *pcbPrv = 0;
  2722. }
  2723. if (!PreparePrivateKeyForImport(pbData2, NULL, pcbPrv,
  2724. NULL, pcbPub))
  2725. {
  2726. dwReturn = (DWORD)NTE_BAD_DATA;
  2727. goto ErrorExit;
  2728. }
  2729. *ppbPub = _nt_malloc(*pcbPub);
  2730. if (NULL == *ppbPub)
  2731. {
  2732. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  2733. goto ErrorExit;
  2734. }
  2735. *ppbPrv = _nt_malloc(*pcbPrv);
  2736. if (NULL == *ppbPrv)
  2737. {
  2738. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  2739. goto ErrorExit;
  2740. }
  2741. if (!PreparePrivateKeyForImport(pbData2,
  2742. (LPBSAFE_PRV_KEY)*ppbPrv,
  2743. pcbPrv,
  2744. (LPBSAFE_PUB_KEY)*ppbPub,
  2745. pcbPub))
  2746. {
  2747. dwReturn = (DWORD)NTE_BAD_DATA;
  2748. goto ErrorExit;
  2749. }
  2750. if (dwFlags & CRYPT_EXPORTABLE)
  2751. *pfExportable = TRUE;
  2752. else
  2753. *pfExportable = FALSE;
  2754. // test the RSA key to make sure it works
  2755. dwSts = EncryptAndDecryptWithRSAKey(*ppbPub, *ppbPrv,
  2756. TRUE, FALSE);
  2757. if (ERROR_SUCCESS != dwSts)
  2758. {
  2759. dwReturn = dwSts; // NTE_BAD_DATA
  2760. goto ErrorExit;
  2761. }
  2762. dwSts = EncryptAndDecryptWithRSAKey(*ppbPub, *ppbPrv,
  2763. FALSE, FALSE);
  2764. if (ERROR_SUCCESS != dwSts)
  2765. {
  2766. dwReturn = dwSts; // NTE_BAD_DATA
  2767. goto ErrorExit;
  2768. }
  2769. // if the context being used is a Verify Context then the key
  2770. // is not persisted to storage
  2771. if (0 == (pTmpUser->Rights & CRYPT_VERIFYCONTEXT))
  2772. {
  2773. // write the new keys to the user storage file
  2774. dwSts = ProtectPrivKey(pTmpUser, szPrompt, dwFlags, (!fExch));
  2775. if (ERROR_SUCCESS != dwSts)
  2776. {
  2777. dwReturn = dwSts;
  2778. goto ErrorExit;
  2779. }
  2780. }
  2781. if (!CPGetUserKey(hUID,
  2782. (fExch ? AT_KEYEXCHANGE : AT_SIGNATURE),
  2783. phKey))
  2784. {
  2785. dwReturn = GetLastError();
  2786. goto ErrorExit;
  2787. }
  2788. }
  2789. __except ( EXCEPTION_EXECUTE_HANDLER )
  2790. {
  2791. // ?BUGBUG? No it's not!
  2792. dwReturn = ERROR_INVALID_PARAMETER;
  2793. goto ErrorExit;
  2794. }
  2795. break;
  2796. case SIMPLEBLOB:
  2797. ThisSB = (NTSimpleBlob *) (pbData + sizeof(BLOBHEADER));
  2798. if (!ValidKeyAlgid(pTmpUser, ThisStdHeader->aiKeyAlg))
  2799. {
  2800. dwReturn = (DWORD)NTE_BAD_TYPE;
  2801. goto ErrorExit;
  2802. }
  2803. if (ThisSB->aiEncAlg != CALG_RSA_KEYX)
  2804. {
  2805. dwReturn = (DWORD)NTE_BAD_ALGID;
  2806. goto ErrorExit;
  2807. }
  2808. // if the import key handle is not zero make sure it is the
  2809. if (0 != hPubKey)
  2810. {
  2811. dwSts = NTLValidate((HNTAG)hPubKey,
  2812. hUID,
  2813. HNTAG_TO_HTYPE((HNTAG)hPubKey),
  2814. &pExPubKey);
  2815. if (ERROR_SUCCESS != dwSts)
  2816. {
  2817. // NTLValidate doesn't know what error to set
  2818. // so it set NTE_FAIL -- fix it up.
  2819. dwReturn = (dwSts == NTE_FAIL) ?(DWORD)NTE_BAD_KEY : dwSts;
  2820. goto ErrorExit;
  2821. }
  2822. if ((pTmpUser->ContInfo.ContLens.cbExchPub != pExPubKey->cbKeyLen)
  2823. || (0 != memcmp((PBYTE)pExPubKey->pKeyValue,
  2824. pTmpUser->ContInfo.pbExchPub,
  2825. pExPubKey->cbKeyLen)))
  2826. {
  2827. dwReturn = (DWORD)NTE_BAD_KEY;
  2828. goto ErrorExit;
  2829. }
  2830. pbParams = pExPubKey->pbParams;
  2831. cbParams = pExPubKey->cbParams;
  2832. }
  2833. pBsafePubKey = (BSAFE_PUB_KEY *)pTmpUser->ContInfo.pbExchPub;
  2834. if (NULL == pBsafePubKey)
  2835. {
  2836. dwReturn = (DWORD)NTE_NO_KEY;
  2837. goto ErrorExit;
  2838. }
  2839. #ifdef USE_SGC
  2840. // check if the provider is an SChannel provider and if so if the
  2841. // SGC flag is set then use the FIsLegalSGCKeySize function
  2842. if ((PROV_RSA_SCHANNEL == pTmpUser->dwProvType)
  2843. && (!(pTmpUser->Rights & CRYPT_VERIFYCONTEXT))
  2844. && (0 != pTmpUser->dwSGCFlags)) // make sure this is server side
  2845. {
  2846. if (!FIsLegalSGCKeySize(CALG_RSA_KEYX,
  2847. pBsafePubKey->bitlen / 8,
  2848. FALSE, FALSE, &fPubKey))
  2849. {
  2850. dwReturn = (DWORD)NTE_BAD_DATA;
  2851. goto ErrorExit;
  2852. }
  2853. }
  2854. else
  2855. #endif
  2856. {
  2857. if (!FIsLegalKeySize(pTmpUser->dwCspTypeId,
  2858. CALG_RSA_KEYX,
  2859. pBsafePubKey->bitlen / 8,
  2860. FALSE, &fPubKey))
  2861. {
  2862. dwReturn = (DWORD)NTE_BAD_DATA;
  2863. goto ErrorExit;
  2864. }
  2865. }
  2866. // get the key to use
  2867. dwSts = UnprotectPrivKey(pTmpUser, g_Strings.pwszImportSimple,
  2868. FALSE, FALSE);
  2869. if (ERROR_SUCCESS != dwSts)
  2870. {
  2871. dwReturn = dwSts; // NTE_NO_KEY
  2872. goto ErrorExit;
  2873. }
  2874. pBsafePrvKey = (BSAFE_PRV_KEY *)pTmpUser->pExchPrivKey;
  2875. if (NULL == pBsafePrvKey)
  2876. {
  2877. dwReturn = (DWORD)NTE_NO_KEY;
  2878. goto ErrorExit;
  2879. }
  2880. // Check the input data length
  2881. if ((dwDataLen - (sizeof(BLOBHEADER) + sizeof(NTSimpleBlob)))
  2882. < ((pBsafePrvKey->bitlen + 7) / 8))
  2883. {
  2884. dwReturn = (DWORD)NTE_BAD_DATA;
  2885. goto ErrorExit;
  2886. }
  2887. // perform the RSA decryption
  2888. dwSts = RSADecrypt(pTmpUser, pBsafePrvKey,
  2889. pbData + sizeof(BLOBHEADER) + sizeof(NTSimpleBlob),
  2890. dwDataLen - (sizeof(BLOBHEADER) + sizeof(NTSimpleBlob)),
  2891. pbParams, cbParams, dwFlags,
  2892. &pKeyBuf, &KeyBufLen);
  2893. if (ERROR_SUCCESS != dwSts)
  2894. {
  2895. dwReturn = dwSts;
  2896. goto ErrorExit;
  2897. }
  2898. // check if the key is CRYPT_EXPORTABLE
  2899. if (dwFlags & CRYPT_EXPORTABLE)
  2900. dwRights = CRYPT_EXPORTABLE;
  2901. #ifdef CSP_USE_SSL3
  2902. // if SSL3 or TLS1 master key then check the version
  2903. if (CALG_SSL3_MASTER == ThisStdHeader->aiKeyAlg ||
  2904. CALG_TLS1_MASTER == ThisStdHeader->aiKeyAlg)
  2905. {
  2906. if (MAKEWORD(pKeyBuf[1], pKeyBuf[0]) < 0x300)
  2907. {
  2908. dwReturn = (DWORD)NTE_BAD_DATA;
  2909. goto ErrorExit;
  2910. }
  2911. }
  2912. #endif // CSP_USE_SSL3
  2913. dwSts = MakeNewKey(ThisStdHeader->aiKeyAlg, dwRights, KeyBufLen,
  2914. hUID, pKeyBuf, TRUE, TRUE, &pTmpKey);
  2915. if (ERROR_SUCCESS != dwSts)
  2916. {
  2917. dwReturn = dwSts;
  2918. goto ErrorExit;
  2919. }
  2920. pKeyBuf = NULL;
  2921. // check keylength...
  2922. if (!FIsLegalImportSymKey(pTmpUser, pTmpKey, TRUE))
  2923. {
  2924. dwReturn = (DWORD)NTE_BAD_FLAGS;
  2925. goto ErrorExit;
  2926. }
  2927. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  2928. if (ERROR_SUCCESS != dwSts)
  2929. {
  2930. dwReturn = dwSts;
  2931. goto ErrorExit;
  2932. }
  2933. // if 40 bit key + no mention of salt, set zeroized salt for
  2934. // RSABase compatibility
  2935. if ((5 == KeyBufLen)
  2936. && (0 == (dwFlags & CRYPT_NO_SALT))
  2937. && (CALG_SSL2_MASTER != ThisStdHeader->aiKeyAlg))
  2938. {
  2939. dwSts = MakeKeyRSABaseCompatible(hUID, *phKey);
  2940. if (ERROR_SUCCESS != dwSts)
  2941. {
  2942. dwReturn = dwSts;
  2943. goto ErrorExit;
  2944. }
  2945. }
  2946. break;
  2947. case OPAQUEKEYBLOB:
  2948. dwSts = ImportOpaqueBlob(hUID, pbData, dwDataLen, phKey);
  2949. if (ERROR_SUCCESS != dwSts)
  2950. {
  2951. dwReturn = dwSts;
  2952. goto ErrorExit;
  2953. }
  2954. break;
  2955. case SYMMETRICWRAPKEYBLOB:
  2956. // get a pointer to the symmetric key to unwrap with (the variable
  2957. // name pExPubKey is a misnomer)
  2958. dwSts = NTLValidate((HNTAG)hPubKey, hUID,
  2959. HNTAG_TO_HTYPE((HNTAG)hPubKey),
  2960. &pExPubKey);
  2961. if (ERROR_SUCCESS != dwSts)
  2962. {
  2963. // NTLValidate doesn't know what error to set
  2964. // so it set NTE_FAIL -- fix it up.
  2965. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  2966. goto ErrorExit;
  2967. }
  2968. dwSts = UnWrapSymKey(hUID, pTmpUser, pExPubKey, (BYTE*)pbData,
  2969. dwDataLen, dwFlags, phKey);
  2970. if (ERROR_SUCCESS != dwSts)
  2971. {
  2972. dwReturn = dwSts;
  2973. goto ErrorExit;
  2974. }
  2975. break;
  2976. case PLAINTEXTKEYBLOB:
  2977. if (! ValidKeyAlgid(pTmpUser, ThisStdHeader->aiKeyAlg))
  2978. {
  2979. dwReturn = (DWORD)NTE_BAD_ALGID;
  2980. goto ErrorExit;
  2981. }
  2982. // check if the key is CRYPT_EXPORTABLE
  2983. if (dwFlags & CRYPT_EXPORTABLE)
  2984. dwRights = CRYPT_EXPORTABLE;
  2985. KeyBufLen = *((DWORD*)(pbData + sizeof(BLOBHEADER)));
  2986. dwSts = MakeNewKey( ThisStdHeader->aiKeyAlg, dwRights,
  2987. KeyBufLen, hUID,
  2988. (BYTE *) (pbData + sizeof(BLOBHEADER) + sizeof(DWORD)),
  2989. FALSE, TRUE, &pTmpKey);
  2990. if (ERROR_SUCCESS != dwSts)
  2991. {
  2992. dwReturn = dwSts;
  2993. goto ErrorExit;
  2994. }
  2995. if (CRYPT_IPSEC_HMAC_KEY & dwFlags)
  2996. fAllowBigRC2Key = TRUE;
  2997. if (! FIsLegalImportSymKey(pTmpUser, pTmpKey, fAllowBigRC2Key))
  2998. {
  2999. dwReturn = (DWORD)NTE_BAD_DATA;
  3000. goto ErrorExit;
  3001. }
  3002. dwSts = NTLMakeItem(phKey, KEY_HANDLE, (void *)pTmpKey);
  3003. if (ERROR_SUCCESS != dwSts)
  3004. {
  3005. dwReturn = dwSts;
  3006. goto ErrorExit;
  3007. }
  3008. // if 40 bit key + no mention of salt, set zeroized salt for
  3009. // RSABase compatibility
  3010. if ((5 == KeyBufLen)
  3011. && (0 == (dwFlags & CRYPT_NO_SALT))
  3012. && (CALG_SSL2_MASTER != ThisStdHeader->aiKeyAlg))
  3013. {
  3014. dwSts = MakeKeyRSABaseCompatible(hUID, *phKey);
  3015. if (ERROR_SUCCESS != dwSts)
  3016. {
  3017. dwReturn = dwSts;
  3018. goto ErrorExit;
  3019. }
  3020. }
  3021. break;
  3022. default:
  3023. dwReturn = (DWORD)NTE_BAD_TYPE;
  3024. goto ErrorExit;
  3025. }
  3026. pTmpKey = NULL;
  3027. dwReturn = ERROR_SUCCESS;
  3028. ErrorExit:
  3029. fRet = (ERROR_SUCCESS == dwReturn);
  3030. if (fInCritSec)
  3031. LeaveCriticalSection(&pTmpUser->CritSec);
  3032. if (pKeyBuf)
  3033. _nt_free(pKeyBuf, KeyBufLen);
  3034. if (pbData2)
  3035. _nt_free(pbData2, dwDataLen - sizeof(BLOBHEADER));
  3036. if (NULL != pTmpKey)
  3037. FreeNewKey(pTmpKey);
  3038. if (!fRet)
  3039. SetLastError(dwReturn);
  3040. return fRet;
  3041. }
  3042. /*
  3043. - CPInflateKey
  3044. -
  3045. * Purpose:
  3046. * Use to "inflate" (expand) a cryptographic key for use with
  3047. * the CryptEncrypt and CryptDecrypt functions
  3048. *
  3049. * Parameters:
  3050. * IN hUID - Handle to a CSP
  3051. * IN hKey - Handle to a key
  3052. * IN dwFlags - Flags values
  3053. *
  3054. * Returns:
  3055. */
  3056. DWORD
  3057. InflateKey(
  3058. IN PNTAGKeyList pTmpKey)
  3059. {
  3060. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  3061. BYTE *pbRealKey = NULL;
  3062. // if space for the key table has been allocated previously
  3063. // then free it
  3064. if (pTmpKey->pData != NULL)
  3065. {
  3066. ASSERT(0 != pTmpKey->cbDataLen);
  3067. _nt_free(pTmpKey->pData, pTmpKey->cbDataLen);
  3068. pTmpKey->cbDataLen = 0;
  3069. }
  3070. else
  3071. {
  3072. ASSERT(pTmpKey->cbDataLen == 0);
  3073. }
  3074. // determine the algorithm to be used
  3075. switch (pTmpKey->Algid)
  3076. {
  3077. #ifdef CSP_USE_RC2
  3078. case CALG_RC2:
  3079. pTmpKey->pData = (BYTE *)_nt_malloc(RC2_TABLESIZE);
  3080. if (NULL == pTmpKey->pData)
  3081. {
  3082. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3083. return NTF_FAILED;
  3084. }
  3085. pbRealKey = (BYTE *)_nt_malloc(pTmpKey->cbKeyLen
  3086. + pTmpKey->cbSaltLen);
  3087. if (NULL == pbRealKey)
  3088. {
  3089. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3090. goto ErrorExit;
  3091. }
  3092. memcpy(pbRealKey, pTmpKey->pKeyValue, pTmpKey->cbKeyLen);
  3093. memcpy(pbRealKey+pTmpKey->cbKeyLen, pTmpKey->rgbSalt,
  3094. pTmpKey->cbSaltLen);
  3095. pTmpKey->cbDataLen = RC2_TABLESIZE;
  3096. RC2KeyEx((WORD *)pTmpKey->pData,
  3097. pbRealKey,
  3098. pTmpKey->cbKeyLen + pTmpKey->cbSaltLen,
  3099. pTmpKey->EffectiveKeyLen);
  3100. break;
  3101. #endif
  3102. #ifdef CSP_USE_RC4
  3103. case CALG_RC4:
  3104. pTmpKey->pData = (BYTE *)_nt_malloc(sizeof(RC4_KEYSTRUCT));
  3105. if (NULL == pTmpKey->pData)
  3106. {
  3107. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3108. goto ErrorExit;
  3109. }
  3110. pbRealKey = (BYTE *)_nt_malloc(pTmpKey->cbKeyLen
  3111. + pTmpKey->cbSaltLen);
  3112. if (NULL == pbRealKey)
  3113. {
  3114. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3115. goto ErrorExit;
  3116. }
  3117. memcpy(pbRealKey, pTmpKey->pKeyValue, pTmpKey->cbKeyLen);
  3118. memcpy(pbRealKey+pTmpKey->cbKeyLen, pTmpKey->rgbSalt,
  3119. pTmpKey->cbSaltLen);
  3120. pTmpKey->cbDataLen = sizeof(RC4_KEYSTRUCT);
  3121. rc4_key((struct RC4_KEYSTRUCT *)pTmpKey->pData,
  3122. pTmpKey->cbKeyLen+pTmpKey->cbSaltLen,
  3123. pbRealKey);
  3124. break;
  3125. #endif
  3126. #ifdef CSP_USE_DES
  3127. case CALG_DES:
  3128. pTmpKey->pData = (BYTE *)_nt_malloc(DES_TABLESIZE);
  3129. if (NULL == pTmpKey->pData)
  3130. {
  3131. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3132. goto ErrorExit;
  3133. }
  3134. pTmpKey->cbDataLen = DES_TABLESIZE;
  3135. deskey((DESTable *)pTmpKey->pData, pTmpKey->pKeyValue);
  3136. break;
  3137. #endif
  3138. #ifdef CSP_USE_3DES
  3139. case CALG_3DES_112:
  3140. pTmpKey->pData = (BYTE *)_nt_malloc(DES3_TABLESIZE);
  3141. if (NULL == pTmpKey->pData)
  3142. {
  3143. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3144. goto ErrorExit;
  3145. }
  3146. pTmpKey->cbDataLen = DES3_TABLESIZE;
  3147. tripledes2key((PDES3TABLE)pTmpKey->pData, pTmpKey->pKeyValue);
  3148. break;
  3149. case CALG_3DES:
  3150. pTmpKey->pData = (BYTE *)_nt_malloc(DES3_TABLESIZE);
  3151. if (NULL == pTmpKey->pData)
  3152. {
  3153. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3154. goto ErrorExit;
  3155. }
  3156. pTmpKey->cbDataLen = DES3_TABLESIZE;
  3157. tripledes3key((PDES3TABLE)pTmpKey->pData, pTmpKey->pKeyValue);
  3158. break;
  3159. #endif
  3160. #ifdef CSP_USE_SSL3
  3161. case CALG_SSL3_MASTER:
  3162. case CALG_PCT1_MASTER:
  3163. case CALG_SCHANNEL_MAC_KEY:
  3164. break;
  3165. #endif
  3166. #ifdef CSP_USE_AES
  3167. case CALG_AES_128:
  3168. pTmpKey->pData = (BYTE *)_nt_malloc(AES_TABLESIZE);
  3169. if (NULL == pTmpKey->pData)
  3170. {
  3171. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3172. goto ErrorExit;
  3173. }
  3174. pTmpKey->cbDataLen = AES_TABLESIZE;
  3175. aeskey((AESTable *)pTmpKey->pData, pTmpKey->pKeyValue, CRYPT_AES128_ROUNDS);
  3176. break;
  3177. case CALG_AES_192:
  3178. pTmpKey->pData = (BYTE *)_nt_malloc(AES_TABLESIZE);
  3179. if (NULL == pTmpKey->pData)
  3180. {
  3181. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3182. goto ErrorExit;
  3183. }
  3184. pTmpKey->cbDataLen = AES_TABLESIZE;
  3185. aeskey((AESTable *)pTmpKey->pData, pTmpKey->pKeyValue, CRYPT_AES192_ROUNDS);
  3186. break;
  3187. case CALG_AES_256:
  3188. pTmpKey->pData = (BYTE *)_nt_malloc(AES_TABLESIZE);
  3189. if (NULL == pTmpKey->pData)
  3190. {
  3191. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3192. goto ErrorExit;
  3193. }
  3194. pTmpKey->cbDataLen = AES_TABLESIZE;
  3195. aeskey((AESTable *)pTmpKey->pData, pTmpKey->pKeyValue, CRYPT_AES256_ROUNDS);
  3196. break;
  3197. #endif
  3198. default:
  3199. dwReturn = (DWORD)NTE_BAD_TYPE;
  3200. goto ErrorExit;
  3201. }
  3202. dwReturn = ERROR_SUCCESS;
  3203. ErrorExit:
  3204. if (pbRealKey)
  3205. _nt_free(pbRealKey, pTmpKey->cbKeyLen + pTmpKey->cbSaltLen);
  3206. return dwReturn;
  3207. }
  3208. /*
  3209. - CPDestroyKey
  3210. -
  3211. * Purpose:
  3212. * Destroys the cryptographic key that is being referenced
  3213. * with the hKey parameter
  3214. *
  3215. *
  3216. * Parameters:
  3217. * IN hUID - Handle to a CSP
  3218. * IN hKey - Handle to a key
  3219. *
  3220. * Returns:
  3221. */
  3222. BOOL WINAPI
  3223. CPDestroyKey(
  3224. IN HCRYPTPROV hUID,
  3225. IN HCRYPTKEY hKey)
  3226. {
  3227. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  3228. PNTAGKeyList pTmpKey;
  3229. BOOL fRet;
  3230. DWORD dwSts;
  3231. EntryPoint
  3232. // check the user identification
  3233. if (NULL == NTLCheckList((HNTAG)hUID, USER_HANDLE))
  3234. {
  3235. dwReturn = (DWORD)NTE_BAD_UID;
  3236. goto ErrorExit;
  3237. }
  3238. dwSts = NTLValidate((HNTAG)hKey, hUID, SIGPUBKEY_HANDLE, &pTmpKey);
  3239. if (ERROR_SUCCESS != dwSts)
  3240. {
  3241. dwSts = NTLValidate((HNTAG)hKey, hUID, EXCHPUBKEY_HANDLE, &pTmpKey);
  3242. if (ERROR_SUCCESS != dwSts)
  3243. {
  3244. dwSts = NTLValidate((HNTAG)hKey, hUID, KEY_HANDLE, &pTmpKey);
  3245. if (ERROR_SUCCESS != dwSts)
  3246. {
  3247. // NTLValidate doesn't know what error to set
  3248. // so it set NTE_FAIL -- fix it up.
  3249. dwReturn = (dwSts == NTE_FAIL)
  3250. ? (DWORD)NTE_BAD_KEY
  3251. : dwSts;
  3252. goto ErrorExit;
  3253. }
  3254. }
  3255. }
  3256. // Remove from internal list first so others can't get to it, then free.
  3257. NTLDelete((HNTAG)hKey);
  3258. // scrub the memory where the key information was held
  3259. if (pTmpKey->pKeyValue)
  3260. {
  3261. ASSERT(pTmpKey->cbKeyLen);
  3262. memnuke(pTmpKey->pKeyValue, pTmpKey->cbKeyLen);
  3263. _nt_free(pTmpKey->pKeyValue, pTmpKey->cbKeyLen);
  3264. }
  3265. if (pTmpKey->pbParams)
  3266. _nt_free(pTmpKey->pbParams, pTmpKey->cbParams);
  3267. if (pTmpKey->pData)
  3268. {
  3269. ASSERT(pTmpKey->cbDataLen);
  3270. if ((CALG_SSL3_MASTER == pTmpKey->Algid) ||
  3271. (CALG_PCT1_MASTER == pTmpKey->Algid))
  3272. {
  3273. FreeSChKey((PSCH_KEY)pTmpKey->pData);
  3274. }
  3275. memnuke(pTmpKey->pData, pTmpKey->cbDataLen);
  3276. _nt_free(pTmpKey->pData, pTmpKey->cbDataLen);
  3277. }
  3278. _nt_free(pTmpKey, sizeof(NTAGKeyList));
  3279. dwReturn = ERROR_SUCCESS;
  3280. ErrorExit:
  3281. fRet = (ERROR_SUCCESS == dwReturn);
  3282. if (!fRet)
  3283. SetLastError(dwReturn);
  3284. return fRet;
  3285. }
  3286. /*
  3287. - CPGetUserKey
  3288. -
  3289. * Purpose:
  3290. * Gets a handle to a permanent user key
  3291. *
  3292. *
  3293. * Parameters:
  3294. * IN hUID - Handle to the user identifcation
  3295. * IN dwWhichKey - Specification of the key to retrieve
  3296. * OUT phKey - Pointer to key handle of retrieved key
  3297. *
  3298. * Returns:
  3299. */
  3300. BOOL WINAPI
  3301. CPGetUserKey(
  3302. IN HCRYPTPROV hUID,
  3303. IN DWORD dwWhichKey,
  3304. OUT HCRYPTKEY *phKey)
  3305. {
  3306. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  3307. PNTAGUserList pUser;
  3308. PNTAGKeyList pTmpKey;
  3309. ALG_ID Algid;
  3310. DWORD cb;
  3311. BYTE *pb;
  3312. BYTE bType;
  3313. DWORD dwExportability = 0;
  3314. BOOL fRet;
  3315. DWORD dwSts;
  3316. EntryPoint
  3317. // check the user identification
  3318. pUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  3319. if (NULL == pUser)
  3320. {
  3321. dwReturn = (DWORD)NTE_BAD_UID;
  3322. goto ErrorExit;
  3323. }
  3324. switch (dwWhichKey)
  3325. {
  3326. case AT_KEYEXCHANGE:
  3327. Algid = CALG_RSA_KEYX;
  3328. cb = pUser->ContInfo.ContLens.cbExchPub;
  3329. pb = pUser->ContInfo.pbExchPub;
  3330. if (pUser->ContInfo.fExchExportable)
  3331. dwExportability = CRYPT_EXPORTABLE;
  3332. bType = EXCHPUBKEY_HANDLE;
  3333. break;
  3334. case AT_SIGNATURE:
  3335. Algid = CALG_RSA_SIGN;
  3336. cb = pUser->ContInfo.ContLens.cbSigPub;
  3337. pb = pUser->ContInfo.pbSigPub;
  3338. if (pUser->ContInfo.fSigExportable)
  3339. dwExportability = CRYPT_EXPORTABLE;
  3340. bType = SIGPUBKEY_HANDLE;
  3341. break;
  3342. default:
  3343. dwReturn = (DWORD)NTE_BAD_KEY;
  3344. goto ErrorExit;
  3345. }
  3346. if (!ValidKeyAlgid(pUser, Algid))
  3347. {
  3348. dwReturn = (DWORD)NTE_BAD_TYPE;
  3349. goto ErrorExit;
  3350. }
  3351. if (0 == cb)
  3352. {
  3353. dwReturn = (DWORD)NTE_NO_KEY;
  3354. goto ErrorExit;
  3355. }
  3356. dwSts = MakeNewKey(Algid, dwExportability, cb, hUID, pb, FALSE, FALSE,
  3357. &pTmpKey);
  3358. if (ERROR_SUCCESS != dwSts)
  3359. {
  3360. dwReturn = dwSts;
  3361. goto ErrorExit;
  3362. }
  3363. dwSts = NTLMakeItem(phKey, bType, (void *)pTmpKey);
  3364. if (ERROR_SUCCESS != dwSts)
  3365. {
  3366. dwReturn = dwSts;
  3367. goto ErrorExit;
  3368. }
  3369. dwReturn = ERROR_SUCCESS;
  3370. ErrorExit:
  3371. fRet = (ERROR_SUCCESS == dwReturn);
  3372. if (!fRet)
  3373. SetLastError(dwReturn);
  3374. return fRet;
  3375. }
  3376. /*
  3377. - CPSetKeyParam
  3378. -
  3379. * Purpose:
  3380. * Allows applications to customize various aspects of the
  3381. * operations of a key
  3382. *
  3383. * Parameters:
  3384. * IN hUID - Handle to a CSP
  3385. * IN hKey - Handle to a key
  3386. * IN dwParam - Parameter number
  3387. * IN pbData - Pointer to data
  3388. * IN dwFlags - Flags values
  3389. *
  3390. * Returns:
  3391. */
  3392. BOOL WINAPI
  3393. CPSetKeyParam(
  3394. IN HCRYPTPROV hUID,
  3395. IN HCRYPTKEY hKey,
  3396. IN DWORD dwParam,
  3397. IN CONST BYTE *pbData,
  3398. IN DWORD dwFlags)
  3399. {
  3400. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  3401. PNTAGUserList pTmpUser;
  3402. PNTAGKeyList pTmpKey;
  3403. PCRYPT_DATA_BLOB psData;
  3404. DWORD *pdw;
  3405. DWORD dw;
  3406. BOOL fRet;
  3407. DWORD dwSts;
  3408. EntryPoint
  3409. if ((dwFlags & ~CRYPT_SERVER) != 0)
  3410. {
  3411. dwReturn = (DWORD)NTE_BAD_FLAGS;
  3412. goto ErrorExit;
  3413. }
  3414. // check the user identification
  3415. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  3416. if (NULL == pTmpUser)
  3417. {
  3418. dwReturn = (DWORD)NTE_BAD_UID;
  3419. goto ErrorExit;
  3420. }
  3421. dwSts = NTLValidate((HNTAG)hKey, hUID, KEY_HANDLE, &pTmpKey);
  3422. if (ERROR_SUCCESS != dwSts)
  3423. {
  3424. dwSts = NTLValidate((HNTAG)hKey, hUID, SIGPUBKEY_HANDLE, &pTmpKey);
  3425. if (ERROR_SUCCESS != dwSts)
  3426. {
  3427. dwSts = NTLValidate((HNTAG)hKey, hUID,
  3428. EXCHPUBKEY_HANDLE, &pTmpKey);
  3429. if (ERROR_SUCCESS != dwSts)
  3430. {
  3431. // NTLValidate doesn't know what error to set
  3432. // so it set NTE_FAIL -- fix it up.
  3433. dwReturn = (dwSts == NTE_FAIL)
  3434. ? (DWORD)NTE_BAD_KEY
  3435. : dwSts;
  3436. goto ErrorExit;
  3437. }
  3438. }
  3439. }
  3440. switch (dwParam)
  3441. {
  3442. case KP_IV:
  3443. memcpy(pTmpKey->IV, pbData, RC2_BLOCKLEN);
  3444. break;
  3445. case KP_SALT:
  3446. if ((CALG_RC2 != pTmpKey->Algid) && (CALG_RC4 != pTmpKey->Algid))
  3447. {
  3448. dwReturn = (DWORD)NTE_BAD_KEY;
  3449. goto ErrorExit;
  3450. }
  3451. if (pbData == NULL)
  3452. {
  3453. dwReturn = ERROR_INVALID_PARAMETER;
  3454. goto ErrorExit;
  3455. }
  3456. if ((POLICY_MS_DEF == pTmpUser->dwCspTypeId)
  3457. || (POLICY_MS_STRONG == pTmpUser->dwCspTypeId))
  3458. {
  3459. pTmpKey->cbSaltLen = DEFAULT_WEAK_SALT_LENGTH;
  3460. }
  3461. else
  3462. {
  3463. pTmpKey->cbSaltLen = DEFAULT_STRONG_SALT_LENGTH;
  3464. }
  3465. if (pTmpKey->cbSaltLen)
  3466. CopyMemory(pTmpKey->rgbSalt, pbData, pTmpKey->cbSaltLen);
  3467. dwSts = InflateKey(pTmpKey);
  3468. if (ERROR_SUCCESS != dwSts)
  3469. {
  3470. dwReturn = dwSts;
  3471. goto ErrorExit;
  3472. }
  3473. break;
  3474. case KP_SALT_EX:
  3475. if ((CALG_RC2 != pTmpKey->Algid) && (CALG_RC4 != pTmpKey->Algid))
  3476. {
  3477. dwReturn = (DWORD)NTE_BAD_KEY;
  3478. goto ErrorExit;
  3479. }
  3480. psData = (PCRYPT_DATA_BLOB)pbData;
  3481. if (pbData == NULL)
  3482. {
  3483. dwReturn = ERROR_INVALID_PARAMETER;
  3484. goto ErrorExit;
  3485. }
  3486. if (psData->cbData > MAX_SALT_LEN)
  3487. {
  3488. dwReturn = NTE_BAD_DATA;
  3489. goto ErrorExit;
  3490. }
  3491. pTmpKey->cbSaltLen = psData->cbData;
  3492. CopyMemory(pTmpKey->rgbSalt, psData->pbData, pTmpKey->cbSaltLen);
  3493. dwSts = InflateKey(pTmpKey);
  3494. if (ERROR_SUCCESS != dwSts)
  3495. {
  3496. dwReturn = dwSts;
  3497. goto ErrorExit;
  3498. }
  3499. break;
  3500. case KP_PADDING:
  3501. if (*((DWORD *) pbData) != PKCS5_PADDING)
  3502. {
  3503. dwReturn = (DWORD)NTE_BAD_DATA;
  3504. goto ErrorExit;
  3505. }
  3506. break;
  3507. case KP_MODE:
  3508. if ((CALG_RSA_SIGN == pTmpKey->Algid) ||
  3509. (CALG_RSA_KEYX == pTmpKey->Algid))
  3510. {
  3511. dwReturn = (DWORD)NTE_BAD_KEY;
  3512. goto ErrorExit;
  3513. }
  3514. if (*pbData != CRYPT_MODE_CBC &&
  3515. *pbData != CRYPT_MODE_ECB &&
  3516. *pbData != CRYPT_MODE_CFB &&
  3517. *pbData != CRYPT_MODE_OFB)
  3518. {
  3519. dwReturn = (DWORD)NTE_BAD_DATA;
  3520. goto ErrorExit;
  3521. }
  3522. pTmpKey->Mode = *((DWORD *) pbData);
  3523. break;
  3524. case KP_MODE_BITS:
  3525. dw = *((DWORD *) pbData);
  3526. if ((dw == 0) || (dw > 64)) // if 0 or larger than the blocklength
  3527. {
  3528. dwReturn = (DWORD)NTE_BAD_DATA;
  3529. goto ErrorExit;
  3530. }
  3531. pTmpKey->ModeBits = dw;
  3532. break;
  3533. case KP_PERMISSIONS:
  3534. {
  3535. DWORD dwPerm = *(LPDWORD)pbData;
  3536. if (0 != (dwPerm & ~(CRYPT_ENCRYPT|CRYPT_DECRYPT|CRYPT_EXPORT|
  3537. CRYPT_READ|CRYPT_WRITE|CRYPT_MAC|CRYPT_ARCHIVE)))
  3538. {
  3539. dwReturn = (DWORD)NTE_BAD_FLAGS;
  3540. goto ErrorExit;
  3541. }
  3542. // the exportability of a key may not be changed, but it may be ignored.
  3543. if (0 != (dwPerm & CRYPT_EXPORT)
  3544. && 0 == (pTmpKey->Permissions & CRYPT_EXPORT))
  3545. {
  3546. dwReturn = (DWORD)NTE_BAD_DATA;
  3547. goto ErrorExit;
  3548. }
  3549. if (0 != (dwPerm & CRYPT_ARCHIVE)
  3550. && 0 == (pTmpKey->Permissions & CRYPT_ARCHIVE))
  3551. {
  3552. dwReturn = (DWORD)NTE_BAD_DATA;
  3553. goto ErrorExit;
  3554. }
  3555. dwPerm &= ~(CRYPT_ARCHIVE | CRYPT_EXPORT);
  3556. dwPerm |= pTmpKey->Permissions & (CRYPT_ARCHIVE | CRYPT_EXPORT);
  3557. pTmpKey->Permissions = dwPerm;
  3558. break;
  3559. }
  3560. case KP_EFFECTIVE_KEYLEN:
  3561. if (CALG_RC2 != pTmpKey->Algid)
  3562. {
  3563. dwReturn = (DWORD)NTE_BAD_KEY;
  3564. goto ErrorExit;
  3565. }
  3566. pdw = (DWORD*)pbData;
  3567. if (*pdw < RC2_MIN_EFFECTIVE_KEYLEN)
  3568. {
  3569. dwReturn = (DWORD)NTE_BAD_DATA;
  3570. goto ErrorExit;
  3571. }
  3572. if (POLICY_MS_DEF == pTmpUser->dwCspTypeId)
  3573. {
  3574. if (*pdw > RC2_MAX_WEAK_EFFECTIVE_KEYLEN)
  3575. {
  3576. dwReturn = (DWORD)NTE_BAD_DATA;
  3577. goto ErrorExit;
  3578. }
  3579. }
  3580. else
  3581. {
  3582. if (*pdw > RC2_MAX_STRONG_EFFECTIVE_KEYLEN)
  3583. {
  3584. dwReturn = (DWORD)NTE_BAD_DATA;
  3585. goto ErrorExit;
  3586. }
  3587. }
  3588. pTmpKey->EffectiveKeyLen = *pdw;
  3589. dwSts = InflateKey(pTmpKey);
  3590. if (ERROR_SUCCESS != dwSts)
  3591. {
  3592. dwReturn = dwSts;
  3593. goto ErrorExit;
  3594. }
  3595. break;
  3596. #ifdef CSP_USE_SSL3
  3597. case KP_CLIENT_RANDOM:
  3598. case KP_SERVER_RANDOM:
  3599. case KP_CERTIFICATE:
  3600. case KP_CLEAR_KEY:
  3601. case KP_SCHANNEL_ALG:
  3602. if (PROV_RSA_SCHANNEL != pTmpUser->dwProvType)
  3603. {
  3604. dwReturn = (DWORD)NTE_BAD_TYPE;
  3605. goto ErrorExit;
  3606. }
  3607. dwSts = SCHSetKeyParam(pTmpUser, pTmpKey, dwParam, pbData);
  3608. if (ERROR_SUCCESS != dwSts)
  3609. {
  3610. dwReturn = dwSts;
  3611. goto ErrorExit;
  3612. }
  3613. break;
  3614. #endif // CSP_USE_SSL3
  3615. case KP_OAEP_PARAMS:
  3616. if (CALG_RSA_KEYX != pTmpKey->Algid)
  3617. {
  3618. dwReturn = (DWORD)NTE_BAD_KEY;
  3619. goto ErrorExit;
  3620. }
  3621. psData = (PCRYPT_DATA_BLOB)pbData;
  3622. if (pbData == NULL)
  3623. {
  3624. dwReturn = ERROR_INVALID_PARAMETER;
  3625. goto ErrorExit;
  3626. }
  3627. // free salt if it already exists
  3628. if (NULL != pTmpKey->pbParams)
  3629. {
  3630. _nt_free(pTmpKey->pbParams, pTmpKey->cbParams);
  3631. pTmpKey->pbParams = NULL;
  3632. }
  3633. pTmpKey->cbParams = psData->cbData;
  3634. // alloc variable size
  3635. pTmpKey->pbParams = (BYTE *)_nt_malloc(pTmpKey->cbParams);
  3636. if (NULL == pTmpKey->pbParams)
  3637. {
  3638. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  3639. pTmpKey->cbParams = 0;
  3640. goto ErrorExit;
  3641. }
  3642. CopyMemory(pTmpKey->pbParams, psData->pbData, pTmpKey->cbParams);
  3643. break;
  3644. #ifdef CSP_USE_SSL3
  3645. case KP_HIGHEST_VERSION:
  3646. if ((CALG_SSL3_MASTER != pTmpKey->Algid) &&
  3647. (CALG_TLS1_MASTER != pTmpKey->Algid))
  3648. {
  3649. dwReturn = (DWORD)NTE_BAD_KEY;
  3650. goto ErrorExit;
  3651. }
  3652. if (pbData == NULL)
  3653. {
  3654. dwReturn = ERROR_INVALID_PARAMETER;
  3655. goto ErrorExit;
  3656. }
  3657. if (dwFlags & CRYPT_SERVER)
  3658. {
  3659. if ((CALG_SSL3_MASTER == pTmpKey->Algid)
  3660. && (*(DWORD *)pbData >= 0x301))
  3661. {
  3662. // We're a server doing SSL3, and we also support TLS1.
  3663. // If the pre_master_secret contains a version number
  3664. // greater than or equal to TLS1, then abort the connection.
  3665. if (MAKEWORD(pTmpKey->pKeyValue[1], pTmpKey->pKeyValue[0]) >= 0x301)
  3666. {
  3667. dwReturn = (DWORD)NTE_BAD_VER;
  3668. goto ErrorExit;
  3669. }
  3670. }
  3671. }
  3672. else
  3673. {
  3674. pTmpKey->pKeyValue[0] = HIBYTE(*(DWORD *)pbData);
  3675. pTmpKey->pKeyValue[1] = LOBYTE(*(DWORD *)pbData);
  3676. }
  3677. break;
  3678. #endif // CSP_USE_SSL3
  3679. default:
  3680. dwReturn = (DWORD)NTE_BAD_TYPE;
  3681. goto ErrorExit;
  3682. }
  3683. dwReturn = ERROR_SUCCESS;
  3684. ErrorExit:
  3685. fRet = (ERROR_SUCCESS == dwReturn);
  3686. if (!fRet)
  3687. SetLastError(dwReturn);
  3688. return fRet;
  3689. }
  3690. /*
  3691. - CPGetKeyParam
  3692. -
  3693. * Purpose:
  3694. * Allows applications to get various aspects of the
  3695. * operations of a key
  3696. *
  3697. * Parameters:
  3698. * IN hUID - Handle to a CSP
  3699. * IN hKey - Handle to a key
  3700. * IN dwParam - Parameter number
  3701. * IN pbData - Pointer to data
  3702. * IN pdwDataLen - Length of parameter data
  3703. * IN dwFlags - Flags values
  3704. *
  3705. * Returns:
  3706. */
  3707. BOOL WINAPI
  3708. CPGetKeyParam(
  3709. IN HCRYPTPROV hUID,
  3710. IN HCRYPTKEY hKey,
  3711. IN DWORD dwParam,
  3712. IN BYTE *pbData,
  3713. IN DWORD *pwDataLen,
  3714. IN DWORD dwFlags)
  3715. {
  3716. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  3717. PNTAGUserList pTmpUser;
  3718. PNTAGKeyList pTmpKey;
  3719. BSAFE_PUB_KEY *pBsafePubKey;
  3720. DWORD *pdw;
  3721. BOOL fRet;
  3722. DWORD dwSts;
  3723. EntryPoint
  3724. if (dwFlags != 0)
  3725. {
  3726. dwReturn = (DWORD)NTE_BAD_FLAGS;
  3727. goto ErrorExit;
  3728. }
  3729. // check the user identification
  3730. pTmpUser = NTLCheckList((HNTAG)hUID, USER_HANDLE);
  3731. if (NULL == pTmpUser)
  3732. {
  3733. dwReturn = (DWORD)NTE_BAD_UID;
  3734. goto ErrorExit;
  3735. }
  3736. dwSts = NTLValidate((HNTAG)hKey, hUID, KEY_HANDLE, &pTmpKey);
  3737. if (ERROR_SUCCESS != dwSts)
  3738. {
  3739. dwSts = NTLValidate((HNTAG)hKey, hUID, SIGPUBKEY_HANDLE, &pTmpKey);
  3740. if (ERROR_SUCCESS != dwSts)
  3741. {
  3742. dwSts = NTLValidate((HNTAG)hKey, hUID,
  3743. EXCHPUBKEY_HANDLE, &pTmpKey);
  3744. if (ERROR_SUCCESS != dwSts)
  3745. {
  3746. // NTLValidate doesn't know what error to set
  3747. // so it set NTE_FAIL -- fix it up.
  3748. dwReturn = (dwSts == NTE_FAIL)
  3749. ? (DWORD)NTE_BAD_KEY
  3750. : dwSts;
  3751. goto ErrorExit;
  3752. }
  3753. }
  3754. }
  3755. if (pwDataLen == NULL)
  3756. {
  3757. dwReturn = ERROR_INVALID_PARAMETER;
  3758. goto ErrorExit;
  3759. }
  3760. switch (dwParam)
  3761. {
  3762. case KP_IV:
  3763. if (pbData == NULL || *pwDataLen < RC2_BLOCKLEN)
  3764. {
  3765. *pwDataLen = RC2_BLOCKLEN;
  3766. if (pbData == NULL)
  3767. dwReturn = ERROR_SUCCESS;
  3768. else
  3769. dwReturn = ERROR_MORE_DATA;
  3770. goto ErrorExit;
  3771. }
  3772. memcpy(pbData, pTmpKey->IV, RC2_BLOCKLEN);
  3773. *pwDataLen = RC2_BLOCKLEN;
  3774. break;
  3775. case KP_SALT:
  3776. if ((CALG_RC2 != pTmpKey->Algid) && (CALG_RC4 != pTmpKey->Algid))
  3777. {
  3778. if ((CALG_DES == pTmpKey->Algid)
  3779. || (CALG_3DES == pTmpKey->Algid)
  3780. || (CALG_3DES_112 == pTmpKey->Algid))
  3781. {
  3782. *pwDataLen = 0;
  3783. dwReturn = ERROR_SUCCESS;
  3784. goto ErrorExit;
  3785. }
  3786. else
  3787. {
  3788. dwReturn = (DWORD)NTE_BAD_KEY;
  3789. goto ErrorExit;
  3790. }
  3791. }
  3792. if (pbData == NULL || (*pwDataLen < pTmpKey->cbSaltLen))
  3793. {
  3794. *pwDataLen = pTmpKey->cbSaltLen;
  3795. if (pbData == NULL)
  3796. dwReturn = ERROR_SUCCESS;
  3797. else
  3798. dwReturn = ERROR_MORE_DATA;
  3799. goto ErrorExit;
  3800. }
  3801. CopyMemory(pbData, pTmpKey->rgbSalt, pTmpKey->cbSaltLen);
  3802. *pwDataLen = pTmpKey->cbSaltLen;
  3803. break;
  3804. case KP_PADDING:
  3805. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  3806. {
  3807. *pwDataLen = sizeof(DWORD);
  3808. if (pbData == NULL)
  3809. dwReturn = ERROR_SUCCESS;
  3810. else
  3811. dwReturn = ERROR_MORE_DATA;
  3812. goto ErrorExit;
  3813. }
  3814. *((DWORD *) pbData) = PKCS5_PADDING;
  3815. *pwDataLen = sizeof(DWORD);
  3816. break;
  3817. case KP_MODE:
  3818. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  3819. {
  3820. *pwDataLen = sizeof(DWORD);
  3821. if (pbData == NULL)
  3822. dwReturn = ERROR_SUCCESS;
  3823. else
  3824. dwReturn = ERROR_MORE_DATA;
  3825. goto ErrorExit;
  3826. }
  3827. *((DWORD *) pbData) = pTmpKey->Mode;
  3828. *pwDataLen = sizeof(DWORD);
  3829. break;
  3830. case KP_MODE_BITS:
  3831. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  3832. {
  3833. *pwDataLen = sizeof(DWORD);
  3834. if (pbData == NULL)
  3835. dwReturn = ERROR_SUCCESS;
  3836. else
  3837. dwReturn = ERROR_MORE_DATA;
  3838. goto ErrorExit;
  3839. }
  3840. *((DWORD *)pbData) = pTmpKey->ModeBits;
  3841. *pwDataLen = sizeof(DWORD);
  3842. break;
  3843. case KP_PERMISSIONS:
  3844. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  3845. {
  3846. *pwDataLen = sizeof(DWORD);
  3847. if (pbData == NULL)
  3848. dwReturn = ERROR_SUCCESS;
  3849. else
  3850. dwReturn = ERROR_MORE_DATA;
  3851. goto ErrorExit;
  3852. }
  3853. *((DWORD *) pbData) = pTmpKey->Permissions;
  3854. *pwDataLen = sizeof(DWORD);
  3855. break;
  3856. case KP_ALGID:
  3857. if (pbData == NULL || *pwDataLen < sizeof(ALG_ID))
  3858. {
  3859. *pwDataLen = sizeof(ALG_ID);
  3860. if (pbData == NULL)
  3861. dwReturn = ERROR_SUCCESS;
  3862. else
  3863. dwReturn = ERROR_MORE_DATA;
  3864. goto ErrorExit;
  3865. }
  3866. *((ALG_ID *) pbData) = pTmpKey->Algid;
  3867. *pwDataLen = sizeof(ALG_ID);
  3868. break;
  3869. case KP_KEYLEN:
  3870. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  3871. {
  3872. *pwDataLen = sizeof(DWORD);
  3873. if (pbData == NULL)
  3874. dwReturn = ERROR_SUCCESS;
  3875. else
  3876. dwReturn = ERROR_MORE_DATA;
  3877. goto ErrorExit;
  3878. }
  3879. // ALWAYS report keylen in BITS
  3880. if ((HNTAG_TO_HTYPE(hKey) == SIGPUBKEY_HANDLE) ||
  3881. (HNTAG_TO_HTYPE(hKey) == EXCHPUBKEY_HANDLE))
  3882. {
  3883. pBsafePubKey = (BSAFE_PUB_KEY *) pTmpKey->pKeyValue;
  3884. if (pBsafePubKey == NULL)
  3885. {
  3886. dwReturn = (DWORD)NTE_NO_KEY;
  3887. goto ErrorExit;
  3888. }
  3889. *((DWORD *) pbData) = pBsafePubKey->bitlen;
  3890. }
  3891. else
  3892. {
  3893. switch (pTmpKey->Algid)
  3894. {
  3895. #ifdef CSP_USE_DES
  3896. case CALG_DES:
  3897. *((DWORD *) pbData) = (DES_KEYSIZE) * 8;
  3898. break;
  3899. #endif
  3900. #ifdef CSP_USE_3DES
  3901. case CALG_3DES_112:
  3902. *((DWORD *) pbData) = (DES2_KEYSIZE) * 8;
  3903. break;
  3904. case CALG_3DES:
  3905. *((DWORD *) pbData) = (DES3_KEYSIZE) * 8;
  3906. break;
  3907. #endif
  3908. default:
  3909. *((DWORD *) pbData) = pTmpKey->cbKeyLen * 8;
  3910. }
  3911. }
  3912. *pwDataLen = sizeof(DWORD);
  3913. break;
  3914. case KP_BLOCKLEN:
  3915. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  3916. {
  3917. *pwDataLen = sizeof(DWORD);
  3918. if (pbData == NULL)
  3919. dwReturn = ERROR_SUCCESS;
  3920. else
  3921. dwReturn = ERROR_MORE_DATA;
  3922. goto ErrorExit;
  3923. }
  3924. if ((HNTAG_TO_HTYPE(hKey) == SIGPUBKEY_HANDLE) ||
  3925. (HNTAG_TO_HTYPE(hKey) == EXCHPUBKEY_HANDLE))
  3926. {
  3927. pBsafePubKey = (BSAFE_PUB_KEY *) pTmpKey->pKeyValue;
  3928. if (pBsafePubKey == NULL)
  3929. {
  3930. dwReturn = (DWORD)NTE_NO_KEY;
  3931. goto ErrorExit;
  3932. }
  3933. *(DWORD *)pbData = pBsafePubKey->bitlen;
  3934. *pwDataLen = sizeof(DWORD);
  3935. }
  3936. else
  3937. {
  3938. switch (pTmpKey->Algid)
  3939. {
  3940. #ifdef CSP_USE_RC2
  3941. case CALG_RC2:
  3942. *((DWORD *) pbData) = RC2_BLOCKLEN * 8;
  3943. *pwDataLen = sizeof(DWORD);
  3944. break;
  3945. #endif
  3946. #ifdef CSP_USE_DES
  3947. case CALG_DES:
  3948. *((DWORD *) pbData) = DES_BLOCKLEN * 8;
  3949. *pwDataLen = sizeof(DWORD);
  3950. break;
  3951. #endif
  3952. #ifdef CSP_USE_3DES
  3953. case CALG_3DES_112:
  3954. case CALG_3DES:
  3955. *((DWORD *) pbData) = DES_BLOCKLEN * 8;
  3956. *pwDataLen = sizeof(DWORD);
  3957. break;
  3958. #endif
  3959. #ifdef CSP_USE_AES
  3960. case CALG_AES_128:
  3961. case CALG_AES_192:
  3962. case CALG_AES_256:
  3963. *((DWORD *) pbData) = pTmpKey->dwBlockLen * 8;
  3964. *pwDataLen = sizeof(DWORD);
  3965. break;
  3966. #endif
  3967. default:
  3968. *((DWORD *) pbData) = 0;
  3969. *pwDataLen = sizeof(DWORD);
  3970. }
  3971. }
  3972. break;
  3973. case KP_EFFECTIVE_KEYLEN:
  3974. if (CALG_RC2 != pTmpKey->Algid &&
  3975. CALG_DES != pTmpKey->Algid &&
  3976. CALG_3DES != pTmpKey->Algid &&
  3977. CALG_3DES_112 != pTmpKey->Algid)
  3978. {
  3979. dwReturn = (DWORD)NTE_BAD_KEY;
  3980. goto ErrorExit;
  3981. }
  3982. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  3983. {
  3984. *pwDataLen = sizeof(DWORD);
  3985. if (pbData == NULL)
  3986. dwReturn = ERROR_SUCCESS;
  3987. else
  3988. dwReturn = ERROR_MORE_DATA;
  3989. goto ErrorExit;
  3990. }
  3991. *pwDataLen = sizeof(DWORD);
  3992. pdw = (DWORD*)pbData;
  3993. switch (pTmpKey->Algid)
  3994. {
  3995. case CALG_RC2:
  3996. *pdw = pTmpKey->EffectiveKeyLen;
  3997. break;
  3998. case CALG_DES:
  3999. *pdw = (DES_KEYSIZE - 1) * 8;
  4000. break;
  4001. case CALG_3DES_112:
  4002. *pdw = (DES2_KEYSIZE - 2) * 8;
  4003. break;
  4004. case CALG_3DES:
  4005. *pdw = (DES3_KEYSIZE - 3) * 8;
  4006. break;
  4007. }
  4008. break;
  4009. default:
  4010. dwReturn = (DWORD)NTE_BAD_TYPE;
  4011. goto ErrorExit;
  4012. }
  4013. dwReturn = ERROR_SUCCESS;
  4014. ErrorExit:
  4015. fRet = (ERROR_SUCCESS == dwReturn);
  4016. if (!fRet)
  4017. SetLastError(dwReturn);
  4018. return fRet;
  4019. }
  4020. /*static*/ DWORD
  4021. DeletePersistedKey(
  4022. PNTAGUserList pTmpUser,
  4023. DWORD dwKeySpec)
  4024. {
  4025. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  4026. CHAR *pszExport;
  4027. CHAR *pszPrivKey;
  4028. CHAR *pszPubKey;
  4029. BOOL fMachineKeySet = FALSE;
  4030. DWORD dwSts;
  4031. if (pTmpUser->Rights & CRYPT_MACHINE_KEYSET)
  4032. fMachineKeySet = TRUE;
  4033. if (AT_SIGNATURE == dwKeySpec)
  4034. {
  4035. pszExport = "SExport";
  4036. pszPrivKey = "SPvK";
  4037. pszPubKey = "SPbK";
  4038. }
  4039. else if (AT_KEYEXCHANGE == dwKeySpec)
  4040. {
  4041. pszExport = "EExport";
  4042. pszPrivKey = "EPvK";
  4043. pszPubKey = "EPbK";
  4044. }
  4045. else
  4046. {
  4047. dwReturn = (DWORD)NTE_BAD_DATA;
  4048. goto ErrorExit;
  4049. }
  4050. // if protected store is available then delete the key from there
  4051. if (pTmpUser->pPStore)
  4052. {
  4053. dwSts = DeleteKeyFromProtectedStorage(
  4054. pTmpUser, &g_Strings, dwKeySpec,
  4055. fMachineKeySet, FALSE);
  4056. if (ERROR_SUCCESS != dwSts)
  4057. {
  4058. dwReturn = dwSts;
  4059. goto ErrorExit;
  4060. }
  4061. }
  4062. // delete stuff from the registry
  4063. RegDeleteValue(pTmpUser->hKeys, pszPrivKey);
  4064. RegDeleteValue(pTmpUser->hKeys, pszPubKey);
  4065. RegDeleteValue(pTmpUser->hKeys, pszExport);
  4066. dwReturn = ERROR_SUCCESS;
  4067. ErrorExit:
  4068. return dwReturn;
  4069. }
  4070. #ifdef USE_SGC
  4071. //
  4072. // Function to bring all the SGC checking together
  4073. //
  4074. /*static*/ DWORD
  4075. SetSGCInfo(
  4076. PNTAGUserList pTmpUser,
  4077. CONST BYTE *pbData)
  4078. {
  4079. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  4080. PCCERT_CONTEXT pCertContext = (PCCERT_CONTEXT)pbData;
  4081. BSAFE_PUB_KEY *pPubKey;
  4082. BYTE *pbMod;
  4083. DWORD dwSts;
  4084. // make sure the root certs are loaded
  4085. dwSts = LoadSGCRoots(&pTmpUser->CritSec);
  4086. if (ERROR_SUCCESS != dwSts)
  4087. {
  4088. dwReturn = dwSts;
  4089. goto ErrorExit;
  4090. }
  4091. // verify context means that you are on the client side
  4092. if (pTmpUser->Rights & CRYPT_VERIFYCONTEXT)
  4093. {
  4094. dwSts = SPQueryCFLevel(pCertContext, NULL, 0, 0,
  4095. (LPDWORD)&pTmpUser->dwSGCFlags);
  4096. if (ERROR_SUCCESS != dwSts)
  4097. {
  4098. dwReturn = dwSts;
  4099. goto ErrorExit;
  4100. }
  4101. // set the modulus of the SGC cert so it may be checked later
  4102. // when exporting the pre-master secret
  4103. dwSts = SGCAssignPubKey(pCertContext,
  4104. &pTmpUser->pbSGCKeyMod,
  4105. &pTmpUser->cbSGCKeyMod,
  4106. &pTmpUser->dwSGCKeyExpo);
  4107. if (ERROR_SUCCESS != dwSts)
  4108. {
  4109. dwReturn = dwSts;
  4110. goto ErrorExit;
  4111. }
  4112. }
  4113. else
  4114. {
  4115. // get a pointer to the exchange public key
  4116. if ((0 == pTmpUser->ContInfo.ContLens.cbExchPub)
  4117. || (NULL == pTmpUser->ContInfo.pbExchPub))
  4118. {
  4119. dwReturn = (DWORD)NTE_FAIL;
  4120. goto ErrorExit;
  4121. }
  4122. pPubKey = (BSAFE_PUB_KEY*)pTmpUser->ContInfo.pbExchPub;
  4123. pbMod = (BYTE*)pPubKey + sizeof(BSAFE_PUB_KEY);
  4124. dwSts = SPQueryCFLevel(pCertContext, pbMod, pPubKey->bitlen / 8,
  4125. pPubKey->pubexp,
  4126. (LPDWORD)&pTmpUser->dwSGCFlags);
  4127. if (ERROR_SUCCESS != dwSts)
  4128. {
  4129. dwReturn = dwSts;
  4130. goto ErrorExit;
  4131. }
  4132. }
  4133. if (0 == pTmpUser->dwSGCFlags)
  4134. {
  4135. dwReturn = (DWORD)NTE_FAIL;
  4136. goto ErrorExit;
  4137. }
  4138. dwReturn = ERROR_SUCCESS;
  4139. ErrorExit:
  4140. return dwReturn;
  4141. }
  4142. #endif
  4143. /*
  4144. - CPSetProvParam
  4145. -
  4146. * Purpose:
  4147. * Allows applications to customize various aspects of the
  4148. * operations of a provider
  4149. *
  4150. * Parameters:
  4151. * IN hUID - Handle to a CSP
  4152. * IN dwParam - Parameter number
  4153. * IN pbData - Pointer to data
  4154. * IN dwFlags - Flags values
  4155. *
  4156. * Returns:
  4157. */
  4158. BOOL WINAPI
  4159. CPSetProvParam(
  4160. IN HCRYPTPROV hUID,
  4161. IN DWORD dwParam,
  4162. IN CONST BYTE *pbData,
  4163. IN DWORD dwFlags)
  4164. {
  4165. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  4166. PNTAGUserList pTmpUser;
  4167. HCRYPTKEY hKey = 0;
  4168. BOOL fRet;
  4169. DWORD dwSts;
  4170. EntryPoint
  4171. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  4172. if (NULL == pTmpUser)
  4173. {
  4174. dwReturn = (DWORD)NTE_BAD_UID;
  4175. goto ErrorExit;
  4176. }
  4177. switch (dwParam)
  4178. {
  4179. case PP_KEYSET_SEC_DESCR:
  4180. if (0 != (dwFlags & ~(OWNER_SECURITY_INFORMATION
  4181. | GROUP_SECURITY_INFORMATION
  4182. | DACL_SECURITY_INFORMATION
  4183. | SACL_SECURITY_INFORMATION)))
  4184. {
  4185. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4186. goto ErrorExit;
  4187. }
  4188. if (!(dwFlags & OWNER_SECURITY_INFORMATION) &&
  4189. !(dwFlags & GROUP_SECURITY_INFORMATION) &&
  4190. !(dwFlags & DACL_SECURITY_INFORMATION) &&
  4191. !(dwFlags & SACL_SECURITY_INFORMATION))
  4192. {
  4193. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4194. goto ErrorExit;
  4195. }
  4196. // set the security descriptor for the hKey of the keyset
  4197. dwSts = SetSecurityOnContainer(pTmpUser->ContInfo.rgwszFileName,
  4198. pTmpUser->dwProvType,
  4199. pTmpUser->Rights & CRYPT_MACHINE_KEYSET,
  4200. (SECURITY_INFORMATION)dwFlags,
  4201. (PSECURITY_DESCRIPTOR)pbData);
  4202. if (ERROR_SUCCESS != dwSts)
  4203. {
  4204. dwReturn = dwSts;
  4205. goto ErrorExit;
  4206. }
  4207. break;
  4208. case PP_KEY_TYPE_SUBTYPE:
  4209. if (dwFlags != 0)
  4210. {
  4211. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4212. goto ErrorExit;
  4213. }
  4214. break;
  4215. case PP_UI_PROMPT:
  4216. if (dwFlags != 0)
  4217. {
  4218. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4219. goto ErrorExit;
  4220. }
  4221. if (pTmpUser->pPStore)
  4222. {
  4223. dwSts = SetUIPrompt(pTmpUser, (LPWSTR)pbData);
  4224. if (ERROR_SUCCESS != dwSts)
  4225. {
  4226. dwReturn = dwSts;
  4227. goto ErrorExit;
  4228. }
  4229. }
  4230. else
  4231. {
  4232. dwReturn = (DWORD)NTE_BAD_TYPE;
  4233. goto ErrorExit;
  4234. }
  4235. break;
  4236. case PP_DELETEKEY:
  4237. if (dwFlags != 0)
  4238. {
  4239. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4240. goto ErrorExit;
  4241. }
  4242. // check if it is a verify context
  4243. if (pTmpUser->Rights & CRYPT_VERIFYCONTEXT)
  4244. {
  4245. dwReturn = (DWORD)NTE_BAD_UID;
  4246. goto ErrorExit;
  4247. }
  4248. // check if the keys exists
  4249. if (!CPGetUserKey(hUID, *((DWORD*)pbData), &hKey))
  4250. {
  4251. dwReturn = GetLastError(); // (DWORD)NTE_NO_KEY
  4252. goto ErrorExit;
  4253. }
  4254. // destroy the key handle right away
  4255. if (!CPDestroyKey(hUID, hKey))
  4256. {
  4257. dwReturn = GetLastError();
  4258. goto ErrorExit;
  4259. }
  4260. // delete the key
  4261. dwSts = DeletePersistedKey(pTmpUser, *(DWORD*)pbData);
  4262. if (ERROR_SUCCESS != dwSts)
  4263. {
  4264. dwReturn = dwSts;
  4265. goto ErrorExit;
  4266. }
  4267. break;
  4268. case PP_SGC_INFO:
  4269. if (dwFlags != 0)
  4270. {
  4271. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4272. goto ErrorExit;
  4273. }
  4274. // check if it is an SChannel provider
  4275. if (PROV_RSA_SCHANNEL != pTmpUser->dwProvType)
  4276. {
  4277. dwReturn = (DWORD)NTE_BAD_TYPE;
  4278. goto ErrorExit;
  4279. }
  4280. #ifdef USE_SGC
  4281. // check if the SGC Info (cert) is good
  4282. dwSts = SetSGCInfo(pTmpUser, pbData);
  4283. if (ERROR_SUCCESS != dwSts)
  4284. {
  4285. dwReturn = dwSts; // (DWORD)NTE_FAIL
  4286. goto ErrorExit;
  4287. }
  4288. #endif
  4289. break;
  4290. #ifdef USE_HW_RNG
  4291. #ifdef _M_IX86
  4292. case PP_USE_HARDWARE_RNG:
  4293. if (dwFlags != 0)
  4294. {
  4295. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4296. goto ErrorExit;
  4297. }
  4298. dwSts = GetRNGDriverHandle(&(pTmpUser->hRNGDriver));
  4299. if (ERROR_SUCCESS != dwSts)
  4300. {
  4301. dwReturn = dwSts;
  4302. goto ErrorExit;
  4303. }
  4304. break;
  4305. #endif // _M_IX86
  4306. #endif // USE_HW_RNG
  4307. default:
  4308. dwReturn = (DWORD)NTE_BAD_TYPE;
  4309. goto ErrorExit;
  4310. }
  4311. dwReturn = ERROR_SUCCESS;
  4312. ErrorExit:
  4313. fRet = (ERROR_SUCCESS == dwReturn);
  4314. if (!fRet)
  4315. SetLastError(dwReturn);
  4316. return fRet;
  4317. }
  4318. /*
  4319. - CPGetProvParam
  4320. -
  4321. * Purpose:
  4322. * Allows applications to get various aspects of the
  4323. * operations of a provider
  4324. *
  4325. * Parameters:
  4326. * IN hUID - Handle to a CSP
  4327. * IN dwParam - Parameter number
  4328. * IN pbData - Pointer to data
  4329. * IN pdwDataLen - Length of parameter data
  4330. * IN dwFlags - Flags values
  4331. *
  4332. * Returns:
  4333. */
  4334. BOOL WINAPI
  4335. CPGetProvParam(
  4336. IN HCRYPTPROV hUID,
  4337. IN DWORD dwParam,
  4338. IN BYTE *pbData,
  4339. IN DWORD *pwDataLen,
  4340. IN DWORD dwFlags)
  4341. {
  4342. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  4343. PNTAGUserList pTmpUser;
  4344. PROV_ENUMALGS *pEnum = NULL;
  4345. PROV_ENUMALGS_EX *pEnumEx = NULL;
  4346. DWORD cbName = 0;
  4347. LPSTR pszName;
  4348. DWORD cbTmpData;
  4349. BOOL fRet;
  4350. DWORD dwSts;
  4351. EntryPoint
  4352. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  4353. if (NULL == pTmpUser)
  4354. {
  4355. dwReturn = (DWORD)NTE_BAD_UID;
  4356. goto ErrorExit;
  4357. }
  4358. if (pwDataLen == NULL)
  4359. {
  4360. dwReturn = ERROR_INVALID_PARAMETER;
  4361. goto ErrorExit;
  4362. }
  4363. switch (dwParam)
  4364. {
  4365. case PP_ENUMALGS:
  4366. if (PROV_RSA_SCHANNEL == pTmpUser->dwProvType)
  4367. {
  4368. if ((dwFlags & ~(CRYPT_FIRST | CRYPT_NEXT | CRYPT_SGC_ENUM)) != 0)
  4369. {
  4370. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4371. goto ErrorExit;
  4372. }
  4373. }
  4374. else
  4375. {
  4376. if ((dwFlags & ~(CRYPT_FIRST | CRYPT_NEXT)) != 0)
  4377. {
  4378. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4379. goto ErrorExit;
  4380. }
  4381. }
  4382. pEnumEx = g_AlgTables[pTmpUser->dwCspTypeId];
  4383. if (dwFlags & CRYPT_FIRST)
  4384. pTmpUser->dwEnumalgs = 0;
  4385. else if (0xFFFFFFFF == pTmpUser->dwEnumalgs)
  4386. {
  4387. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4388. goto ErrorExit;
  4389. }
  4390. if (pEnumEx[pTmpUser->dwEnumalgs].aiAlgid == 0)
  4391. {
  4392. dwReturn = ERROR_NO_MORE_ITEMS;
  4393. goto ErrorExit;
  4394. }
  4395. if (pbData == NULL || *pwDataLen < sizeof(PROV_ENUMALGS))
  4396. {
  4397. *pwDataLen = sizeof(PROV_ENUMALGS);
  4398. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4399. goto ErrorExit;
  4400. }
  4401. // each entry in ENUMALGS is of fixed size
  4402. pEnum = (PROV_ENUMALGS *)pbData;
  4403. pEnum->aiAlgid = pEnumEx[pTmpUser->dwEnumalgs].aiAlgid;
  4404. pEnum->dwBitLen = pEnumEx[pTmpUser->dwEnumalgs].dwDefaultLen;
  4405. pEnum->dwNameLen = pEnumEx[pTmpUser->dwEnumalgs].dwNameLen;
  4406. memcpy(pEnum->szName, pEnumEx[pTmpUser->dwEnumalgs].szName,
  4407. sizeof(pEnum->szName));
  4408. *pwDataLen = sizeof(PROV_ENUMALGS);
  4409. pTmpUser->dwEnumalgs++;
  4410. break;
  4411. case PP_ENUMALGS_EX:
  4412. if (PROV_RSA_SCHANNEL == pTmpUser->dwProvType)
  4413. {
  4414. if ((dwFlags & ~(CRYPT_FIRST | CRYPT_NEXT | CRYPT_SGC_ENUM)) != 0)
  4415. {
  4416. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4417. goto ErrorExit;
  4418. }
  4419. }
  4420. else
  4421. {
  4422. if ((dwFlags & ~(CRYPT_FIRST | CRYPT_NEXT)) != 0)
  4423. {
  4424. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4425. goto ErrorExit;
  4426. }
  4427. }
  4428. pEnumEx = g_AlgTables[pTmpUser->dwCspTypeId];
  4429. if (dwFlags & CRYPT_FIRST)
  4430. pTmpUser->dwEnumalgsEx = 0;
  4431. else if (0xFFFFFFFF == pTmpUser->dwEnumalgsEx)
  4432. {
  4433. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4434. goto ErrorExit;
  4435. }
  4436. if (pEnumEx[pTmpUser->dwEnumalgsEx].aiAlgid == 0)
  4437. {
  4438. dwReturn = ERROR_NO_MORE_ITEMS;
  4439. goto ErrorExit;
  4440. }
  4441. if (pbData == NULL || *pwDataLen < sizeof(pEnumEx[0]))
  4442. {
  4443. *pwDataLen = sizeof(pEnumEx[0]);
  4444. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4445. goto ErrorExit;
  4446. }
  4447. // each entry in ENUMALGSEX is of fixed size
  4448. memcpy(pbData, &pEnumEx[pTmpUser->dwEnumalgsEx], sizeof(pEnumEx[0]));
  4449. *pwDataLen = sizeof(pEnumEx[0]);
  4450. pTmpUser->dwEnumalgsEx++;
  4451. break;
  4452. case PP_ENUMCONTAINERS:
  4453. {
  4454. BOOL fMachineKeySet = pTmpUser->Rights & CRYPT_MACHINE_KEYSET;
  4455. if ((dwFlags & ~(CRYPT_FIRST | CRYPT_NEXT)) != 0)
  4456. {
  4457. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4458. goto ErrorExit;
  4459. }
  4460. if (dwFlags & CRYPT_FIRST)
  4461. {
  4462. if (0 != pTmpUser->ContInfo.hFind)
  4463. {
  4464. FindClose(pTmpUser->ContInfo.hFind);
  4465. pTmpUser->ContInfo.hFind = 0;
  4466. }
  4467. FreeEnumOldMachKeyEntries(&pTmpUser->ContInfo);
  4468. FreeEnumRegEntries(&pTmpUser->ContInfo);
  4469. pTmpUser->ContInfo.fCryptFirst = TRUE;
  4470. pTmpUser->ContInfo.fNoMoreFiles = FALSE;
  4471. }
  4472. else if (!pTmpUser->ContInfo.fCryptFirst)
  4473. {
  4474. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4475. goto ErrorExit;
  4476. }
  4477. dwSts = ERROR_SUCCESS;
  4478. if (!pTmpUser->ContInfo.fNoMoreFiles)
  4479. {
  4480. dwSts = GetNextContainer(pTmpUser->dwProvType,
  4481. fMachineKeySet,
  4482. dwFlags,
  4483. (LPSTR)pbData,
  4484. pwDataLen,
  4485. &pTmpUser->ContInfo.hFind);
  4486. }
  4487. // ?BUGBUG? This logic needs desperate cleaning!
  4488. if ((ERROR_SUCCESS != dwSts) || pTmpUser->ContInfo.fNoMoreFiles)
  4489. {
  4490. if ((ERROR_SUCCESS != dwSts) && (ERROR_NO_MORE_ITEMS != dwSts))
  4491. {
  4492. dwReturn = dwSts;
  4493. goto ErrorExit;
  4494. }
  4495. pTmpUser->ContInfo.fNoMoreFiles = TRUE;
  4496. if (fMachineKeySet)
  4497. {
  4498. dwSts = EnumOldMachineKeys(pTmpUser->dwProvType,
  4499. &pTmpUser->ContInfo);
  4500. if (ERROR_SUCCESS != dwSts)
  4501. {
  4502. if (ERROR_NO_MORE_ITEMS != dwSts)
  4503. {
  4504. dwReturn = dwSts;
  4505. goto ErrorExit;
  4506. }
  4507. }
  4508. }
  4509. dwSts = EnumRegKeys(&pTmpUser->ContInfo,
  4510. fMachineKeySet,
  4511. pTmpUser->dwProvType,
  4512. pbData,
  4513. pwDataLen);
  4514. if (ERROR_SUCCESS != dwSts)
  4515. {
  4516. dwReturn = dwSts;
  4517. goto ErrorExit;
  4518. }
  4519. cbTmpData = *pwDataLen;
  4520. if ((!fMachineKeySet)
  4521. || (0 != (dwSts = GetNextEnumedOldMachKeys(&pTmpUser->ContInfo,
  4522. fMachineKeySet,
  4523. pbData,
  4524. &cbTmpData))))
  4525. {
  4526. if (0 != (dwSts = GetNextEnumedRegKeys(&pTmpUser->ContInfo,
  4527. pbData,
  4528. pwDataLen)))
  4529. {
  4530. dwReturn = dwSts;
  4531. goto ErrorExit;
  4532. }
  4533. }
  4534. else
  4535. *pwDataLen = cbTmpData;
  4536. }
  4537. break;
  4538. }
  4539. case PP_IMPTYPE:
  4540. if (0 != dwFlags)
  4541. {
  4542. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4543. goto ErrorExit;
  4544. }
  4545. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  4546. {
  4547. *pwDataLen = sizeof(DWORD);
  4548. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4549. goto ErrorExit;
  4550. }
  4551. *pwDataLen = sizeof(DWORD);
  4552. *((DWORD *) pbData) = CRYPT_IMPL_SOFTWARE;
  4553. break;
  4554. case PP_NAME:
  4555. if (0 != dwFlags)
  4556. {
  4557. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4558. goto ErrorExit;
  4559. }
  4560. ASSERT(NULL != pTmpUser->szProviderName);
  4561. if (NULL != pTmpUser->szProviderName)
  4562. cbName = (lstrlen(pTmpUser->szProviderName) + 1) * sizeof(CHAR);
  4563. else
  4564. cbName = 0;
  4565. if (pbData == NULL || *pwDataLen < cbName)
  4566. {
  4567. *pwDataLen = cbName;
  4568. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4569. goto ErrorExit;
  4570. }
  4571. *pwDataLen = cbName;
  4572. memcpy(pbData, pTmpUser->szProviderName, cbName);
  4573. break;
  4574. case PP_VERSION:
  4575. if (dwFlags != 0)
  4576. {
  4577. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4578. goto ErrorExit;
  4579. }
  4580. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  4581. {
  4582. *pwDataLen = sizeof(DWORD);
  4583. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4584. goto ErrorExit;
  4585. }
  4586. *pwDataLen = sizeof(DWORD);
  4587. *((DWORD *) pbData) = 0x200; // ?BUGBUG? Symbolic?
  4588. break;
  4589. case PP_CONTAINER:
  4590. if (0 != dwFlags)
  4591. {
  4592. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4593. goto ErrorExit;
  4594. }
  4595. pszName = pTmpUser->ContInfo.pszUserName;
  4596. if (pbData == NULL || *pwDataLen < (strlen(pszName) + 1))
  4597. {
  4598. *pwDataLen = strlen(pszName) + 1;
  4599. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4600. goto ErrorExit;
  4601. }
  4602. *pwDataLen = strlen(pszName) + 1;
  4603. strcpy((LPSTR)pbData, pszName);
  4604. break;
  4605. case PP_UNIQUE_CONTAINER:
  4606. if (0 != dwFlags)
  4607. {
  4608. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4609. goto ErrorExit;
  4610. }
  4611. dwSts = GetUniqueContainerName(&pTmpUser->ContInfo,
  4612. pbData, pwDataLen);
  4613. if (ERROR_SUCCESS != dwSts)
  4614. {
  4615. dwReturn = dwSts;
  4616. goto ErrorExit;
  4617. }
  4618. break;
  4619. case PP_KEYSET_SEC_DESCR:
  4620. if (0 != (dwFlags & ~(OWNER_SECURITY_INFORMATION
  4621. | GROUP_SECURITY_INFORMATION
  4622. | DACL_SECURITY_INFORMATION
  4623. | SACL_SECURITY_INFORMATION)))
  4624. {
  4625. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4626. goto ErrorExit;
  4627. }
  4628. if (!(dwFlags & OWNER_SECURITY_INFORMATION) &&
  4629. !(dwFlags & GROUP_SECURITY_INFORMATION) &&
  4630. !(dwFlags & DACL_SECURITY_INFORMATION) &&
  4631. !(dwFlags & SACL_SECURITY_INFORMATION))
  4632. {
  4633. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4634. goto ErrorExit;
  4635. }
  4636. dwSts = GetSecurityOnContainer(pTmpUser->ContInfo.rgwszFileName,
  4637. pTmpUser->dwProvType,
  4638. pTmpUser->Rights & CRYPT_MACHINE_KEYSET,
  4639. (SECURITY_INFORMATION)dwFlags,
  4640. (PSECURITY_DESCRIPTOR)pbData,
  4641. pwDataLen);
  4642. if (ERROR_SUCCESS != dwSts)
  4643. {
  4644. dwReturn = dwSts;
  4645. goto ErrorExit;
  4646. }
  4647. break;
  4648. case PP_KEYSTORAGE:
  4649. if (dwFlags != 0)
  4650. {
  4651. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4652. goto ErrorExit;
  4653. }
  4654. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  4655. {
  4656. *pwDataLen = sizeof(DWORD);
  4657. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4658. goto ErrorExit;
  4659. }
  4660. *pwDataLen = sizeof(DWORD);
  4661. if (pTmpUser->pPStore)
  4662. *((DWORD*)pbData) = CRYPT_PSTORE
  4663. | CRYPT_UI_PROMPT
  4664. | CRYPT_SEC_DESCR;
  4665. else
  4666. *((DWORD*)pbData) = CRYPT_SEC_DESCR;
  4667. break;
  4668. case PP_PROVTYPE:
  4669. if (dwFlags != 0)
  4670. {
  4671. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4672. goto ErrorExit;
  4673. }
  4674. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  4675. {
  4676. *pwDataLen = sizeof(DWORD);
  4677. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4678. goto ErrorExit;
  4679. }
  4680. *pwDataLen = sizeof(DWORD);
  4681. *((DWORD*)pbData) = pTmpUser->dwProvType;
  4682. break;
  4683. case PP_KEYSET_TYPE:
  4684. if (dwFlags != 0)
  4685. {
  4686. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4687. goto ErrorExit;
  4688. }
  4689. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  4690. {
  4691. *pwDataLen = sizeof(DWORD);
  4692. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4693. goto ErrorExit;
  4694. }
  4695. *pwDataLen = sizeof(DWORD);
  4696. if (pTmpUser->Rights & CRYPT_MACHINE_KEYSET)
  4697. *(DWORD*)pbData = CRYPT_MACHINE_KEYSET;
  4698. else
  4699. *(DWORD*)pbData = 0;
  4700. break;
  4701. case PP_SIG_KEYSIZE_INC:
  4702. case PP_KEYX_KEYSIZE_INC:
  4703. if (dwFlags != 0)
  4704. {
  4705. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4706. goto ErrorExit;
  4707. }
  4708. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  4709. {
  4710. *pwDataLen = sizeof(DWORD);
  4711. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4712. goto ErrorExit;
  4713. }
  4714. *pwDataLen = sizeof(DWORD);
  4715. *((DWORD*)pbData) = RSA_KEYSIZE_INC;
  4716. break;
  4717. case PP_SGC_INFO:
  4718. if (dwFlags != 0)
  4719. {
  4720. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4721. goto ErrorExit;
  4722. }
  4723. // check if it is an SChannel provider
  4724. if (PROV_RSA_SCHANNEL != pTmpUser->dwProvType)
  4725. {
  4726. dwReturn = (DWORD)NTE_BAD_TYPE;
  4727. goto ErrorExit;
  4728. }
  4729. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  4730. {
  4731. *pwDataLen = sizeof(DWORD);
  4732. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4733. goto ErrorExit;
  4734. }
  4735. *pwDataLen = sizeof(DWORD);
  4736. // return the SGC Flags
  4737. #ifdef USE_SGC
  4738. *((DWORD*)pbData) = pTmpUser->dwSGCFlags;
  4739. #else
  4740. *((DWORD*)pbData) = 0;
  4741. #endif
  4742. break;
  4743. #ifdef USE_HW_RNG
  4744. #ifdef _M_IX86
  4745. case PP_USE_HARDWARE_RNG:
  4746. if (dwFlags != 0)
  4747. {
  4748. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4749. goto ErrorExit;
  4750. }
  4751. *pwDataLen = 0;
  4752. // check if the hardware RNG is available for use
  4753. dwSts = CheckIfRNGAvailable();
  4754. if (ERROR_SUCCESS != dwSts)
  4755. {
  4756. dwReturn = dwSts;
  4757. goto ErrorExit;
  4758. }
  4759. break;
  4760. #endif // _M_IX86
  4761. #endif // USE_HW_RNG
  4762. case PP_KEYSPEC:
  4763. if (dwFlags != 0)
  4764. {
  4765. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4766. goto ErrorExit;
  4767. }
  4768. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  4769. {
  4770. *pwDataLen = sizeof(DWORD);
  4771. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  4772. goto ErrorExit;
  4773. }
  4774. *pwDataLen = sizeof(DWORD);
  4775. if (PROV_RSA_SIG == pTmpUser->dwProvType)
  4776. *((DWORD*)pbData) = AT_SIGNATURE;
  4777. else if (PROV_RSA_FULL == pTmpUser->dwProvType)
  4778. *((DWORD*)pbData) = AT_SIGNATURE | AT_KEYEXCHANGE;
  4779. else if (PROV_RSA_SCHANNEL == pTmpUser->dwProvType)
  4780. *((DWORD*)pbData) = AT_KEYEXCHANGE;
  4781. break;
  4782. case PP_ENUMEX_SIGNING_PROT:
  4783. if (0 != dwFlags)
  4784. {
  4785. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4786. goto ErrorExit;
  4787. }
  4788. *pwDataLen = 0;
  4789. break;
  4790. default:
  4791. dwReturn = (DWORD)NTE_BAD_TYPE;
  4792. goto ErrorExit;
  4793. }
  4794. dwReturn = ERROR_SUCCESS;
  4795. ErrorExit:
  4796. fRet = (ERROR_SUCCESS == dwReturn);
  4797. if (!fRet)
  4798. SetLastError(dwReturn);
  4799. return fRet;
  4800. }
  4801. /*
  4802. - CPSetHashParam
  4803. -
  4804. * Purpose:
  4805. * Allows applications to customize various aspects of the
  4806. * operations of a hash
  4807. *
  4808. * Parameters:
  4809. * IN hUID - Handle to a CSP
  4810. * IN hHash - Handle to a hash
  4811. * IN dwParam - Parameter number
  4812. * IN pbData - Pointer to data
  4813. * IN dwFlags - Flags values
  4814. *
  4815. * Returns:
  4816. */
  4817. BOOL WINAPI
  4818. CPSetHashParam(
  4819. IN HCRYPTPROV hUID,
  4820. IN HCRYPTHASH hHash,
  4821. IN DWORD dwParam,
  4822. IN CONST BYTE *pbData,
  4823. IN DWORD dwFlags)
  4824. {
  4825. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  4826. PNTAGHashList pTmpHash;
  4827. PNTAGKeyList pTmpKey;
  4828. MD4_object *pMD4Hash;
  4829. MD5_object *pMD5Hash;
  4830. A_SHA_CTX *pSHAHash;
  4831. MACstate *pMAC;
  4832. PHMAC_INFO pHMACInfo;
  4833. BYTE *pb;
  4834. BOOL fRet;
  4835. DWORD dwSts;
  4836. EntryPoint
  4837. if (dwFlags != 0)
  4838. {
  4839. dwReturn = (DWORD)NTE_BAD_FLAGS;
  4840. goto ErrorExit;
  4841. }
  4842. // check the user identification
  4843. if (NTLCheckList((HNTAG)hUID, USER_HANDLE) == NULL)
  4844. {
  4845. dwReturn = (DWORD)NTE_BAD_UID;
  4846. goto ErrorExit;
  4847. }
  4848. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  4849. if (ERROR_SUCCESS != dwSts)
  4850. {
  4851. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_HASH : dwSts;
  4852. goto ErrorExit;
  4853. }
  4854. switch (dwParam)
  4855. {
  4856. case HP_HASHVAL:
  4857. switch (pTmpHash->Algid)
  4858. {
  4859. #ifdef CSP_USE_MD2
  4860. case CALG_MD2:
  4861. {
  4862. MD2_object *pMD2Hash;
  4863. pMD2Hash = (MD2_object *) pTmpHash->pHashData;
  4864. if (pMD2Hash->FinishFlag == TRUE)
  4865. {
  4866. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  4867. goto ErrorExit;
  4868. }
  4869. memcpy(&pMD2Hash->MD.state, pbData, MD2DIGESTLEN);
  4870. break;
  4871. }
  4872. #endif
  4873. #ifdef CSP_USE_MD4
  4874. case CALG_MD4:
  4875. pMD4Hash = (MD4_object *) pTmpHash->pHashData;
  4876. if (pMD4Hash->FinishFlag == TRUE)
  4877. {
  4878. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  4879. goto ErrorExit;
  4880. }
  4881. memcpy (&pMD4Hash->MD, pbData, MD4DIGESTLEN);
  4882. break;
  4883. #endif
  4884. #ifdef CSP_USE_MD5
  4885. case CALG_MD5:
  4886. pMD5Hash = (MD5_object *) pTmpHash->pHashData;
  4887. if (pMD5Hash->FinishFlag == TRUE)
  4888. {
  4889. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  4890. goto ErrorExit;
  4891. }
  4892. memcpy (pMD5Hash->digest, pbData, MD5DIGESTLEN);
  4893. break;
  4894. #endif
  4895. #ifdef CSP_USE_SHA
  4896. case CALG_SHA:
  4897. pSHAHash = (A_SHA_CTX *) pTmpHash->pHashData;
  4898. if (pSHAHash->FinishFlag == TRUE)
  4899. {
  4900. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  4901. goto ErrorExit;
  4902. }
  4903. memcpy (pSHAHash->HashVal, pbData, A_SHA_DIGEST_LEN);
  4904. break;
  4905. #endif
  4906. #ifdef CSP_USE_SSL3SHAMD5
  4907. case CALG_SSL3_SHAMD5:
  4908. memcpy (pTmpHash->pHashData, pbData, SSL3_SHAMD5_LEN);
  4909. break;
  4910. #endif
  4911. #ifdef CSP_USE_MAC
  4912. case CALG_MAC:
  4913. pMAC = (MACstate *)pTmpHash->pHashData;
  4914. dwSts = NTLValidate(pTmpHash->hKey, hUID, KEY_HANDLE, &pTmpKey);
  4915. if (ERROR_SUCCESS != dwSts)
  4916. {
  4917. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  4918. goto ErrorExit;
  4919. }
  4920. if (pMAC->FinishFlag == TRUE)
  4921. {
  4922. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  4923. goto ErrorExit;
  4924. }
  4925. memcpy(pTmpKey->FeedBack, pbData, pTmpKey->dwBlockLen);
  4926. break;
  4927. #endif
  4928. default:
  4929. dwReturn = (DWORD)NTE_BAD_ALGID;
  4930. goto ErrorExit;
  4931. }
  4932. pTmpHash->dwHashState |= DATA_IN_HASH;
  4933. break;
  4934. case HP_HMAC_INFO:
  4935. if (CALG_HMAC != pTmpHash->Algid)
  4936. {
  4937. dwReturn = (DWORD)NTE_BAD_TYPE;
  4938. goto ErrorExit;
  4939. }
  4940. pHMACInfo = (PHMAC_INFO)pbData;
  4941. pTmpHash->HMACAlgid = pHMACInfo->HashAlgid;
  4942. // now that we know the type of hash we can create it
  4943. dwSts = LocalCreateHash(pTmpHash->HMACAlgid,
  4944. (BYTE**)&pTmpHash->pHashData,
  4945. &pTmpHash->dwDataLen);
  4946. if (ERROR_SUCCESS != dwSts)
  4947. {
  4948. dwReturn = dwSts;
  4949. goto ErrorExit;
  4950. }
  4951. // if the length of the inner string is 0 then use the default string
  4952. if (0 == pHMACInfo->cbInnerString)
  4953. pTmpHash->cbHMACInner = HMAC_DEFAULT_STRING_LEN;
  4954. else
  4955. pTmpHash->cbHMACInner = pHMACInfo->cbInnerString;
  4956. pb = _nt_malloc(pTmpHash->cbHMACInner);
  4957. if (NULL == pb)
  4958. {
  4959. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  4960. goto ErrorExit;
  4961. }
  4962. if (0 == pHMACInfo->cbInnerString)
  4963. memset(pb, 0x36, pTmpHash->cbHMACInner);
  4964. else
  4965. memcpy(pb, pHMACInfo->pbInnerString, pTmpHash->cbHMACInner);
  4966. if (pTmpHash->pbHMACInner)
  4967. _nt_free(pTmpHash->pbHMACInner, pTmpHash->cbHMACInner);
  4968. pTmpHash->pbHMACInner = pb;
  4969. // if the length of the outer string is 0 then use the default string
  4970. if (0 == pHMACInfo->cbOuterString)
  4971. pTmpHash->cbHMACOuter = HMAC_DEFAULT_STRING_LEN;
  4972. else
  4973. pTmpHash->cbHMACOuter = pHMACInfo->cbOuterString;
  4974. pb = _nt_malloc(pTmpHash->cbHMACOuter);
  4975. if (NULL == pb)
  4976. {
  4977. _nt_free(pTmpHash->pbHMACInner, pTmpHash->cbHMACInner);
  4978. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  4979. goto ErrorExit;
  4980. }
  4981. if (0 == pHMACInfo->cbOuterString)
  4982. memset(pb, 0x5C, pTmpHash->cbHMACOuter);
  4983. else
  4984. memcpy(pb, pHMACInfo->pbOuterString, pTmpHash->cbHMACOuter);
  4985. if (pTmpHash->pbHMACOuter)
  4986. _nt_free(pTmpHash->pbHMACOuter, pTmpHash->cbHMACOuter);
  4987. pTmpHash->pbHMACOuter = pb;
  4988. break;
  4989. #ifdef CSP_USE_SSL3
  4990. case HP_TLS1PRF_LABEL:
  4991. case HP_TLS1PRF_SEED:
  4992. {
  4993. if (CALG_TLS1PRF != pTmpHash->Algid)
  4994. {
  4995. dwReturn = (DWORD)NTE_BAD_HASH;
  4996. goto ErrorExit;
  4997. }
  4998. dwSts = SetPRFHashParam((PRF_HASH*)pTmpHash->pHashData,
  4999. dwParam, pbData);
  5000. if (ERROR_SUCCESS != dwSts)
  5001. {
  5002. dwReturn = dwSts;
  5003. goto ErrorExit;
  5004. }
  5005. pTmpHash->dwHashState |= DATA_IN_HASH;
  5006. break;
  5007. }
  5008. #endif
  5009. default:
  5010. dwReturn = (DWORD)NTE_BAD_TYPE;
  5011. goto ErrorExit;
  5012. }
  5013. if (dwParam == HP_HASHVAL)
  5014. pTmpHash->HashFlags |= HF_VALUE_SET;
  5015. dwReturn = ERROR_SUCCESS;
  5016. ErrorExit:
  5017. fRet = (ERROR_SUCCESS == dwReturn);
  5018. if (!fRet)
  5019. SetLastError(dwReturn);
  5020. return fRet;
  5021. }
  5022. /*static*/ DWORD
  5023. LocalGetHashVal(
  5024. IN ALG_ID Algid,
  5025. IN DWORD dwHashFlags,
  5026. IN OUT BYTE *pbHashData,
  5027. OUT BYTE *pbHashVal,
  5028. OUT DWORD *pcbHashVal)
  5029. {
  5030. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  5031. MD2_object *pMD2Hash;
  5032. MD4_object *pMD4Hash;
  5033. MD5_object *pMD5Hash;
  5034. A_SHA_CTX *pSHAHash;
  5035. switch (Algid)
  5036. {
  5037. #ifdef CSP_USE_MD2
  5038. case CALG_MD2:
  5039. // make sure there's enough room.
  5040. if (pbHashVal == NULL || *pcbHashVal < MD2DIGESTLEN)
  5041. {
  5042. *pcbHashVal = MD2DIGESTLEN;
  5043. dwReturn = (pbHashVal == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  5044. goto ErrorExit;
  5045. }
  5046. pMD2Hash = (MD2_object *)pbHashData;
  5047. if ((dwHashFlags & HF_VALUE_SET) == 0)
  5048. {
  5049. if (pMD2Hash->FinishFlag == TRUE)
  5050. {
  5051. *pcbHashVal = MD2DIGESTLEN;
  5052. memcpy(pbHashVal, pMD2Hash->MD.state, MD2DIGESTLEN);
  5053. break;
  5054. }
  5055. // set the finish flag on the hash and
  5056. // process what's left in the buffer.
  5057. pMD2Hash->FinishFlag = TRUE;
  5058. // Finish offthe hash
  5059. MD2Final(&pMD2Hash->MD);
  5060. }
  5061. *pcbHashVal = MD2DIGESTLEN;
  5062. memcpy (pbHashVal, pMD2Hash->MD.state, MD2DIGESTLEN);
  5063. break;
  5064. #endif
  5065. #ifdef CSP_USE_MD4
  5066. case CALG_MD4:
  5067. // make sure there's enough room.
  5068. if (pbHashVal == NULL || *pcbHashVal < MD4DIGESTLEN)
  5069. {
  5070. *pcbHashVal = MD4DIGESTLEN;
  5071. dwReturn = (pbHashVal == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  5072. goto ErrorExit;
  5073. }
  5074. pMD4Hash = (MD4_object *)pbHashData;
  5075. if ((dwHashFlags & HF_VALUE_SET) == 0)
  5076. {
  5077. if (pMD4Hash->FinishFlag == TRUE)
  5078. {
  5079. *pcbHashVal = MD4DIGESTLEN;
  5080. memcpy(pbHashVal, &pMD4Hash->MD, *pcbHashVal);
  5081. break;
  5082. }
  5083. // set the finish flag on the hash and
  5084. // process what's left in the buffer.
  5085. pMD4Hash->FinishFlag = TRUE;
  5086. if (MD4_SUCCESS != MDupdate(&pMD4Hash->MD, pMD4Hash->Buf,
  5087. MD4BYTESTOBITS(pMD4Hash->BufLen)))
  5088. {
  5089. dwReturn = (DWORD)NTE_FAIL;
  5090. goto ErrorExit;
  5091. }
  5092. }
  5093. *pcbHashVal = MD4DIGESTLEN;
  5094. memcpy(pbHashVal, &pMD4Hash->MD, *pcbHashVal);
  5095. break;
  5096. #endif
  5097. #ifdef CSP_USE_MD5
  5098. case CALG_MD5:
  5099. // make sure there's enough room.
  5100. if (pbHashVal == NULL || *pcbHashVal < MD5DIGESTLEN)
  5101. {
  5102. *pcbHashVal = MD5DIGESTLEN;
  5103. dwReturn = (pbHashVal == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  5104. goto ErrorExit;
  5105. }
  5106. pMD5Hash = (MD5_object *)pbHashData;
  5107. if ((dwHashFlags & HF_VALUE_SET) == 0)
  5108. {
  5109. if (pMD5Hash->FinishFlag == TRUE)
  5110. {
  5111. *pcbHashVal = MD5DIGESTLEN;
  5112. memcpy (pbHashVal, pMD5Hash->digest, MD5DIGESTLEN);
  5113. break;
  5114. }
  5115. // set the finish flag on the hash and
  5116. // process what's left in the buffer.
  5117. pMD5Hash->FinishFlag = TRUE;
  5118. // Finish offthe hash
  5119. MD5Final(pMD5Hash);
  5120. }
  5121. *pcbHashVal = MD5DIGESTLEN;
  5122. memcpy (pbHashVal, pMD5Hash->digest, MD5DIGESTLEN);
  5123. break;
  5124. #endif
  5125. #ifdef CSP_USE_SHA
  5126. case CALG_SHA:
  5127. // make sure there's enough room.
  5128. if (pbHashVal == NULL || *pcbHashVal < A_SHA_DIGEST_LEN)
  5129. {
  5130. *pcbHashVal = A_SHA_DIGEST_LEN;
  5131. dwReturn = (pbHashVal == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  5132. goto ErrorExit;
  5133. }
  5134. pSHAHash = (A_SHA_CTX *)pbHashData;
  5135. if ((dwHashFlags & HF_VALUE_SET) == 0)
  5136. {
  5137. if (pSHAHash->FinishFlag == TRUE)
  5138. {
  5139. *pcbHashVal = A_SHA_DIGEST_LEN;
  5140. memcpy (pbHashVal, pSHAHash->HashVal, A_SHA_DIGEST_LEN);
  5141. break;
  5142. }
  5143. // set the finish flag on the hash and
  5144. // process what's left in the buffer.
  5145. pSHAHash->FinishFlag = TRUE;
  5146. // Finish off the hash
  5147. A_SHAFinal(pSHAHash, pSHAHash->HashVal);
  5148. }
  5149. *pcbHashVal = A_SHA_DIGEST_LEN;
  5150. memcpy (pbHashVal, pSHAHash->HashVal, A_SHA_DIGEST_LEN);
  5151. break;
  5152. #endif
  5153. default:
  5154. dwReturn = (DWORD)NTE_BAD_ALGID;
  5155. goto ErrorExit;
  5156. }
  5157. dwReturn = ERROR_SUCCESS;
  5158. ErrorExit:
  5159. return dwReturn;
  5160. }
  5161. /*static*/ DWORD
  5162. GetHashLength(
  5163. IN ALG_ID Algid)
  5164. {
  5165. DWORD cbLen;
  5166. switch (Algid)
  5167. {
  5168. #ifdef CSP_USE_MD2
  5169. case CALG_MD2:
  5170. cbLen = MD2DIGESTLEN;
  5171. break;
  5172. #endif
  5173. #ifdef CSP_USE_MD4
  5174. case CALG_MD4:
  5175. cbLen = MD4DIGESTLEN;
  5176. break;
  5177. #endif
  5178. #ifdef CSP_USE_MD5
  5179. case CALG_MD5:
  5180. cbLen = MD5DIGESTLEN;
  5181. break;
  5182. #endif
  5183. #ifdef CSP_USE_SHA
  5184. case CALG_SHA:
  5185. cbLen = A_SHA_DIGEST_LEN;
  5186. break;
  5187. #endif
  5188. default:
  5189. ASSERT(FALSE);
  5190. cbLen = 0;
  5191. }
  5192. return cbLen;
  5193. }
  5194. /*
  5195. - CPGetHashParam
  5196. -
  5197. * Purpose:
  5198. * Allows applications to get various aspects of the
  5199. * operations of a key
  5200. *
  5201. * Parameters:
  5202. * IN hUID - Handle to a CSP
  5203. * IN hHash - Handle to a hash
  5204. * IN dwParam - Parameter number
  5205. * IN pbData - Pointer to data
  5206. * IN pdwDataLen - Length of parameter data
  5207. * IN dwFlags - Flags values
  5208. *
  5209. * Returns:
  5210. */
  5211. BOOL WINAPI
  5212. CPGetHashParam(
  5213. IN HCRYPTPROV hUID,
  5214. IN HCRYPTHASH hHash,
  5215. IN DWORD dwParam,
  5216. IN BYTE *pbData,
  5217. IN DWORD *pwDataLen,
  5218. IN DWORD dwFlags)
  5219. {
  5220. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  5221. PNTAGHashList pTmpHash;
  5222. MACstate *pMAC;
  5223. BYTE MACbuf[2*MAX_BLOCKLEN];
  5224. PNTAGKeyList pTmpKey;
  5225. BYTE rgbFinalHash[A_SHA_DIGEST_LEN];
  5226. DWORD cbFinalHash;
  5227. DWORD cb;
  5228. BYTE *pb = NULL;
  5229. DWORD cbHashData;
  5230. BYTE *pbHashData = NULL;
  5231. DWORD i;
  5232. BOOL fRet;
  5233. DWORD dwSts;
  5234. EntryPoint
  5235. if (dwFlags != 0)
  5236. {
  5237. dwReturn = (DWORD)NTE_BAD_FLAGS;
  5238. goto ErrorExit;
  5239. }
  5240. // check the user identification
  5241. if (NTLCheckList ((HNTAG)hUID, USER_HANDLE) == NULL)
  5242. {
  5243. dwReturn = (DWORD)NTE_BAD_UID;
  5244. goto ErrorExit;
  5245. }
  5246. if (pwDataLen == NULL)
  5247. {
  5248. dwReturn = ERROR_INVALID_PARAMETER;
  5249. goto ErrorExit;
  5250. }
  5251. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  5252. if (ERROR_SUCCESS != dwSts)
  5253. {
  5254. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_HASH : dwSts;
  5255. goto ErrorExit;
  5256. }
  5257. switch (dwParam)
  5258. {
  5259. case HP_ALGID:
  5260. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  5261. {
  5262. *pwDataLen = sizeof(DWORD);
  5263. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  5264. goto ErrorExit;
  5265. }
  5266. *((DWORD *) pbData) = pTmpHash->Algid;
  5267. *pwDataLen = sizeof(DWORD);
  5268. break;
  5269. case HP_HASHSIZE:
  5270. if (pbData == NULL || *pwDataLen < sizeof(DWORD))
  5271. {
  5272. *pwDataLen = sizeof(DWORD);
  5273. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  5274. goto ErrorExit;
  5275. }
  5276. switch (pTmpHash->Algid)
  5277. {
  5278. case CALG_MD2:
  5279. case CALG_MD4:
  5280. case CALG_MD5:
  5281. case CALG_SHA:
  5282. *(DWORD *)pbData = GetHashLength(pTmpHash->Algid);
  5283. break;
  5284. #ifdef CSP_USE_MAC
  5285. case CALG_MAC:
  5286. *(DWORD *)pbData = MAX_BLOCKLEN;
  5287. break;
  5288. #endif // CSP_USE_MAC
  5289. case CALG_HMAC:
  5290. *(DWORD *)pbData = GetHashLength(pTmpHash->HMACAlgid);
  5291. break;
  5292. #ifdef CSP_USE_SSL3SHAMD5
  5293. case CALG_SSL3_SHAMD5:
  5294. *((DWORD *) pbData) = SSL3_SHAMD5_LEN;
  5295. break;
  5296. #endif
  5297. default:
  5298. dwReturn = (DWORD)NTE_BAD_ALGID;
  5299. goto ErrorExit;
  5300. }
  5301. *pwDataLen = sizeof(DWORD);
  5302. break;
  5303. case HP_HASHVAL:
  5304. switch (pTmpHash->Algid)
  5305. {
  5306. #ifdef CSP_USE_SSL3SHAMD5
  5307. case CALG_SSL3_SHAMD5:
  5308. // make sure there's enough room.
  5309. if (pbData == NULL || *pwDataLen < SSL3_SHAMD5_LEN)
  5310. {
  5311. *pwDataLen = SSL3_SHAMD5_LEN;
  5312. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  5313. goto ErrorExit;
  5314. }
  5315. // Hash value must have already been set.
  5316. if ((pTmpHash->HashFlags & HF_VALUE_SET) == 0)
  5317. {
  5318. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  5319. goto ErrorExit;
  5320. }
  5321. *pwDataLen = SSL3_SHAMD5_LEN;
  5322. memcpy (pbData, pTmpHash->pHashData, SSL3_SHAMD5_LEN);
  5323. break;
  5324. #endif
  5325. #ifdef CSP_USE_MAC
  5326. case CALG_MAC:
  5327. pMAC = (MACstate *)pTmpHash->pHashData;
  5328. dwSts = NTLValidate(pTmpHash->hKey, hUID, KEY_HANDLE, &pTmpKey);
  5329. if (ERROR_SUCCESS != dwSts)
  5330. {
  5331. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  5332. goto ErrorExit;
  5333. }
  5334. // make sure there is enough room.
  5335. if (pbData == NULL || (*pwDataLen < pTmpKey->dwBlockLen))
  5336. {
  5337. *pwDataLen = pTmpKey->dwBlockLen;
  5338. dwReturn = (pbData == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  5339. goto ErrorExit;
  5340. }
  5341. if (pMAC->FinishFlag == TRUE)
  5342. {
  5343. *pwDataLen = pTmpKey->dwBlockLen;
  5344. memcpy(pbData, pTmpKey->FeedBack, pTmpKey->dwBlockLen);
  5345. break;
  5346. }
  5347. // set the finish flag on the hash and
  5348. // process what's left in the buffer.
  5349. pMAC->FinishFlag = TRUE;
  5350. if (pMAC->dwBufLen)
  5351. {
  5352. memset(MACbuf, 0, 2*MAX_BLOCKLEN);
  5353. memcpy(MACbuf, pMAC->Buffer, pMAC->dwBufLen);
  5354. switch (pTmpKey->Algid)
  5355. {
  5356. case CALG_RC2:
  5357. dwSts = BlockEncrypt(RC2, pTmpKey, RC2_BLOCKLEN, TRUE,
  5358. MACbuf, &pMAC->dwBufLen,
  5359. 2*MAX_BLOCKLEN);
  5360. if (ERROR_SUCCESS != dwSts)
  5361. {
  5362. dwReturn = dwSts;
  5363. goto ErrorExit;
  5364. }
  5365. break;
  5366. case CALG_DES:
  5367. dwSts = BlockEncrypt(des, pTmpKey, DES_BLOCKLEN, TRUE,
  5368. MACbuf, &pMAC->dwBufLen,
  5369. 2*MAX_BLOCKLEN);
  5370. if (ERROR_SUCCESS != dwSts)
  5371. {
  5372. dwReturn = dwSts;
  5373. goto ErrorExit;
  5374. }
  5375. break;
  5376. #ifdef CSP_USE_3DES
  5377. case CALG_3DES_112:
  5378. case CALG_3DES:
  5379. dwSts = BlockEncrypt(tripledes, pTmpKey, DES_BLOCKLEN,
  5380. TRUE, MACbuf, &pMAC->dwBufLen,
  5381. 2*MAX_BLOCKLEN);
  5382. if (ERROR_SUCCESS != dwSts)
  5383. {
  5384. dwReturn = dwSts;
  5385. goto ErrorExit;
  5386. }
  5387. break;
  5388. #endif
  5389. #ifdef CSP_USE_AES
  5390. case CALG_AES_128:
  5391. case CALG_AES_192:
  5392. case CALG_AES_256:
  5393. dwSts = BlockEncrypt(aes, pTmpKey, pTmpKey->dwBlockLen,
  5394. TRUE, MACbuf, &pMAC->dwBufLen,
  5395. 2*MAX_BLOCKLEN);
  5396. if (ERROR_SUCCESS != dwSts)
  5397. {
  5398. dwReturn = dwSts;
  5399. goto ErrorExit;
  5400. }
  5401. break;
  5402. #endif
  5403. // default: It's not a block cipher.
  5404. }
  5405. }
  5406. *pwDataLen = pTmpKey->dwBlockLen;
  5407. memcpy(pbData, pTmpKey->FeedBack, pTmpKey->dwBlockLen);
  5408. break;
  5409. #endif
  5410. case CALG_HMAC:
  5411. if (!(pTmpHash->HMACState & HMAC_FINISHED))
  5412. {
  5413. cbFinalHash = sizeof(rgbFinalHash);
  5414. dwSts = LocalGetHashVal(pTmpHash->HMACAlgid,
  5415. pTmpHash->HashFlags,
  5416. pTmpHash->pHashData,
  5417. rgbFinalHash,
  5418. &cbFinalHash);
  5419. if (ERROR_SUCCESS != dwSts)
  5420. {
  5421. dwReturn = dwSts;
  5422. goto ErrorExit;
  5423. }
  5424. // now XOR the outer string with the key and hash
  5425. // over this and the inner hash
  5426. dwSts = NTLValidate(pTmpHash->hKey, hUID,
  5427. KEY_HANDLE, &pTmpKey);
  5428. if (ERROR_SUCCESS != dwSts)
  5429. {
  5430. dwReturn = (dwSts == NTE_FAIL)
  5431. ? (DWORD)NTE_BAD_KEY
  5432. : dwSts;
  5433. goto ErrorExit;
  5434. }
  5435. if (pTmpKey->cbKeyLen < pTmpHash->cbHMACOuter)
  5436. cb = pTmpHash->cbHMACOuter;
  5437. else
  5438. cb = pTmpKey->cbKeyLen;
  5439. pb = (BYTE *)_nt_malloc(cb);
  5440. if (NULL == pb)
  5441. {
  5442. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5443. goto ErrorExit;
  5444. }
  5445. memcpy(pb, pTmpHash->pbHMACOuter, pTmpHash->cbHMACOuter);
  5446. // currently no support for byte reversed keys with HMAC
  5447. for (i=0;i<pTmpKey->cbKeyLen;i++)
  5448. pb[i] ^= (pTmpKey->pKeyValue)[i];
  5449. dwSts = LocalCreateHash(pTmpHash->HMACAlgid,
  5450. &pbHashData,
  5451. &cbHashData);
  5452. if (ERROR_SUCCESS != dwSts)
  5453. {
  5454. dwReturn = dwSts;
  5455. goto ErrorExit;
  5456. }
  5457. dwSts = LocalHashData(pTmpHash->HMACAlgid, pbHashData,
  5458. pb, cb);
  5459. if (ERROR_SUCCESS != dwSts)
  5460. {
  5461. dwReturn = dwSts;
  5462. goto ErrorExit;
  5463. }
  5464. dwSts = LocalHashData(pTmpHash->HMACAlgid, pbHashData,
  5465. rgbFinalHash, cbFinalHash);
  5466. if (ERROR_SUCCESS != dwSts)
  5467. {
  5468. dwReturn = dwSts;
  5469. goto ErrorExit;
  5470. }
  5471. _nt_free(pTmpHash->pHashData, pTmpHash->dwDataLen);
  5472. pTmpHash->dwDataLen = cbHashData;
  5473. pTmpHash->pHashData = pbHashData;
  5474. pbHashData = NULL;
  5475. pTmpHash->HMACState |= HMAC_FINISHED;
  5476. }
  5477. dwSts = LocalGetHashVal(pTmpHash->HMACAlgid, pTmpHash->HashFlags,
  5478. pTmpHash->pHashData, pbData, pwDataLen);
  5479. if (ERROR_SUCCESS != dwSts)
  5480. {
  5481. dwReturn = dwSts;
  5482. goto ErrorExit;
  5483. }
  5484. break;
  5485. #ifdef CSP_USE_SSL3
  5486. case CALG_TLS1PRF:
  5487. {
  5488. dwSts = CalculatePRF((PRF_HASH*)pTmpHash->pHashData,
  5489. pbData, pwDataLen);
  5490. if (ERROR_SUCCESS != dwSts)
  5491. {
  5492. dwReturn = dwSts;
  5493. goto ErrorExit;
  5494. }
  5495. break;
  5496. }
  5497. #endif
  5498. default:
  5499. dwSts = LocalGetHashVal(pTmpHash->Algid, pTmpHash->HashFlags,
  5500. pTmpHash->pHashData, pbData, pwDataLen);
  5501. if (ERROR_SUCCESS != dwSts)
  5502. {
  5503. dwReturn = dwSts;
  5504. goto ErrorExit;
  5505. }
  5506. }
  5507. break;
  5508. default:
  5509. dwReturn = (DWORD)NTE_BAD_TYPE;
  5510. goto ErrorExit;
  5511. }
  5512. dwReturn = ERROR_SUCCESS;
  5513. ErrorExit:
  5514. fRet = (ERROR_SUCCESS == dwReturn);
  5515. if (pb)
  5516. _nt_free(pb, cb);
  5517. if (pbHashData)
  5518. _nt_free(pbHashData, cbHashData);
  5519. if (!fRet)
  5520. SetLastError(dwReturn);
  5521. return fRet;
  5522. }
  5523. /*static*/ DWORD
  5524. CopyKey(
  5525. IN PNTAGKeyList pOldKey,
  5526. OUT PNTAGKeyList *ppNewKey)
  5527. {
  5528. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  5529. PNTAGKeyList pNewKey;
  5530. pNewKey = (PNTAGKeyList)_nt_malloc(sizeof(NTAGKeyList));
  5531. if (NULL == pNewKey)
  5532. {
  5533. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5534. goto ErrorExit;
  5535. }
  5536. memcpy(pNewKey, pOldKey, sizeof(NTAGKeyList));
  5537. pNewKey->Rights &= ~CRYPT_ARCHIVABLE;
  5538. pNewKey->Permissions &= ~CRYPT_ARCHIVE;
  5539. pNewKey->pKeyValue = NULL;
  5540. pNewKey->cbDataLen = 0;
  5541. pNewKey->pData = NULL;
  5542. pNewKey->cbSaltLen = 0;
  5543. pNewKey->cbKeyLen = pOldKey->cbKeyLen;
  5544. if (pNewKey->cbKeyLen)
  5545. {
  5546. pNewKey->pKeyValue = (BYTE*)_nt_malloc(pNewKey->cbKeyLen);
  5547. if (NULL == pNewKey->pKeyValue)
  5548. {
  5549. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5550. goto ErrorExit;
  5551. }
  5552. }
  5553. memcpy(pNewKey->pKeyValue, pOldKey->pKeyValue, pNewKey->cbKeyLen);
  5554. pNewKey->cbDataLen = pOldKey->cbDataLen;
  5555. if (pNewKey->cbDataLen)
  5556. {
  5557. pNewKey->pData = (BYTE*)_nt_malloc(pNewKey->cbDataLen);
  5558. if (NULL == pNewKey->pData)
  5559. {
  5560. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5561. goto ErrorExit;
  5562. }
  5563. }
  5564. memcpy(pNewKey->pData, pOldKey->pData, pNewKey->cbDataLen);
  5565. if (pOldKey->Algid == CALG_PCT1_MASTER)
  5566. {
  5567. // This is a PCT master key, and so it might have some certificate
  5568. // data attached to it. If this is the case, then make a copy
  5569. // of the certificate data and attach it to the new key.
  5570. if (pOldKey->cbDataLen == sizeof(SCH_KEY))
  5571. {
  5572. PSCH_KEY pOldSChKey = (PSCH_KEY)pOldKey->pData;
  5573. PSCH_KEY pNewSChKey = (PSCH_KEY)pNewKey->pData;
  5574. if (pOldSChKey->pbCertData && pOldSChKey->cbCertData)
  5575. {
  5576. pNewSChKey->pbCertData = (BYTE*)_nt_malloc(pOldSChKey->cbCertData);
  5577. if (NULL == pNewSChKey->pbCertData)
  5578. {
  5579. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5580. goto ErrorExit;
  5581. }
  5582. memcpy(pNewSChKey->pbCertData,
  5583. pOldSChKey->pbCertData,
  5584. pOldSChKey->cbCertData);
  5585. }
  5586. }
  5587. }
  5588. pNewKey->cbSaltLen = pOldKey->cbSaltLen;
  5589. memcpy(pNewKey->rgbSalt, pOldKey->rgbSalt, pNewKey->cbSaltLen);
  5590. *ppNewKey = pNewKey;
  5591. pNewKey = NULL;
  5592. dwReturn = ERROR_SUCCESS;
  5593. ErrorExit:
  5594. if (NULL != pNewKey)
  5595. FreeNewKey(pNewKey);
  5596. return dwReturn;
  5597. }
  5598. /*
  5599. - CPDuplicateKey
  5600. -
  5601. * Purpose:
  5602. * Duplicates the state of a key and returns a handle to it
  5603. *
  5604. * Parameters:
  5605. * IN hUID - Handle to a CSP
  5606. * IN hKey - Handle to a key
  5607. * IN pdwReserved - Reserved
  5608. * IN dwFlags - Flags
  5609. * IN phKey - Handle to the new key
  5610. *
  5611. * Returns:
  5612. */
  5613. BOOL WINAPI
  5614. CPDuplicateKey(
  5615. IN HCRYPTPROV hUID,
  5616. IN HCRYPTKEY hKey,
  5617. IN DWORD *pdwReserved,
  5618. IN DWORD dwFlags,
  5619. IN HCRYPTKEY *phKey)
  5620. {
  5621. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  5622. PNTAGKeyList pTmpKey;
  5623. PNTAGKeyList pNewKey = NULL;
  5624. BYTE bType = KEY_HANDLE;
  5625. BOOL fRet;
  5626. DWORD dwSts;
  5627. EntryPoint
  5628. if (NULL != pdwReserved)
  5629. {
  5630. dwReturn = ERROR_INVALID_PARAMETER;
  5631. goto ErrorExit;
  5632. }
  5633. if (0 != dwFlags)
  5634. {
  5635. dwReturn = (DWORD)NTE_BAD_FLAGS;
  5636. goto ErrorExit;
  5637. }
  5638. dwSts = NTLValidate((HNTAG)hKey, hUID, bType, &pTmpKey);
  5639. if (ERROR_SUCCESS != dwSts)
  5640. {
  5641. bType = SIGPUBKEY_HANDLE;
  5642. dwSts = NTLValidate((HNTAG)hKey, hUID, bType, &pTmpKey);
  5643. if (ERROR_SUCCESS != dwSts)
  5644. {
  5645. bType = EXCHPUBKEY_HANDLE;
  5646. dwSts = NTLValidate((HNTAG)hKey, hUID, bType, &pTmpKey);
  5647. if (ERROR_SUCCESS != dwSts)
  5648. {
  5649. dwReturn = (NTE_FAIL == dwSts)
  5650. ? (DWORD)NTE_BAD_KEY
  5651. : dwSts;
  5652. goto ErrorExit;
  5653. }
  5654. }
  5655. }
  5656. dwSts = CopyKey(pTmpKey, &pNewKey);
  5657. if (ERROR_SUCCESS != dwSts)
  5658. {
  5659. dwReturn = dwSts;
  5660. goto ErrorExit;
  5661. }
  5662. dwSts = NTLMakeItem(phKey, bType, (void *)pNewKey);
  5663. if (ERROR_SUCCESS != dwSts)
  5664. {
  5665. dwReturn = dwSts;
  5666. goto ErrorExit;
  5667. }
  5668. dwReturn = ERROR_SUCCESS;
  5669. ErrorExit:
  5670. fRet = (ERROR_SUCCESS == dwReturn);
  5671. if (!fRet)
  5672. {
  5673. if (NULL != pNewKey)
  5674. FreeNewKey(pNewKey);
  5675. SetLastError(dwReturn);
  5676. }
  5677. return fRet;
  5678. }
  5679. //
  5680. // Function : TestEncDec
  5681. //
  5682. // Description : This function expands the passed in key buffer for the
  5683. // appropriate algorithm, and then either encryption or
  5684. // decryption is performed. A comparison is then made to see
  5685. // if the ciphertext or plaintext matches the expected value.
  5686. // The function only uses ECB mode for block ciphers and the
  5687. // plaintext buffer must be the same length as the ciphertext
  5688. // buffer. The length of the plaintext must be either the
  5689. // block length of the cipher if it is a block cipher or less
  5690. // than MAX_BLOCKLEN if a stream cipher is being used.
  5691. //
  5692. /*static*/ DWORD
  5693. TestEncDec(
  5694. IN ALG_ID Algid,
  5695. IN BYTE *pbKey,
  5696. IN DWORD cbKey,
  5697. IN BYTE *pbPlaintext,
  5698. IN DWORD cbPlaintext,
  5699. IN BYTE *pbCiphertext,
  5700. IN BYTE *pbIV,
  5701. IN int iOperation)
  5702. {
  5703. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  5704. BYTE *pbExpandedKey = NULL;
  5705. BYTE rgbBuffIn[MAX_BLOCKLEN];
  5706. BYTE rgbBuffOut[MAX_BLOCKLEN];
  5707. DWORD i;
  5708. memset(rgbBuffIn, 0, sizeof(rgbBuffIn));
  5709. memset(rgbBuffOut, 0, sizeof(rgbBuffOut));
  5710. // length of data to encrypt must be < MAX_BLOCKLEN
  5711. if (cbPlaintext > MAX_BLOCKLEN)
  5712. {
  5713. dwReturn = (DWORD)NTE_BAD_LEN;
  5714. goto ErrorExit;
  5715. }
  5716. // alloc for and expand the key
  5717. switch (Algid)
  5718. {
  5719. #ifdef CSP_USE_RC4
  5720. case (CALG_RC4):
  5721. pbExpandedKey = _nt_malloc(sizeof(RC4_KEYSTRUCT));
  5722. if (NULL == pbExpandedKey)
  5723. {
  5724. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5725. goto ErrorExit;
  5726. }
  5727. rc4_key((RC4_KEYSTRUCT*)pbExpandedKey, cbKey, pbKey);
  5728. break;
  5729. #endif // CSP_USE_RC4
  5730. #ifdef CSP_USE_RC2
  5731. case (CALG_RC2):
  5732. pbExpandedKey = _nt_malloc(RC2_TABLESIZE);
  5733. if (NULL == pbExpandedKey)
  5734. {
  5735. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5736. goto ErrorExit;
  5737. }
  5738. RC2KeyEx((WORD*)pbExpandedKey, pbKey, cbKey, cbKey * 8);
  5739. break;
  5740. #endif // CSP_USE_RC2
  5741. #ifdef CSP_USE_DES40
  5742. case (CALG_DES40):
  5743. pbExpandedKey = _nt_malloc(DES_TABLESIZE);
  5744. if (NULL == pbExpandedKey)
  5745. {
  5746. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5747. goto ErrorExit;
  5748. }
  5749. pbKey[0] &= 0x0F; // set 4 leftmost bits of first byte to zero
  5750. pbKey[2] &= 0x0F; // set 4 leftmost bits of third byte to zero
  5751. pbKey[4] &= 0x0F; // set 4 leftmost bits of fifth byte to zero
  5752. pbKey[6] &= 0x0F; // set 4 leftmost bits of seventh byte to zero
  5753. desparityonkey(pbKey, cbKey);
  5754. deskey((DESTable*)pbExpandedKey, pbKey);
  5755. break;
  5756. #endif // CSP_USE_DES40
  5757. #ifdef CSP_USE_DES
  5758. case (CALG_DES):
  5759. pbExpandedKey = _nt_malloc(DES_TABLESIZE);
  5760. if (NULL == pbExpandedKey)
  5761. {
  5762. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5763. goto ErrorExit;
  5764. }
  5765. desparityonkey(pbKey, cbKey);
  5766. deskey((DESTable*)pbExpandedKey, pbKey);
  5767. break;
  5768. #endif // CSP_USE_DES
  5769. #ifdef CSP_USE_3DES
  5770. case (CALG_3DES):
  5771. pbExpandedKey = _nt_malloc(DES3_TABLESIZE);
  5772. if (NULL == pbExpandedKey)
  5773. {
  5774. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5775. goto ErrorExit;
  5776. }
  5777. desparityonkey(pbKey, cbKey);
  5778. tripledes3key((PDES3TABLE)pbExpandedKey, pbKey);
  5779. break;
  5780. case (CALG_3DES_112):
  5781. pbExpandedKey = _nt_malloc(DES3_TABLESIZE);
  5782. if (NULL == pbExpandedKey)
  5783. {
  5784. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5785. goto ErrorExit;
  5786. }
  5787. desparityonkey(pbKey, cbKey);
  5788. tripledes2key((PDES3TABLE)pbExpandedKey, pbKey);
  5789. break;
  5790. #endif // CSP_USE_3DES
  5791. #ifdef CSP_USE_AES
  5792. case CALG_AES_128:
  5793. pbExpandedKey = _nt_malloc(AES_TABLESIZE);
  5794. if (NULL == pbExpandedKey)
  5795. {
  5796. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5797. goto ErrorExit;
  5798. }
  5799. aeskey((AESTable *) pbExpandedKey, pbKey, CRYPT_AES128_ROUNDS);
  5800. break;
  5801. case CALG_AES_192:
  5802. pbExpandedKey = _nt_malloc(AES_TABLESIZE);
  5803. if (NULL == pbExpandedKey)
  5804. {
  5805. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5806. goto ErrorExit;
  5807. }
  5808. aeskey((AESTable *) pbExpandedKey, pbKey, CRYPT_AES192_ROUNDS);
  5809. break;
  5810. case CALG_AES_256:
  5811. pbExpandedKey = _nt_malloc(AES_TABLESIZE);
  5812. if (NULL == pbExpandedKey)
  5813. {
  5814. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  5815. goto ErrorExit;
  5816. }
  5817. aeskey((AESTable *) pbExpandedKey, pbKey, CRYPT_AES256_ROUNDS);
  5818. break;
  5819. #endif
  5820. default:
  5821. dwReturn = (DWORD)NTE_BAD_ALGID;
  5822. goto ErrorExit;
  5823. }
  5824. // if encrypting and there is an IV then use it
  5825. if ((ENCRYPT == iOperation) && (CALG_RC4 != Algid))
  5826. {
  5827. memcpy(rgbBuffIn, pbPlaintext, cbPlaintext);
  5828. if (NULL != pbIV)
  5829. {
  5830. for (i = 0; i < cbPlaintext; i++)
  5831. rgbBuffIn[i] = (BYTE)(rgbBuffIn[i] ^ pbIV[i]);
  5832. }
  5833. }
  5834. // encrypt the plaintext
  5835. switch (Algid)
  5836. {
  5837. #ifdef CSP_USE_RC4
  5838. case (CALG_RC4):
  5839. if (ENCRYPT == iOperation)
  5840. memcpy(rgbBuffOut, pbPlaintext, cbPlaintext);
  5841. else
  5842. memcpy(rgbBuffOut, pbCiphertext, cbPlaintext);
  5843. rc4((RC4_KEYSTRUCT*)pbExpandedKey, cbPlaintext, rgbBuffOut);
  5844. break;
  5845. #endif // CSP_USE_RC4
  5846. #ifdef CSP_USE_RC2
  5847. case (CALG_RC2):
  5848. if (ENCRYPT == iOperation)
  5849. RC2(rgbBuffOut, rgbBuffIn, pbExpandedKey, ENCRYPT);
  5850. else
  5851. RC2(rgbBuffOut, pbCiphertext, pbExpandedKey, DECRYPT);
  5852. break;
  5853. #endif // CSP_USE_RC2
  5854. #ifdef CSP_USE_DES40
  5855. case (CALG_DES40):
  5856. if (ENCRYPT == iOperation)
  5857. des(rgbBuffOut, rgbBuffIn, pbExpandedKey, ENCRYPT);
  5858. else
  5859. des(rgbBuffOut, pbCiphertext, pbExpandedKey, DECRYPT);
  5860. break;
  5861. #endif // CSP_USE_DES40
  5862. #ifdef CSP_USE_DES
  5863. case (CALG_DES):
  5864. if (ENCRYPT == iOperation)
  5865. des(rgbBuffOut, rgbBuffIn, pbExpandedKey, ENCRYPT);
  5866. else
  5867. des(rgbBuffOut, pbCiphertext, pbExpandedKey, DECRYPT);
  5868. break;
  5869. #endif // CSP_USE_DES
  5870. #ifdef CSP_USE_3DES
  5871. case (CALG_3DES):
  5872. case (CALG_3DES_112):
  5873. if (ENCRYPT == iOperation)
  5874. tripledes(rgbBuffOut, rgbBuffIn, pbExpandedKey, ENCRYPT);
  5875. else
  5876. tripledes(rgbBuffOut, pbCiphertext, pbExpandedKey, DECRYPT);
  5877. break;
  5878. #endif // CSP_USE_3DES
  5879. #ifdef CSP_USE_AES
  5880. case CALG_AES_128:
  5881. case CALG_AES_192:
  5882. case CALG_AES_256:
  5883. if (ENCRYPT == iOperation)
  5884. aes(rgbBuffOut, rgbBuffIn, pbExpandedKey, ENCRYPT);
  5885. else
  5886. aes(rgbBuffOut, pbCiphertext, pbExpandedKey, DECRYPT);
  5887. break;
  5888. #endif
  5889. default:
  5890. dwReturn = (DWORD)NTE_BAD_ALGID;
  5891. goto ErrorExit;
  5892. }
  5893. if (ENCRYPT == iOperation)
  5894. {
  5895. // compare the encrypted plaintext with the passed in ciphertext
  5896. if (0 != memcmp(pbCiphertext, rgbBuffOut, cbPlaintext))
  5897. {
  5898. dwReturn = (DWORD)NTE_FAIL;
  5899. goto ErrorExit;
  5900. }
  5901. }
  5902. else
  5903. {
  5904. // if there is an IV then use it
  5905. if (NULL != pbIV)
  5906. {
  5907. for (i = 0; i < cbPlaintext; i++)
  5908. rgbBuffOut[i] = (BYTE)(rgbBuffOut[i] ^ pbIV[i]);
  5909. }
  5910. // compare the decrypted ciphertext with the passed in plaintext
  5911. if (0 != memcmp(pbPlaintext, rgbBuffOut, cbPlaintext))
  5912. {
  5913. dwReturn = (DWORD)NTE_FAIL;
  5914. goto ErrorExit;
  5915. }
  5916. }
  5917. dwReturn = ERROR_SUCCESS;
  5918. ErrorExit:
  5919. if (pbExpandedKey)
  5920. _nt_free(pbExpandedKey, 0);
  5921. return dwReturn;
  5922. }
  5923. //
  5924. // Function : TestSymmetricAlgorithm
  5925. //
  5926. // Description : This function expands the passed in key buffer for the
  5927. // appropriate algorithm, encrypts the plaintext buffer with the
  5928. // same algorithm and key, and the compares the passed in
  5929. // expected ciphertext with the calculated ciphertext to make
  5930. // sure they are the same. The opposite is then done with
  5931. // decryption.
  5932. //
  5933. // The function only uses ECB mode for block ciphers and the
  5934. // plaintext buffer must be the same length as the ciphertext
  5935. // buffer. The length of the plaintext must be either the block
  5936. // length of the cipher if it is a block cipher or less than
  5937. // MAX_BLOCKLEN if a stream cipher is being used.
  5938. //
  5939. DWORD
  5940. TestSymmetricAlgorithm(
  5941. IN ALG_ID Algid,
  5942. IN BYTE *pbKey,
  5943. IN DWORD cbKey,
  5944. IN BYTE *pbPlaintext,
  5945. IN DWORD cbPlaintext,
  5946. IN BYTE *pbCiphertext,
  5947. IN BYTE *pbIV)
  5948. {
  5949. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  5950. DWORD dwSts;
  5951. dwSts = TestEncDec(Algid, pbKey, cbKey, pbPlaintext, cbPlaintext,
  5952. pbCiphertext, pbIV, ENCRYPT);
  5953. if (ERROR_SUCCESS != dwSts)
  5954. {
  5955. dwReturn = dwSts;
  5956. goto ErrorExit;
  5957. }
  5958. dwSts = TestEncDec(Algid, pbKey, cbKey, pbPlaintext, cbPlaintext,
  5959. pbCiphertext, pbIV, DECRYPT);
  5960. if (ERROR_SUCCESS != dwSts)
  5961. {
  5962. dwReturn = dwSts;
  5963. goto ErrorExit;
  5964. }
  5965. dwReturn = ERROR_SUCCESS;
  5966. ErrorExit:
  5967. return dwReturn;
  5968. }