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.

1432 lines
36 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation
  4. //
  5. // File: keypack.c
  6. //
  7. // Contents: Keypack encoding/decoding library
  8. //
  9. // History:
  10. //
  11. //---------------------------------------------------------------------------
  12. #include "precomp.h"
  13. #include <stddef.h>
  14. #include "md5.h"
  15. #include "rc4.h"
  16. typedef struct _Enveloped_Data
  17. {
  18. DWORD cbEncryptedKey;
  19. PBYTE pbEncryptedKey;
  20. DWORD cbEncryptedData;
  21. PBYTE pbEncryptedData;
  22. } Enveloped_Data, * PEnveloped_Data;
  23. ///////////////////////////////////////////////////////////////////////////////
  24. //
  25. // Internal functions
  26. //
  27. DWORD WINAPI
  28. VerifyAndGetLicenseKeyPack(
  29. HCRYPTPROV hCryptProv,
  30. PLicense_KeyPack pLicenseKeyPack,
  31. DWORD cbSignerCert,
  32. PBYTE pbSignerCert,
  33. DWORD cbRootCertificate,
  34. PBYTE pbRootCertificate,
  35. DWORD cbSignedBlob,
  36. PBYTE pbSignedBlob
  37. );
  38. DWORD WINAPI
  39. GetCertificate(
  40. DWORD cbCertificateBlob,
  41. PBYTE pbCertificateBlob,
  42. HCRYPTPROV hCryptProv,
  43. PCCERT_CONTEXT * ppCertContext,
  44. HCERTSTORE * phCertStore
  45. );
  46. DWORD WINAPI
  47. VerifyCertificateChain(
  48. HCERTSTORE hCertStore,
  49. PCCERT_CONTEXT pCertContext,
  50. DWORD cbRootCertificate,
  51. PBYTE pbRootCertificate
  52. );
  53. DWORD WINAPI
  54. GetCertVerificationResult(
  55. DWORD dwFlags
  56. );
  57. DWORD WINAPI
  58. UnpackEnvelopedData(
  59. IN OUT PEnveloped_Data pEnvelopedData,
  60. IN DWORD cbPackedData,
  61. IN PBYTE pbPackedData
  62. );
  63. DWORD WINAPI
  64. GetEnvelopedData(
  65. IN DWORD dwEncyptType,
  66. IN HCRYPTPROV hCryptProv,
  67. IN PEnveloped_Data pEnvelopedData,
  68. OUT PDWORD pcbData,
  69. OUT PBYTE *ppbData
  70. );
  71. /////////////////////////////////////////////////////////
  72. DWORD WINAPI
  73. LicensePackEncryptDecryptData(
  74. IN PBYTE pbParm,
  75. IN DWORD cbParm,
  76. IN OUT PBYTE pbData,
  77. IN DWORD cbData
  78. )
  79. /*++
  80. Abstract:
  81. Internal routine to encrypt/decrypt a blob of data
  82. Parameter:
  83. pbParm : binary blob to generate encrypt/decrypt key.
  84. cbParm : size of binary blob.
  85. pbData : data to be encrypt/decrypt.
  86. cbData : size of data to be encrypt/decrypt.
  87. Returns:
  88. ERROR_SUCCESS or error code.
  89. Remark:
  90. --*/
  91. {
  92. DWORD dwRetCode = ERROR_SUCCESS;
  93. MD5_CTX md5Ctx;
  94. RC4_KEYSTRUCT rc4KS;
  95. BYTE key[16];
  96. int i;
  97. if(NULL == pbParm || 0 == cbParm)
  98. {
  99. SetLastError(dwRetCode = ERROR_INVALID_PARAMETER);
  100. return dwRetCode;
  101. }
  102. MD5Init(&md5Ctx);
  103. MD5Update(
  104. &md5Ctx,
  105. pbParm,
  106. cbParm
  107. );
  108. MD5Final(&md5Ctx);
  109. memset(key, 0, sizeof(key));
  110. for(i=0; i < 5; i++)
  111. {
  112. key[i] = md5Ctx.digest[i];
  113. }
  114. //
  115. // Call RC4 to encrypt/decrypt data
  116. //
  117. rc4_key(
  118. &rc4KS,
  119. sizeof(key),
  120. key
  121. );
  122. rc4(
  123. &rc4KS,
  124. cbData,
  125. pbData
  126. );
  127. return dwRetCode;
  128. }
  129. static BYTE rgbPubKeyWithExponentOfOne[] =
  130. {
  131. 0x06, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
  132. 0x52, 0x53, 0x41, 0x31, 0x00, 0x02, 0x00, 0x00,
  133. 0x01, 0x00, 0x00, 0x00,
  134. 0xab, 0xef, 0xfa, 0xc6, 0x7d, 0xe8, 0xde, 0xfb,
  135. 0x68, 0x38, 0x09, 0x92, 0xd9, 0x42, 0x7e, 0x6b,
  136. 0x89, 0x9e, 0x21, 0xd7, 0x52, 0x1c, 0x99, 0x3c,
  137. 0x17, 0x48, 0x4e, 0x3a, 0x44, 0x02, 0xf2, 0xfa,
  138. 0x74, 0x57, 0xda, 0xe4, 0xd3, 0xc0, 0x35, 0x67,
  139. 0xfa, 0x6e, 0xdf, 0x78, 0x4c, 0x75, 0x35, 0x1c,
  140. 0xa0, 0x74, 0x49, 0xe3, 0x20, 0x13, 0x71, 0x35,
  141. 0x65, 0xdf, 0x12, 0x20, 0xf5, 0xf5, 0xf5, 0xc1
  142. };
  143. //---------------------------------------------------------------
  144. BOOL WINAPI
  145. GetPlaintextKey(
  146. IN HCRYPTPROV hProv,
  147. IN HCRYPTKEY hSymKey,
  148. OUT BYTE *pbPlainKey // this must be a 16 byte buffer
  149. )
  150. /*++
  151. part of Jeff Spelman's code
  152. --*/
  153. {
  154. HCRYPTKEY hPubKey = 0;
  155. BYTE rgbSimpleBlob[128];
  156. DWORD cbSimpleBlob;
  157. BYTE *pb;
  158. DWORD i;
  159. BOOL fRet = FALSE;
  160. memset(rgbSimpleBlob, 0, sizeof(rgbSimpleBlob));
  161. if (!CryptImportKey(hProv,
  162. rgbPubKeyWithExponentOfOne,
  163. sizeof(rgbPubKeyWithExponentOfOne),
  164. 0,
  165. 0,
  166. &hPubKey))
  167. {
  168. goto Ret;
  169. }
  170. cbSimpleBlob = sizeof(rgbSimpleBlob);
  171. if (!CryptExportKey(hSymKey,
  172. hPubKey,
  173. SIMPLEBLOB,
  174. 0,
  175. rgbSimpleBlob,
  176. &cbSimpleBlob))
  177. {
  178. goto Ret;
  179. }
  180. memset(pbPlainKey, 0, 16);
  181. pb = rgbSimpleBlob + sizeof(BLOBHEADER) + sizeof(ALG_ID);
  182. // byte reverse the key
  183. for (i = 0; i < 5; i++)
  184. {
  185. pbPlainKey[i] = pb[5 - (i + 1)];
  186. }
  187. fRet = TRUE;
  188. Ret:
  189. if (hPubKey)
  190. {
  191. CryptDestroyKey(hPubKey);
  192. }
  193. return fRet;
  194. }
  195. //--------------------------------------------------------------------
  196. DWORD WINAPI
  197. KeyPackDecryptData(
  198. IN DWORD dwEncryptType,
  199. IN HCRYPTPROV hCryptProv,
  200. IN BYTE* pbEncryptKey,
  201. IN DWORD cbEncryptKey,
  202. IN BYTE* pbEncryptData,
  203. IN DWORD cbEncryptData,
  204. OUT PBYTE* ppbDecryptData,
  205. OUT PDWORD pcbDecryptData
  206. )
  207. /*++
  208. Abstract:
  209. Decrypt a blob of data
  210. Parameters:
  211. bForceCrypto : TRUE if always use Crypto. API, FALSE otherwise.
  212. hCryptProv :
  213. pbEncryptKey :
  214. cbEncryptKey :
  215. pbEncryptData :
  216. cbEncryptData :
  217. ppbDecryptData :
  218. pcbDecryptData :
  219. Returns:
  220. ERROR_SUCCESS or error code.
  221. Remark:
  222. --*/
  223. {
  224. HCRYPTKEY hSymKey = 0;
  225. DWORD dwErrCode = ERROR_SUCCESS;
  226. BYTE rgbPlainKey[16];
  227. RC4_KEYSTRUCT KeyStruct;
  228. BOOL bFrenchLocale;
  229. bFrenchLocale = (MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH) == GetSystemDefaultLangID());
  230. if( (HCRYPTPROV)NULL == hCryptProv || NULL == pbEncryptKey || 0 == cbEncryptKey ||
  231. NULL == pbEncryptData || 0 == cbEncryptData )
  232. {
  233. SetLastError(dwErrCode = ERROR_INVALID_PARAMETER);
  234. return dwErrCode;
  235. }
  236. if( NULL == ppbDecryptData || NULL == pcbDecryptData )
  237. {
  238. SetLastError(dwErrCode = ERROR_INVALID_PARAMETER);
  239. return dwErrCode;
  240. }
  241. *pcbDecryptData = 0;
  242. *ppbDecryptData = NULL;
  243. if(!CryptImportKey(
  244. hCryptProv,
  245. pbEncryptKey,
  246. cbEncryptKey,
  247. 0,
  248. CRYPT_EXPORTABLE,
  249. &hSymKey
  250. ))
  251. {
  252. dwErrCode = GetLastError();
  253. goto cleanup;
  254. }
  255. *pcbDecryptData = cbEncryptData;
  256. *ppbDecryptData = (PBYTE) LocalAlloc(LPTR, cbEncryptData);
  257. if(NULL == *ppbDecryptData)
  258. {
  259. dwErrCode = GetLastError();
  260. goto cleanup;
  261. }
  262. memcpy(
  263. *ppbDecryptData,
  264. pbEncryptData,
  265. *pcbDecryptData
  266. );
  267. if( LICENSE_KEYPACK_ENCRYPT_ALWAYSFRENCH == dwEncryptType ||
  268. (TRUE == bFrenchLocale && LICENSE_KEYPACK_ENCRYPT_CRYPTO == dwEncryptType) )
  269. {
  270. if(!GetPlaintextKey(
  271. hCryptProv,
  272. hSymKey,
  273. rgbPlainKey))
  274. {
  275. dwErrCode = GetLastError();
  276. goto cleanup;
  277. }
  278. //
  279. // RC4 - input buffer size = output buffer size
  280. //
  281. rc4_key(&KeyStruct, sizeof(rgbPlainKey), rgbPlainKey);
  282. rc4(&KeyStruct, *pcbDecryptData, *ppbDecryptData);
  283. dwErrCode = ERROR_SUCCESS;
  284. }
  285. else
  286. {
  287. if(!CryptDecrypt(hSymKey, 0, TRUE, 0, *ppbDecryptData, pcbDecryptData))
  288. {
  289. dwErrCode = GetLastError();
  290. if(NTE_BAD_LEN == dwErrCode)
  291. {
  292. PBYTE pbNew;
  293. //
  294. // output buffer is too small, re-allocate
  295. //
  296. pbNew = (PBYTE) LocalReAlloc(
  297. *ppbDecryptData,
  298. *pcbDecryptData,
  299. LMEM_ZEROINIT
  300. );
  301. if(NULL == pbNew)
  302. {
  303. dwErrCode = GetLastError();
  304. goto cleanup;
  305. }
  306. *ppbDecryptData = pbNew;
  307. }
  308. memcpy(
  309. *ppbDecryptData,
  310. pbEncryptData,
  311. cbEncryptData
  312. );
  313. if(!CryptDecrypt(hSymKey, 0, TRUE, 0, *ppbDecryptData, pcbDecryptData))
  314. {
  315. dwErrCode = GetLastError();
  316. }
  317. }
  318. }
  319. cleanup:
  320. if (hSymKey)
  321. {
  322. CryptDestroyKey(hSymKey);
  323. }
  324. if(dwErrCode != ERROR_SUCCESS)
  325. {
  326. if(*ppbDecryptData != NULL)
  327. {
  328. LocalFree(*ppbDecryptData);
  329. }
  330. *ppbDecryptData = NULL;
  331. *pcbDecryptData = 0;
  332. }
  333. return dwErrCode;
  334. }
  335. ///////////////////////////////////////////////////////////////////////////////
  336. //
  337. // decode the encrypted license key pack blob with the license server's private
  338. // key.
  339. //
  340. // hCryptProv is opened with the key container that contains the key exchange
  341. // private key.
  342. //
  343. ///////////////////////////////////////////////////////////////////////////////
  344. DWORD WINAPI
  345. DecodeLicenseKeyPackEx(
  346. OUT PLicense_KeyPack pLicenseKeyPack,
  347. IN PLicensePackDecodeParm pDecodeParm,
  348. IN DWORD cbKeyPackBlob,
  349. IN PBYTE pbKeyPackBlob
  350. )
  351. /*++
  352. Abstract:
  353. Decode the encrypted license key pack blob.
  354. Parameters:
  355. pLicenseKeyPack : Decoded license key pack.
  356. hCryptProv :
  357. --*/
  358. {
  359. DWORD dwRetCode = ERROR_SUCCESS;
  360. DWORD cbSignedBlob, cbSignature;
  361. PBYTE pbSignedBlob = NULL, pcbSignature = NULL;
  362. Enveloped_Data EnvelopedData;
  363. PEncodedLicenseKeyPack pEncodedLicensePack;
  364. if( NULL == pLicenseKeyPack || NULL == pDecodeParm ||
  365. NULL == pbKeyPackBlob || 0 == cbKeyPackBlob )
  366. {
  367. return ERROR_INVALID_PARAMETER;
  368. }
  369. if( (HCRYPTPROV)NULL == pDecodeParm->hCryptProv )
  370. {
  371. return ERROR_INVALID_PARAMETER;
  372. }
  373. pEncodedLicensePack = (PEncodedLicenseKeyPack)pbKeyPackBlob;
  374. if(pEncodedLicensePack->dwSignature != LICENSEPACKENCODE_SIGNATURE)
  375. {
  376. //
  377. // EncodedLicenseKeyPack() puts size of encryption key as first DWORD
  378. //
  379. dwRetCode = DecodeLicenseKeyPack(
  380. pLicenseKeyPack,
  381. pDecodeParm->hCryptProv,
  382. pDecodeParm->cbClearingHouseCert,
  383. pDecodeParm->pbClearingHouseCert,
  384. pDecodeParm->cbRootCertificate,
  385. pDecodeParm->pbRootCertificate,
  386. cbKeyPackBlob,
  387. pbKeyPackBlob
  388. );
  389. return dwRetCode;
  390. }
  391. if(pEncodedLicensePack->dwStructVersion > LICENSEPACKENCODE_CURRENTVERSION)
  392. {
  393. return ERROR_INVALID_DATA;
  394. }
  395. if( pEncodedLicensePack->dwEncodeType > LICENSE_KEYPACK_ENCRYPT_MAX )
  396. {
  397. return ERROR_INVALID_DATA;
  398. }
  399. if( cbKeyPackBlob != offsetof(EncodedLicenseKeyPack, pbData) + pEncodedLicensePack->cbData )
  400. {
  401. return ERROR_INVALID_DATA;
  402. }
  403. //
  404. // depends on encryption type, check input parameter
  405. //
  406. if( LICENSE_KEYPACK_ENCRYPT_PRIVATE == pEncodedLicensePack->dwEncodeType )
  407. {
  408. if(NULL == pDecodeParm->pbDecryptParm || 0 == pDecodeParm->cbDecryptParm )
  409. {
  410. return ERROR_INVALID_PARAMETER;
  411. }
  412. }
  413. if( 0 == pDecodeParm->cbClearingHouseCert ||
  414. NULL == pDecodeParm->pbClearingHouseCert ||
  415. 0 == pDecodeParm->cbRootCertificate ||
  416. NULL == pDecodeParm->pbRootCertificate )
  417. {
  418. return ERROR_INVALID_PARAMETER;
  419. }
  420. //
  421. // Get the enveloped data
  422. //
  423. memset(
  424. &EnvelopedData,
  425. 0,
  426. sizeof( Enveloped_Data )
  427. );
  428. dwRetCode = UnpackEnvelopedData(
  429. &EnvelopedData,
  430. pEncodedLicensePack->cbData,
  431. &(pEncodedLicensePack->pbData[0])
  432. );
  433. if( ERROR_SUCCESS != dwRetCode )
  434. {
  435. goto done;
  436. }
  437. switch( pEncodedLicensePack->dwEncodeType )
  438. {
  439. case LICENSE_KEYPACK_ENCRYPT_NONE:
  440. case LICENSE_KEYPACK_ENCRYPT_PRIVATE:
  441. pbSignedBlob = EnvelopedData.pbEncryptedData;
  442. cbSignedBlob = EnvelopedData.cbEncryptedData;
  443. EnvelopedData.pbEncryptedData = NULL;
  444. EnvelopedData.pbEncryptedData = 0;
  445. if( LICENSE_KEYPACK_ENCRYPT_PRIVATE == pEncodedLicensePack->dwEncodeType )
  446. {
  447. dwRetCode = LicensePackEncryptDecryptData(
  448. pDecodeParm->pbDecryptParm,
  449. pDecodeParm->cbDecryptParm,
  450. pbSignedBlob,
  451. cbSignedBlob
  452. );
  453. }
  454. break;
  455. case LICENSE_KEYPACK_ENCRYPT_CRYPTO:
  456. case LICENSE_KEYPACK_ENCRYPT_ALWAYSCRYPTO:
  457. case LICENSE_KEYPACK_ENCRYPT_ALWAYSFRENCH:
  458. //
  459. // unpack the enveloped data to get the signed keypack blob
  460. //
  461. dwRetCode = GetEnvelopedData(
  462. pEncodedLicensePack->dwEncodeType,
  463. pDecodeParm->hCryptProv,
  464. &EnvelopedData,
  465. &cbSignedBlob,
  466. &pbSignedBlob
  467. );
  468. break;
  469. default:
  470. // impossible to come here
  471. dwRetCode = ERROR_INVALID_DATA;
  472. }
  473. if( ERROR_SUCCESS != dwRetCode )
  474. {
  475. goto done;
  476. }
  477. //
  478. // Get the license keypack from the signed blob. We also provide the
  479. // clearing house certificate to verify the authenticity of the keypack.
  480. //
  481. dwRetCode = VerifyAndGetLicenseKeyPack(
  482. pDecodeParm->hCryptProv,
  483. pLicenseKeyPack,
  484. pDecodeParm->cbClearingHouseCert,
  485. pDecodeParm->pbClearingHouseCert,
  486. pDecodeParm->cbRootCertificate,
  487. pDecodeParm->pbRootCertificate,
  488. cbSignedBlob,
  489. pbSignedBlob
  490. );
  491. done:
  492. if( EnvelopedData.pbEncryptedKey )
  493. {
  494. LocalFree( EnvelopedData.pbEncryptedKey );
  495. }
  496. if( EnvelopedData.pbEncryptedData )
  497. {
  498. LocalFree( EnvelopedData.pbEncryptedData );
  499. }
  500. if( pbSignedBlob )
  501. {
  502. LocalFree( pbSignedBlob );
  503. }
  504. return( dwRetCode );
  505. }
  506. ///////////////////////////////////////////////////////////////////////////////
  507. DWORD WINAPI
  508. GetEnvelopedData(
  509. IN DWORD dwEncryptType,
  510. IN HCRYPTPROV hCryptProv,
  511. IN PEnveloped_Data pEnvelopedData,
  512. OUT PDWORD pcbData,
  513. OUT PBYTE *ppbData
  514. )
  515. /*++
  516. --*/
  517. {
  518. HCRYPTKEY hPrivateKey = 0;
  519. DWORD dwRetCode = ERROR_SUCCESS;
  520. if( (HCRYPTPROV)NULL == hCryptProv || pEnvelopedData == NULL ||
  521. ppbData == NULL || pcbData == NULL )
  522. {
  523. SetLastError(dwRetCode = ERROR_INVALID_PARAMETER);
  524. return dwRetCode;
  525. }
  526. //
  527. // Make sure we have a exchange key to decrypt session key.
  528. //
  529. if( !CryptGetUserKey( hCryptProv, AT_KEYEXCHANGE, &hPrivateKey ) )
  530. {
  531. dwRetCode = GetLastError();
  532. goto done;
  533. }
  534. //
  535. // decrypt the data, KeyPackDecryptData() handle
  536. // memory freeing in case of error.
  537. //
  538. dwRetCode = KeyPackDecryptData(
  539. dwEncryptType,
  540. hCryptProv,
  541. pEnvelopedData->pbEncryptedKey,
  542. pEnvelopedData->cbEncryptedKey,
  543. pEnvelopedData->pbEncryptedData,
  544. pEnvelopedData->cbEncryptedData,
  545. ppbData,
  546. pcbData
  547. );
  548. done:
  549. if( hPrivateKey )
  550. {
  551. CryptDestroyKey( hPrivateKey );
  552. }
  553. return( dwRetCode );
  554. }
  555. ///////////////////////////////////////////////////////////////////////////////
  556. DWORD WINAPI
  557. UnpackEnvelopedData(
  558. IN OUT PEnveloped_Data pEnvelopedData,
  559. IN DWORD cbPackedData,
  560. IN PBYTE pbPackedData
  561. )
  562. /*++
  563. Abstract:
  564. Unpack an encrypted license pack blob.
  565. Parameters:
  566. pEnvelopedData :
  567. cbPackedData :
  568. pbPackedData :
  569. Returns:
  570. --*/
  571. {
  572. PBYTE pbCopyPos = pbPackedData;
  573. DWORD cbDataToUnpack = cbPackedData;
  574. //
  575. // ensure that the data is of minimum length
  576. //
  577. if( ( ( sizeof( DWORD ) * 2 ) > cbPackedData ) ||
  578. ( NULL == pbPackedData ) ||
  579. ( NULL == pEnvelopedData ) )
  580. {
  581. return( ERROR_INVALID_PARAMETER );
  582. }
  583. //
  584. // read a DWORD to get the encrypted key length
  585. //
  586. memcpy( &pEnvelopedData->cbEncryptedKey, pbCopyPos, sizeof( DWORD ) );
  587. pbCopyPos += sizeof( DWORD );
  588. cbDataToUnpack -= sizeof( DWORD );
  589. if( cbDataToUnpack < pEnvelopedData->cbEncryptedKey )
  590. {
  591. return( ERROR_INVALID_DATA );
  592. }
  593. //
  594. // Allocate memory to unpack the encrypted key
  595. //
  596. if(pEnvelopedData->cbEncryptedKey > 0)
  597. {
  598. pEnvelopedData->pbEncryptedKey = LocalAlloc( GPTR, pEnvelopedData->cbEncryptedKey );
  599. if( NULL == pEnvelopedData->pbEncryptedKey )
  600. {
  601. return( GetLastError() );
  602. }
  603. memcpy( pEnvelopedData->pbEncryptedKey, pbCopyPos, pEnvelopedData->cbEncryptedKey );
  604. }
  605. pbCopyPos += pEnvelopedData->cbEncryptedKey;
  606. cbDataToUnpack -= pEnvelopedData->cbEncryptedKey;
  607. //
  608. // expecting to read a DWORD for the encrypted data length
  609. //
  610. if( sizeof( DWORD ) > cbDataToUnpack )
  611. {
  612. return( ERROR_INVALID_DATA );
  613. }
  614. memcpy( &pEnvelopedData->cbEncryptedData, pbCopyPos, sizeof( DWORD ) );
  615. pbCopyPos += sizeof( DWORD );
  616. cbDataToUnpack -= sizeof( DWORD );
  617. if( cbDataToUnpack < pEnvelopedData->cbEncryptedData )
  618. {
  619. return( ERROR_INVALID_DATA );
  620. }
  621. //
  622. // allocate memory for the encrypted data
  623. //
  624. pEnvelopedData->pbEncryptedData = LocalAlloc( GPTR, pEnvelopedData->cbEncryptedData );
  625. if( NULL == pEnvelopedData->pbEncryptedData )
  626. {
  627. return( GetLastError() );
  628. }
  629. memcpy( pEnvelopedData->pbEncryptedData, pbCopyPos, pEnvelopedData->cbEncryptedData );
  630. return( ERROR_SUCCESS );
  631. }
  632. ///////////////////////////////////////////////////////////////////////////////
  633. //
  634. // decode the encrypted license key pack blob with the license server's private
  635. // key.
  636. //
  637. // hCryptProv is opened with the key container that contains the key exchange
  638. // private key.
  639. //
  640. ///////////////////////////////////////////////////////////////////////////////
  641. DWORD WINAPI
  642. DecodeLicenseKeyPack(
  643. PLicense_KeyPack pLicenseKeyPack,
  644. HCRYPTPROV hCryptProv,
  645. DWORD cbClearingHouseCert,
  646. PBYTE pbClearingHouseCert,
  647. DWORD cbRootCertificate,
  648. PBYTE pbRootCertificate,
  649. DWORD cbKeyPackBlob,
  650. PBYTE pbKeyPackBlob )
  651. {
  652. DWORD dwRetCode = ERROR_SUCCESS;
  653. DWORD cbSignedBlob, cbSignature;
  654. PBYTE pbSignedBlob = NULL, pcbSignature = NULL;
  655. Enveloped_Data EnvelopedData;
  656. if( 0 == hCryptProv )
  657. {
  658. return( ERROR_INVALID_PARAMETER );
  659. }
  660. //
  661. // Get the enveloped data
  662. //
  663. memset( &EnvelopedData, 0, sizeof( Enveloped_Data ) );
  664. dwRetCode = UnpackEnvelopedData( &EnvelopedData, cbKeyPackBlob, pbKeyPackBlob );
  665. if( ERROR_SUCCESS != dwRetCode )
  666. {
  667. goto done;
  668. }
  669. //
  670. // unpack the enveloped data to get the signed keypack blob
  671. //
  672. dwRetCode = GetEnvelopedData(
  673. LICENSE_KEYPACK_ENCRYPT_CRYPTO,
  674. hCryptProv,
  675. &EnvelopedData,
  676. &cbSignedBlob,
  677. &pbSignedBlob
  678. );
  679. if( ERROR_SUCCESS != dwRetCode )
  680. {
  681. goto done;
  682. }
  683. //
  684. // Get the license keypack from the signed blob. We also provide the
  685. // clearing house certificate to verify the authenticity of the keypack.
  686. //
  687. dwRetCode = VerifyAndGetLicenseKeyPack( hCryptProv, pLicenseKeyPack,
  688. cbClearingHouseCert, pbClearingHouseCert,
  689. cbRootCertificate, pbRootCertificate,
  690. cbSignedBlob, pbSignedBlob );
  691. done:
  692. if( EnvelopedData.pbEncryptedKey )
  693. {
  694. LocalFree( EnvelopedData.pbEncryptedKey );
  695. }
  696. if( EnvelopedData.pbEncryptedData )
  697. {
  698. LocalFree( EnvelopedData.pbEncryptedData );
  699. }
  700. if( pbSignedBlob )
  701. {
  702. LocalFree( pbSignedBlob );
  703. }
  704. return( dwRetCode );
  705. }
  706. ///////////////////////////////////////////////////////////////////////////////
  707. DWORD WINAPI
  708. VerifyAndGetLicenseKeyPack(
  709. HCRYPTPROV hCryptProv,
  710. PLicense_KeyPack pLicenseKeyPack,
  711. DWORD cbSignerCert,
  712. PBYTE pbSignerCert,
  713. DWORD cbRootCertificate,
  714. PBYTE pbRootCertificate,
  715. DWORD cbSignedBlob,
  716. PBYTE pbSignedBlob )
  717. {
  718. DWORD dwRetCode = ERROR_SUCCESS;
  719. PCCERT_CONTEXT pCertContext = 0;
  720. HCERTSTORE hCertStore = 0;
  721. HCRYPTHASH hCryptHash = 0;
  722. HCRYPTKEY hPubKey = 0;
  723. PBYTE pbCopyPos = pbSignedBlob, pbSignedHash;
  724. PKeyPack_Description pKpDesc;
  725. DWORD i, cbSignedHash;
  726. SetLastError(ERROR_SUCCESS);
  727. //
  728. // make sure that the signed key blob is of the minimum size
  729. //
  730. if( cbSignedBlob < ( ( 8 * sizeof( DWORD ) ) + ( 3 * sizeof( FILETIME ) ) +
  731. sizeof( GUID ) ) )
  732. {
  733. return( ERROR_INVALID_PARAMETER );
  734. }
  735. //
  736. // get a certificate context for the signer's certificate
  737. //
  738. dwRetCode = GetCertificate( cbSignerCert,
  739. pbSignerCert,
  740. hCryptProv,
  741. &pCertContext,
  742. &hCertStore );
  743. if( ERROR_SUCCESS != dwRetCode )
  744. {
  745. SetLastError(dwRetCode);
  746. goto ErrorReturn;
  747. }
  748. //
  749. // Verify the signer's certificate and the certificate chain that issued the
  750. // certificate.
  751. //
  752. dwRetCode = VerifyCertificateChain( hCertStore, pCertContext,
  753. cbRootCertificate, pbRootCertificate );
  754. if( ERROR_SUCCESS != dwRetCode )
  755. {
  756. SetLastError(dwRetCode);
  757. goto ErrorReturn;
  758. }
  759. //
  760. // unpack the signed blob
  761. //
  762. memcpy( &pLicenseKeyPack->dwVersion, pbCopyPos, sizeof( DWORD ) );
  763. pbCopyPos += sizeof( DWORD );
  764. memcpy( &pLicenseKeyPack->dwKeypackType, pbCopyPos, sizeof( DWORD ) );
  765. pbCopyPos += sizeof( DWORD );
  766. memcpy( &pLicenseKeyPack->dwDistChannel, pbCopyPos, sizeof( DWORD ) );
  767. pbCopyPos += sizeof( DWORD );
  768. memcpy( &pLicenseKeyPack->KeypackSerialNum, pbCopyPos, sizeof( GUID ) );
  769. pbCopyPos += sizeof( GUID );
  770. memcpy( &pLicenseKeyPack->IssueDate, pbCopyPos, sizeof( FILETIME ) );
  771. pbCopyPos += sizeof( FILETIME );
  772. memcpy( &pLicenseKeyPack->ActiveDate, pbCopyPos, sizeof( FILETIME ) );
  773. pbCopyPos += sizeof( FILETIME );
  774. memcpy( &pLicenseKeyPack->ExpireDate, pbCopyPos, sizeof( FILETIME ) );
  775. pbCopyPos += sizeof( FILETIME );
  776. memcpy( &pLicenseKeyPack->dwBeginSerialNum, pbCopyPos, sizeof( DWORD ) );
  777. pbCopyPos += sizeof( DWORD );
  778. memcpy( &pLicenseKeyPack->dwQuantity, pbCopyPos, sizeof( DWORD ) );
  779. pbCopyPos += sizeof( DWORD );
  780. memcpy( &pLicenseKeyPack->cbProductId, pbCopyPos, sizeof( DWORD ) );
  781. pbCopyPos += sizeof( DWORD );
  782. if( pLicenseKeyPack->cbProductId )
  783. {
  784. pLicenseKeyPack->pbProductId = LocalAlloc( GPTR, pLicenseKeyPack->cbProductId );
  785. if( NULL == pLicenseKeyPack->pbProductId )
  786. {
  787. goto ErrorReturn;
  788. }
  789. memcpy( pLicenseKeyPack->pbProductId, pbCopyPos, pLicenseKeyPack->cbProductId );
  790. pbCopyPos += pLicenseKeyPack->cbProductId;
  791. }
  792. memcpy( &pLicenseKeyPack->dwProductVersion, pbCopyPos, sizeof( DWORD ) );
  793. pbCopyPos += sizeof( DWORD );
  794. memcpy( &pLicenseKeyPack->dwPlatformId, pbCopyPos, sizeof( DWORD ) );
  795. pbCopyPos += sizeof( DWORD );
  796. memcpy( &pLicenseKeyPack->dwLicenseType, pbCopyPos, sizeof( DWORD ) );
  797. pbCopyPos += sizeof( DWORD );
  798. memcpy( &pLicenseKeyPack->dwDescriptionCount, pbCopyPos, sizeof( DWORD ) );
  799. pbCopyPos += sizeof( DWORD );
  800. if( pLicenseKeyPack->dwDescriptionCount )
  801. {
  802. //
  803. // allocate memory for the keypack descriptions structure
  804. //
  805. pLicenseKeyPack->pDescription = LocalAlloc( GPTR, ( sizeof( KeyPack_Description ) *
  806. pLicenseKeyPack->dwDescriptionCount ) );
  807. if( NULL == pLicenseKeyPack->pDescription )
  808. {
  809. goto ErrorReturn;
  810. }
  811. for( i = 0, pKpDesc = pLicenseKeyPack->pDescription;
  812. i < pLicenseKeyPack->dwDescriptionCount;
  813. i++, pKpDesc++ )
  814. {
  815. memcpy( &pKpDesc->Locale, pbCopyPos, sizeof( LCID ) );
  816. pbCopyPos += sizeof( LCID );
  817. memcpy( &pKpDesc->cbProductName, pbCopyPos, sizeof( DWORD ) );
  818. pbCopyPos += sizeof( DWORD );
  819. if( pKpDesc->cbProductName )
  820. {
  821. //
  822. // allocate memory for product name
  823. //
  824. pKpDesc->pbProductName = LocalAlloc( GPTR, pKpDesc->cbProductName );
  825. if( NULL == pKpDesc->pbProductName )
  826. {
  827. goto ErrorReturn;
  828. }
  829. //
  830. // copy the product name
  831. //
  832. memcpy( pKpDesc->pbProductName, pbCopyPos, pKpDesc->cbProductName );
  833. pbCopyPos += pKpDesc->cbProductName;
  834. }
  835. memcpy( &pKpDesc->cbDescription, pbCopyPos, sizeof( DWORD ) );
  836. pbCopyPos += sizeof( DWORD );
  837. if( pKpDesc->cbDescription )
  838. {
  839. //
  840. // allocate memory for the keypack description
  841. //
  842. pKpDesc->pDescription = LocalAlloc( GPTR, pKpDesc->cbDescription );
  843. if( NULL == pKpDesc->pDescription )
  844. {
  845. goto ErrorReturn;
  846. }
  847. //
  848. // copy the key pack description
  849. //
  850. memcpy( pKpDesc->pDescription, pbCopyPos, pKpDesc->cbDescription );
  851. pbCopyPos += pKpDesc->cbDescription;
  852. }
  853. }
  854. }
  855. memcpy( &pLicenseKeyPack->cbManufacturer, pbCopyPos, sizeof( DWORD ) );
  856. pbCopyPos += sizeof( DWORD );
  857. if( pLicenseKeyPack->cbManufacturer )
  858. {
  859. pLicenseKeyPack->pbManufacturer = LocalAlloc( GPTR, pLicenseKeyPack->cbManufacturer );
  860. if( NULL == pLicenseKeyPack->pbManufacturer )
  861. {
  862. goto ErrorReturn;
  863. }
  864. memcpy( pLicenseKeyPack->pbManufacturer, pbCopyPos, pLicenseKeyPack->cbManufacturer );
  865. pbCopyPos += pLicenseKeyPack->cbManufacturer;
  866. }
  867. memcpy( &pLicenseKeyPack->cbManufacturerData, pbCopyPos, sizeof( DWORD ) );
  868. pbCopyPos += sizeof( DWORD );
  869. if( pLicenseKeyPack->cbManufacturerData )
  870. {
  871. pLicenseKeyPack->pbManufacturerData = LocalAlloc( GPTR, pLicenseKeyPack->cbManufacturerData );
  872. if( NULL == pLicenseKeyPack->pbManufacturerData )
  873. {
  874. goto ErrorReturn;
  875. }
  876. memcpy( pLicenseKeyPack->pbManufacturerData, pbCopyPos, pLicenseKeyPack->cbManufacturerData );
  877. pbCopyPos += pLicenseKeyPack->cbManufacturerData;
  878. }
  879. //
  880. // get the size and the pointer of the signed hash.
  881. //
  882. memcpy( &cbSignedHash, pbCopyPos, sizeof( DWORD ) );
  883. pbSignedHash = pbCopyPos + sizeof( DWORD );
  884. //
  885. // compute the hash
  886. //
  887. if( !CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hCryptHash ) )
  888. {
  889. goto ErrorReturn;
  890. }
  891. if( !CryptHashData( hCryptHash, pbSignedBlob, (DWORD)(pbCopyPos - pbSignedBlob), 0 ) )
  892. {
  893. goto ErrorReturn;
  894. }
  895. //
  896. // import the public key
  897. //
  898. if( !CryptImportPublicKeyInfoEx( hCryptProv, X509_ASN_ENCODING,
  899. &pCertContext->pCertInfo->SubjectPublicKeyInfo,
  900. CALG_RSA_SIGN, 0, NULL, &hPubKey ) )
  901. {
  902. goto ErrorReturn;
  903. }
  904. //
  905. // use the public key to verify the signed hash
  906. //
  907. if( !CryptVerifySignature( hCryptHash, pbSignedHash, cbSignedHash, hPubKey,
  908. NULL, 0) )
  909. {
  910. goto ErrorReturn;
  911. }
  912. ErrorReturn:
  913. dwRetCode = GetLastError();
  914. if( hCryptHash )
  915. {
  916. CryptDestroyHash( hCryptHash );
  917. }
  918. if( hPubKey )
  919. {
  920. CryptDestroyKey( hPubKey );
  921. }
  922. if( pCertContext )
  923. {
  924. CertFreeCertificateContext( pCertContext );
  925. }
  926. if( hCertStore )
  927. {
  928. CertCloseStore( hCertStore, CERT_CLOSE_STORE_FORCE_FLAG );
  929. }
  930. return( dwRetCode );
  931. }
  932. ///////////////////////////////////////////////////////////////////////////////
  933. //
  934. // GetCertificate
  935. //
  936. // Get the first certificate from the certificate blob. The certificate blob
  937. // is in fact a certificate store that may contain a chain of certificates.
  938. // This function also return handles to the crypto provider and the certificate
  939. // store.
  940. //
  941. ///////////////////////////////////////////////////////////////////////////////
  942. DWORD WINAPI
  943. GetCertificate(
  944. DWORD cbCertificateBlob,
  945. PBYTE pbCertificateBlob,
  946. HCRYPTPROV hCryptProv,
  947. PCCERT_CONTEXT * ppCertContext,
  948. HCERTSTORE * phCertStore )
  949. {
  950. CRYPT_DATA_BLOB CertBlob;
  951. DWORD dwRetCode = ERROR_SUCCESS;
  952. //
  953. // Open the PKCS7 certificate store
  954. //
  955. CertBlob.cbData = cbCertificateBlob;
  956. CertBlob.pbData = pbCertificateBlob;
  957. *phCertStore = CertOpenStore( sz_CERT_STORE_PROV_PKCS7,
  958. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  959. hCryptProv,
  960. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  961. &CertBlob );
  962. if( NULL == ( *phCertStore ) )
  963. {
  964. return( GetLastError() );
  965. }
  966. //
  967. // get the first certificate from the store
  968. //
  969. *ppCertContext = CertEnumCertificatesInStore( *phCertStore, NULL );
  970. if( NULL == ( *ppCertContext ) )
  971. {
  972. return( GetLastError() );
  973. }
  974. return( dwRetCode );
  975. }
  976. ///////////////////////////////////////////////////////////////////////////////
  977. //
  978. // VerifyCertificateChain
  979. //
  980. // Verify the certificate represented by the cert context against the
  981. // issuers in the certificate store. The caller may provide a root
  982. // certificate so that all issuers are eventually verified against this
  983. // root certificate. If no root certificate is provided, then the last
  984. // issuer in the chain must be a self-signing issuer.
  985. //
  986. ///////////////////////////////////////////////////////////////////////////////
  987. DWORD WINAPI
  988. VerifyCertificateChain(
  989. HCERTSTORE hCertStore,
  990. PCCERT_CONTEXT pCertContext,
  991. DWORD cbRootCertificate,
  992. PBYTE pbRootCertificate )
  993. {
  994. DWORD dwRetCode = ERROR_SUCCESS, dwFlags;
  995. PCCERT_CONTEXT pRootCertCtx = NULL;
  996. PCCERT_CONTEXT pIssuerCertCtx = NULL;
  997. PCCERT_CONTEXT pCurrentContext = NULL;
  998. if( ( 0 != cbRootCertificate ) && ( NULL != pbRootCertificate ) )
  999. {
  1000. //
  1001. // Get a certificate context for the root certificate
  1002. //
  1003. pRootCertCtx = CertCreateCertificateContext( X509_ASN_ENCODING,
  1004. pbRootCertificate,
  1005. cbRootCertificate );
  1006. if( NULL == pRootCertCtx )
  1007. {
  1008. dwRetCode = GetLastError();
  1009. goto done;
  1010. }
  1011. }
  1012. //
  1013. // Verify the certificate chain. The time, signature and validity of
  1014. // the subject certificate is verified. Only the signatures are verified
  1015. // for the certificates in the issuer chain.
  1016. //
  1017. dwFlags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG |
  1018. CERT_STORE_TIME_VALIDITY_FLAG;
  1019. pCurrentContext = CertDuplicateCertificateContext( pCertContext );
  1020. if (NULL == pCurrentContext)
  1021. {
  1022. dwRetCode = ERROR_INVALID_PARAMETER;
  1023. goto done;
  1024. }
  1025. do
  1026. {
  1027. pIssuerCertCtx = NULL;
  1028. pIssuerCertCtx = CertGetIssuerCertificateFromStore( hCertStore,
  1029. pCurrentContext,
  1030. pIssuerCertCtx,
  1031. &dwFlags );
  1032. if( pIssuerCertCtx )
  1033. {
  1034. //
  1035. // Found the issuer, verify that the checks went OK
  1036. //
  1037. dwRetCode = GetCertVerificationResult( dwFlags );
  1038. if( ERROR_SUCCESS != dwRetCode )
  1039. {
  1040. break;
  1041. }
  1042. //
  1043. // only verify the signature for subsequent issuer certificates
  1044. //
  1045. dwFlags = CERT_STORE_SIGNATURE_FLAG;
  1046. //
  1047. // free the current certificate context and make the current issuer certificate
  1048. // the subject certificate for the next iteration.
  1049. //
  1050. CertFreeCertificateContext( pCurrentContext );
  1051. pCurrentContext = pIssuerCertCtx;
  1052. }
  1053. } while( pIssuerCertCtx );
  1054. if( ERROR_SUCCESS != dwRetCode )
  1055. {
  1056. //
  1057. // encountered some error while verifying the certificate
  1058. //
  1059. goto done;
  1060. }
  1061. //
  1062. // we got here because we have walked through the chain of issuers in the
  1063. // store. The last issuer in the chain may or may not be a self signing root.
  1064. //
  1065. if( pRootCertCtx )
  1066. {
  1067. //
  1068. // The caller has specified a root certificate that must be used. Verify the
  1069. // last issuer against this root certificate regardless of whether it is a
  1070. // self signing root.
  1071. //
  1072. dwFlags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG |
  1073. CERT_STORE_TIME_VALIDITY_FLAG;
  1074. if( ( NULL == pCurrentContext ) ||
  1075. ( !CertVerifySubjectCertificateContext( pCurrentContext, pRootCertCtx, &dwFlags ) ) )
  1076. {
  1077. dwRetCode = GetLastError();
  1078. goto done;
  1079. }
  1080. //
  1081. // get the certificate verification result
  1082. //
  1083. dwRetCode = GetCertVerificationResult( dwFlags );
  1084. }
  1085. else
  1086. {
  1087. //
  1088. // if the caller did not specify a CA root certificate, make sure that the root
  1089. // issuer of the certificate is a self-signed root. Otherwise, return an error
  1090. //
  1091. if( CRYPT_E_SELF_SIGNED != GetLastError() )
  1092. {
  1093. dwRetCode = GetLastError();
  1094. }
  1095. }
  1096. done:
  1097. if( pRootCertCtx )
  1098. {
  1099. CertFreeCertificateContext( pRootCertCtx );
  1100. }
  1101. if( pCurrentContext )
  1102. {
  1103. CertFreeCertificateContext( pCurrentContext );
  1104. }
  1105. if( pIssuerCertCtx )
  1106. {
  1107. CertFreeCertificateContext( pIssuerCertCtx );
  1108. }
  1109. return( dwRetCode );
  1110. }
  1111. ///////////////////////////////////////////////////////////////////////////////
  1112. DWORD WINAPI
  1113. GetCertVerificationResult(
  1114. DWORD dwFlags )
  1115. {
  1116. if( dwFlags & CERT_STORE_SIGNATURE_FLAG )
  1117. {
  1118. //
  1119. // The certificate signature did not verify
  1120. //
  1121. return( (DWORD )NTE_BAD_SIGNATURE );
  1122. }
  1123. if( dwFlags & CERT_STORE_TIME_VALIDITY_FLAG )
  1124. {
  1125. //
  1126. // The certificate has expired
  1127. //
  1128. return( ( DWORD )CERT_E_EXPIRED );
  1129. }
  1130. //
  1131. // check if the cert has been revoked
  1132. //
  1133. if( dwFlags & CERT_STORE_REVOCATION_FLAG )
  1134. {
  1135. if( !( dwFlags & CERT_STORE_NO_CRL_FLAG ) )
  1136. {
  1137. //
  1138. // The certificate has been revoked
  1139. //
  1140. return( ( DWORD )CERT_E_REVOKED );
  1141. }
  1142. }
  1143. return( ERROR_SUCCESS );
  1144. }