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.

2474 lines
68 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: signhlp.cpp
  7. //
  8. // Contents: Digital Signing Helper APIs
  9. //
  10. // History: June-25-1997 Xiaohs Created
  11. //----------------------------------------------------------------------------
  12. #include "global.hxx"
  13. //+-------------------------------------------------------------------------
  14. // Local function for SpcGetCertFromKey
  15. //
  16. // Signer cert flags. Used to determine the "strength" of the signer cert.
  17. //
  18. // The following must be ordered as follows. ie, END_ENTITY_FLAG is most
  19. // important and needs to be the largest number.
  20. //--------------------------------------------------------------------------
  21. #define SIGNER_CERT_NOT_SELF_SIGNED_FLAG 0x00000001
  22. #define SIGNER_CERT_NOT_GLUE_FLAG 0x00000002
  23. #define SIGNER_CERT_NOT_CA_FLAG 0x00000004
  24. #define SIGNER_CERT_END_ENTITY_FLAG 0x00000008
  25. #define SIGNER_CERT_ALL_FLAGS 0x0000000F
  26. //--------------------------------------------------------------------------
  27. //
  28. // Copy all the certs from store name to hDescStore
  29. //
  30. //--------------------------------------------------------------------------
  31. HRESULT MoveStoreName(HCRYPTPROV hCryptProv,
  32. DWORD dwCertEncodingType,
  33. HCERTSTORE hDescStore,
  34. DWORD dwStoreName,
  35. DWORD dwStoreFlag)
  36. {
  37. HCERTSTORE hTmpStore=NULL;
  38. HRESULT hr;
  39. WCHAR wszStoreName[40];
  40. //load the name of the store
  41. if(0==LoadStringU(hInstance, dwStoreName, wszStoreName, 40))
  42. {
  43. hr=SignError();
  44. goto CLEANUP;
  45. }
  46. //open a system cert store
  47. if (NULL == (hTmpStore = CertOpenStore(
  48. CERT_STORE_PROV_SYSTEM_W,
  49. dwCertEncodingType,
  50. hCryptProv,
  51. dwStoreFlag,
  52. wszStoreName
  53. )))
  54. {
  55. hr=SignError();
  56. goto CLEANUP;
  57. }
  58. hr=MoveStore(hDescStore, hTmpStore);
  59. CLEANUP:
  60. if(hTmpStore)
  61. CertCloseStore(hTmpStore,0);
  62. return hr;
  63. }
  64. //--------------------------------------------------------------------------
  65. //
  66. // Copy all the certs from hSrcStore to hDescStore
  67. //
  68. //--------------------------------------------------------------------------
  69. HRESULT MoveStore(HCERTSTORE hDescStore,
  70. HCERTSTORE hSrcStore)
  71. {
  72. PCCERT_CONTEXT pCertContext=NULL;
  73. PCCERT_CONTEXT pPreContext=NULL;
  74. HRESULT hr=S_OK;
  75. while(pCertContext=CertEnumCertificatesInStore(hSrcStore,
  76. pPreContext))
  77. {
  78. if(!(CertAddCertificateContextToStore(hDescStore,
  79. pCertContext,CERT_STORE_ADD_USE_EXISTING,
  80. NULL)))
  81. {
  82. hr=SignError();
  83. goto CLEANUP;
  84. }
  85. pPreContext=pCertContext;
  86. pCertContext=NULL;
  87. }
  88. hr=S_OK;
  89. CLEANUP:
  90. if(pCertContext)
  91. CertFreeCertificateContext(pCertContext);
  92. return hr;
  93. }
  94. //--------------------------------------------------------------------------
  95. //
  96. // Build up the certificate chain. Put the whole chain to the store
  97. //
  98. //
  99. //--------------------------------------------------------------------------
  100. HRESULT BuildCertChain(HCRYPTPROV hCryptProv,
  101. DWORD dwCertEncodingType,
  102. HCERTSTORE hStore,
  103. HCERTSTORE hOptionalStore,
  104. PCCERT_CONTEXT pSigningCert,
  105. DWORD dwCertPolicy)
  106. {
  107. DWORD i=0;
  108. PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
  109. CERT_CHAIN_PARA CertChainPara;
  110. HRESULT hr=E_FAIL;
  111. //we regard the chain is good unless there are some cryptographic errors.
  112. //all error code regarding trusted root and CTLs are machine dependent, therefore
  113. //they are ignored. We do not consider revocation.
  114. DWORD dwChainError=CERT_TRUST_IS_NOT_TIME_VALID |
  115. CERT_TRUST_IS_NOT_SIGNATURE_VALID;
  116. memset(&CertChainPara, 0, sizeof(CertChainPara));
  117. CertChainPara.cbSize = sizeof(CertChainPara);
  118. if (!CertGetCertificateChain(
  119. HCCE_CURRENT_USER,
  120. pSigningCert,
  121. NULL,
  122. hOptionalStore,
  123. &CertChainPara,
  124. 0,
  125. NULL,
  126. &pCertChainContext))
  127. {
  128. hr=SignError();
  129. goto CLEANUP;
  130. }
  131. //
  132. // make sure there is at least 1 simple chain
  133. //
  134. if (pCertChainContext->cChain == 0)
  135. {
  136. hr=SignError();
  137. goto CLEANUP;
  138. }
  139. // make sure that we have a good chain
  140. if(dwChainError & (pCertChainContext->rgpChain[0]->TrustStatus.dwErrorStatus))
  141. {
  142. hr=CERT_E_CHAINING;
  143. goto CLEANUP;
  144. }
  145. i = 0;
  146. while (i < pCertChainContext->rgpChain[0]->cElement)
  147. {
  148. //
  149. // if we are supposed to skip the root cert,
  150. // and we are on the root cert, then continue
  151. //
  152. if(dwCertPolicy & SIGNER_CERT_POLICY_CHAIN_NO_ROOT ||
  153. dwCertPolicy & SIGNER_CERT_POLICY_SPC)
  154. {
  155. if ((pCertChainContext->rgpChain[0]->rgpElement[i]->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED))
  156. {
  157. i++;
  158. continue;
  159. }
  160. }
  161. CertAddCertificateContextToStore(
  162. hStore,
  163. pCertChainContext->rgpChain[0]->rgpElement[i]->pCertContext,
  164. CERT_STORE_ADD_REPLACE_EXISTING,
  165. NULL);
  166. i++;
  167. }
  168. hr=S_OK;
  169. CLEANUP:
  170. if (pCertChainContext != NULL)
  171. {
  172. CertFreeCertificateChain(pCertChainContext);
  173. }
  174. return hr;
  175. }
  176. //--------------------------------------------------------------------------
  177. //
  178. // Make sure the two certificates are the same
  179. //
  180. //
  181. //--------------------------------------------------------------------------
  182. BOOL SameCert(PCCERT_CONTEXT pCertOne, PCCERT_CONTEXT pCertTwo)
  183. {
  184. if(!pCertOne || !pCertTwo)
  185. return FALSE;
  186. if(pCertOne->cbCertEncoded != pCertTwo->cbCertEncoded)
  187. return FALSE;
  188. if(0 == memcmp(pCertOne->pbCertEncoded, pCertTwo->pbCertEncoded, pCertTwo->cbCertEncoded))
  189. return TRUE;
  190. return FALSE;
  191. }
  192. //The following cert chain building code is obsolete. The new cert chain
  193. //building API should be used
  194. //--------------------------------------------------------------------------
  195. //
  196. // Build up the certificate chain. Put the whole chain to the store
  197. //
  198. //
  199. //--------------------------------------------------------------------------
  200. /*HRESULT BuildCertChain(HCRYPTPROV hCryptProv,
  201. DWORD dwCertEncodingType,
  202. HCERTSTORE hStore,
  203. HCERTSTORE hOptionalStore,
  204. PCCERT_CONTEXT pSigningCert,
  205. DWORD dwCertPolicy)
  206. {
  207. HRESULT hr=E_FAIL;
  208. HCERTSTORE hSpcStore=NULL;
  209. PCCERT_CONTEXT pSubCertContext=NULL;
  210. PCCERT_CONTEXT pIssuerCertContext=NULL;
  211. PCCERT_CONTEXT pFindCertContext=NULL;
  212. LPWSTR rgwszStoreName[4] ={L"MY", L"ROOT", L"CA",L"SPC"};
  213. DWORD dwStoreOpenFlag=0;
  214. HCERTSTORE rghStore[5]={NULL, NULL, NULL, NULL,NULL};
  215. DWORD dwStoreCount=0;
  216. DWORD dwStoreIndex=0;
  217. FILETIME fileTime;
  218. DWORD dwConfidence=0;
  219. DWORD dwError=0;
  220. BYTE *pbHash=NULL;
  221. DWORD cbHash = 0;
  222. CRYPT_HASH_BLOB Blob;
  223. //open a spc cert store
  224. dwStoreCount=sizeof(rgwszStoreName)/sizeof(rgwszStoreName[0]);
  225. GetSystemTimeAsFileTime(&fileTime);
  226. //open the spc store
  227. if (NULL == (hSpcStore = CertOpenStore(
  228. CERT_STORE_PROV_SYSTEM_W,
  229. dwCertEncodingType,
  230. hCryptProv,
  231. CERT_STORE_NO_CRYPT_RELEASE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,
  232. L"SPC"
  233. )))
  234. {
  235. hr=SignError();
  236. goto CLEANUP;
  237. }
  238. //open SPC, my, CA, root store
  239. for(dwStoreIndex=0; dwStoreIndex<dwStoreCount; dwStoreIndex++)
  240. {
  241. //open the store
  242. dwStoreOpenFlag= CERT_STORE_NO_CRYPT_RELEASE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER;
  243. if (NULL == (rghStore[dwStoreIndex] = CertOpenStore(
  244. CERT_STORE_PROV_SYSTEM_W,
  245. dwCertEncodingType,
  246. hCryptProv,
  247. dwStoreOpenFlag,
  248. rgwszStoreName[dwStoreIndex]
  249. )))
  250. {
  251. hr=SignError();
  252. goto CLEANUP;
  253. }
  254. }
  255. //copy all the certs in hOptionalStore if present
  256. if(hOptionalStore)
  257. {
  258. rghStore[dwStoreCount]=hOptionalStore;
  259. dwStoreCount++;
  260. }
  261. //now, build the chain
  262. pSubCertContext=CertDuplicateCertificateContext(pSigningCert);
  263. //loop until break
  264. while(1==1)
  265. {
  266. //find the issuer of the certificate
  267. if(!(pIssuerCertContext=TrustFindIssuerCertificate(
  268. pSubCertContext,
  269. dwCertEncodingType,
  270. dwStoreCount,
  271. rghStore,
  272. &fileTime,
  273. &dwConfidence,
  274. &dwError,
  275. 0)))
  276. {
  277. //fail if we can not find one
  278. hr=CERT_E_CHAINING;
  279. goto CLEANUP;
  280. }
  281. //now, make sure the confidence level is hign enough
  282. if(dwConfidence < (CERT_CONFIDENCE_SIG+CERT_CONFIDENCE_TIME+CERT_CONFIDENCE_TIMENEST))
  283. {
  284. hr=CERT_E_CHAINING;
  285. goto CLEANUP;
  286. }
  287. //check to see if the cert is the root cert
  288. if(TrustIsCertificateSelfSigned(pIssuerCertContext,
  289. pIssuerCertContext->dwCertEncodingType,
  290. 0))
  291. {
  292. if(dwCertPolicy & SIGNER_CERT_POLICY_CHAIN_NO_ROOT)
  293. break;
  294. else
  295. {
  296. //add the root and we are done
  297. if(!CertAddCertificateContextToStore(hStore,pIssuerCertContext,
  298. CERT_STORE_ADD_USE_EXISTING, NULL))
  299. {
  300. hr=CERT_E_CHAINING;
  301. goto CLEANUP;
  302. }
  303. break;
  304. }
  305. }
  306. else
  307. {
  308. //add the certificate context to the store
  309. if(!CertAddCertificateContextToStore(hStore,pIssuerCertContext,
  310. CERT_STORE_ADD_USE_EXISTING, NULL ))
  311. {
  312. hr=CERT_E_CHAINING;
  313. goto CLEANUP;
  314. }
  315. }
  316. //check if the certificate is from the spc store
  317. if(dwCertPolicy & SIGNER_CERT_POLICY_SPC)
  318. {
  319. //get the SHA1 hash of the certificate
  320. if(!CertGetCertificateContextProperty(
  321. pIssuerCertContext,
  322. CERT_SHA1_HASH_PROP_ID,
  323. NULL,
  324. &cbHash
  325. ))
  326. {
  327. hr=SignError();
  328. goto CLEANUP;
  329. }
  330. pbHash=(BYTE *)malloc(cbHash);
  331. if(!pbHash)
  332. {
  333. hr=E_OUTOFMEMORY;
  334. goto CLEANUP;
  335. }
  336. if(!CertGetCertificateContextProperty(
  337. pIssuerCertContext,
  338. CERT_SHA1_HASH_PROP_ID,
  339. pbHash,
  340. &cbHash
  341. ))
  342. {
  343. hr=SignError();
  344. goto CLEANUP;
  345. }
  346. //find the ceritificate in the store
  347. Blob.cbData=cbHash;
  348. Blob.pbData=pbHash;
  349. pFindCertContext=CertFindCertificateInStore(
  350. hSpcStore,
  351. dwCertEncodingType,
  352. 0,
  353. CERT_FIND_SHA1_HASH,
  354. &Blob,
  355. NULL);
  356. //if the certificate is from the SPC store, we are done
  357. if(pFindCertContext)
  358. break;
  359. }
  360. //free the subject context
  361. if(pSubCertContext)
  362. CertFreeCertificateContext(pSubCertContext);
  363. pSubCertContext=pIssuerCertContext;
  364. pIssuerCertContext=NULL;
  365. }
  366. hr=S_OK;
  367. CLEANUP:
  368. if(pIssuerCertContext)
  369. CertFreeCertificateContext(pIssuerCertContext);
  370. if(pSubCertContext)
  371. CertFreeCertificateContext(pSubCertContext);
  372. if(pFindCertContext)
  373. CertFreeCertificateContext(pFindCertContext);
  374. //close all of the stores
  375. for(dwStoreIndex=0; dwStoreIndex < (hOptionalStore ? dwStoreCount-1 : dwStoreCount);
  376. dwStoreIndex++)
  377. {
  378. if(rghStore[dwStoreIndex])
  379. CertCloseStore(rghStore[dwStoreIndex], 0);
  380. }
  381. if(hSpcStore)
  382. CertCloseStore(hSpcStore,0);
  383. if(pbHash)
  384. free(pbHash);
  385. return hr;
  386. } */
  387. //+-------------------------------------------------------------------------
  388. // Build the SPC certificate store from the SPC file and the certificate chain
  389. //--------------------------------------------------------------------------
  390. HRESULT BuildStoreFromSpcChain(HCRYPTPROV hPvkProv,
  391. DWORD dwKeySpec,
  392. HCRYPTPROV hCryptProv,
  393. DWORD dwCertEncodingType,
  394. SIGNER_SPC_CHAIN_INFO *pSpcChainInfo,
  395. HCERTSTORE *phSpcStore,
  396. PCCERT_CONTEXT *ppSignCert
  397. )
  398. {
  399. HCERTSTORE hMemoryStore=NULL;
  400. HRESULT hr=S_OK;
  401. PCCERT_CONTEXT pCertContext=NULL;
  402. PCCERT_CONTEXT pPreContext=NULL;
  403. if(!pSpcChainInfo || !phSpcStore || !ppSignCert)
  404. return E_INVALIDARG;
  405. //init
  406. *phSpcStore=NULL;
  407. //open a memory store
  408. if (NULL == (hMemoryStore = CertOpenStore(
  409. CERT_STORE_PROV_FILENAME_W,
  410. dwCertEncodingType,
  411. hCryptProv,
  412. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  413. pSpcChainInfo->pwszSpcFile)))
  414. {
  415. hr=SignError();
  416. goto CLEANUP;
  417. }
  418. //get the signing certificate
  419. if(S_OK != SpcGetCertFromKey(
  420. dwCertEncodingType,
  421. hMemoryStore,
  422. hPvkProv,
  423. dwKeySpec,
  424. ppSignCert))
  425. {
  426. hr=CRYPT_E_NO_MATCH;
  427. goto CLEANUP;
  428. }
  429. //add all the certs in optional certStore
  430. if(pSpcChainInfo->dwCertPolicy & SIGNER_CERT_POLICY_STORE)
  431. {
  432. if(!(pSpcChainInfo->hCertStore))
  433. {
  434. hr=CERT_E_CHAINING;
  435. goto CLEANUP;
  436. }
  437. //enumerate all the certs in store and add them
  438. while(pCertContext=CertEnumCertificatesInStore(pSpcChainInfo->hCertStore,
  439. pPreContext))
  440. {
  441. if(!CertAddCertificateContextToStore(hMemoryStore, pCertContext,
  442. CERT_STORE_ADD_USE_EXISTING,
  443. NULL))
  444. {
  445. hr=SignError();
  446. goto CLEANUP;
  447. }
  448. pPreContext=pCertContext;
  449. }
  450. hr=S_OK;
  451. }
  452. //see if the certs if self-signed
  453. /* if(TrustIsCertificateSelfSigned(*ppSignCert,
  454. (*ppSignCert)->dwCertEncodingType,
  455. 0))
  456. {
  457. //no need to build the certificate chain anymore
  458. hr=S_OK;
  459. goto CLEANUP;
  460. } */
  461. //build up the cert chain as requested
  462. if(pSpcChainInfo->dwCertPolicy & SIGNER_CERT_POLICY_CHAIN ||
  463. pSpcChainInfo->dwCertPolicy & SIGNER_CERT_POLICY_CHAIN_NO_ROOT ||
  464. pSpcChainInfo->dwCertPolicy & SIGNER_CERT_POLICY_SPC
  465. )
  466. {
  467. //include everthing in the chain
  468. hr=BuildCertChain(hCryptProv, dwCertEncodingType,
  469. hMemoryStore, hMemoryStore,
  470. *ppSignCert, pSpcChainInfo->dwCertPolicy);
  471. }
  472. CLEANUP:
  473. if(pCertContext)
  474. CertFreeCertificateContext(pCertContext);
  475. if(hr==S_OK)
  476. {
  477. *phSpcStore=hMemoryStore;
  478. }
  479. else
  480. {
  481. if(hMemoryStore)
  482. CertCloseStore(hMemoryStore, 0);
  483. if(*ppSignCert)
  484. {
  485. CertFreeCertificateContext(*ppSignCert);
  486. *ppSignCert=NULL;
  487. }
  488. }
  489. return hr;
  490. }
  491. //+-------------------------------------------------------------------------
  492. // Build the spc certificate store from cert chain
  493. //--------------------------------------------------------------------------
  494. HRESULT BuildStoreFromStore(HCRYPTPROV hPvkProv,
  495. DWORD dwKeySpec,
  496. HCRYPTPROV hCryptProv,
  497. DWORD dwCertEncodingType,
  498. SIGNER_CERT_STORE_INFO *pCertStoreInfo,
  499. HCERTSTORE *phSpcStore,
  500. PCCERT_CONTEXT *ppSignCert
  501. )
  502. {
  503. HCERTSTORE hMemoryStore=NULL;
  504. HRESULT hr=S_OK;
  505. PCCERT_CONTEXT pCertContext=NULL;
  506. PCCERT_CONTEXT pPreContext=NULL;
  507. if(!pCertStoreInfo || !phSpcStore || !ppSignCert)
  508. return E_INVALIDARG;
  509. //init
  510. *phSpcStore=NULL;
  511. //open a memory store
  512. if (NULL == (hMemoryStore = CertOpenStore(
  513. CERT_STORE_PROV_MEMORY,
  514. dwCertEncodingType,
  515. hCryptProv,
  516. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  517. NULL
  518. )))
  519. {
  520. hr=SignError();
  521. goto CLEANUP;
  522. }
  523. //add the signing cert to the store
  524. if(!CertAddCertificateContextToStore(hMemoryStore,
  525. pCertStoreInfo->pSigningCert,
  526. CERT_STORE_ADD_USE_EXISTING ,
  527. NULL))
  528. {
  529. hr=SignError();
  530. goto CLEANUP;
  531. }
  532. //get the signing certificate based on the private key
  533. if(S_OK != SpcGetCertFromKey(
  534. dwCertEncodingType,
  535. hMemoryStore,
  536. hPvkProv,
  537. dwKeySpec,
  538. ppSignCert))
  539. {
  540. hr=CRYPT_E_NO_MATCH;
  541. goto CLEANUP;
  542. }
  543. //add all the certs in optional certStore
  544. if(pCertStoreInfo->dwCertPolicy & SIGNER_CERT_POLICY_STORE)
  545. {
  546. if(!(pCertStoreInfo->hCertStore))
  547. {
  548. hr=CERT_E_CHAINING;
  549. goto CLEANUP;
  550. }
  551. //enumerate all the certs in store and add them
  552. while(pCertContext=CertEnumCertificatesInStore(pCertStoreInfo->hCertStore,
  553. pPreContext))
  554. {
  555. if(!CertAddCertificateContextToStore(hMemoryStore, pCertContext,
  556. CERT_STORE_ADD_USE_EXISTING,
  557. NULL))
  558. {
  559. hr=SignError();
  560. goto CLEANUP;
  561. }
  562. pPreContext=pCertContext;
  563. }
  564. hr=S_OK;
  565. }
  566. //see if the certs if self-signed
  567. /* if(TrustIsCertificateSelfSigned(pCertStoreInfo->pSigningCert,
  568. pCertStoreInfo->pSigningCert->dwCertEncodingType,
  569. 0))
  570. {
  571. //no need to build the certificate chain anymore
  572. *ppSignCert=CertDuplicateCertificateContext(pCertStoreInfo->pSigningCert);
  573. hr=S_OK;
  574. goto CLEANUP;
  575. }*/
  576. //build up the cert chain as requested
  577. if(pCertStoreInfo->dwCertPolicy & SIGNER_CERT_POLICY_CHAIN ||
  578. pCertStoreInfo->dwCertPolicy & SIGNER_CERT_POLICY_CHAIN_NO_ROOT ||
  579. pCertStoreInfo->dwCertPolicy & SIGNER_CERT_POLICY_SPC
  580. )
  581. {
  582. //include everthing in the chain
  583. hr=BuildCertChain(hCryptProv, dwCertEncodingType,
  584. hMemoryStore, NULL,
  585. pCertStoreInfo->pSigningCert, pCertStoreInfo->dwCertPolicy);
  586. }
  587. if(S_OK != hr)
  588. goto CLEANUP;
  589. hr=S_OK;
  590. CLEANUP:
  591. if(pCertContext)
  592. CertFreeCertificateContext(pCertContext);
  593. if(hr==S_OK)
  594. {
  595. *phSpcStore=hMemoryStore;
  596. }
  597. else
  598. {
  599. if(hMemoryStore)
  600. CertCloseStore(hMemoryStore, 0);
  601. if(*ppSignCert)
  602. {
  603. CertFreeCertificateContext(*ppSignCert);
  604. *ppSignCert=NULL;
  605. }
  606. }
  607. return hr;
  608. }
  609. //+-------------------------------------------------------------------------
  610. // Build the spc certificate store from a spc file
  611. //--------------------------------------------------------------------------
  612. HRESULT BuildStoreFromSpcFile(HCRYPTPROV hPvkProv,
  613. DWORD dwKeySpec,
  614. HCRYPTPROV hCryptProv,
  615. DWORD dwCertEncodingType,
  616. LPCWSTR pwszSpcFile,
  617. HCERTSTORE *phSpcStore,
  618. PCCERT_CONTEXT *ppSignCert)
  619. {
  620. if(!phSpcStore || !pwszSpcFile || !ppSignCert)
  621. return E_INVALIDARG;
  622. *phSpcStore=NULL;
  623. // Open up the spc store
  624. *phSpcStore= CertOpenStore(CERT_STORE_PROV_FILENAME_W,
  625. dwCertEncodingType,
  626. hCryptProv,
  627. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  628. pwszSpcFile);
  629. if(!(*phSpcStore))
  630. return SignError();
  631. //get the signing certificate
  632. if(S_OK != SpcGetCertFromKey(dwCertEncodingType,
  633. *phSpcStore,
  634. hPvkProv,
  635. dwKeySpec,
  636. ppSignCert))
  637. {
  638. CertCloseStore(*phSpcStore, 0);
  639. *phSpcStore=NULL;
  640. return CRYPT_E_NO_MATCH;
  641. }
  642. return S_OK;
  643. }
  644. //+-------------------------------------------------------------------------
  645. // Build the spc certificate store from either a spc file or the
  646. // cert chain
  647. //--------------------------------------------------------------------------
  648. HRESULT BuildCertStore(HCRYPTPROV hPvkProv,
  649. DWORD dwKeySpec,
  650. HCRYPTPROV hCryptProv,
  651. DWORD dwCertEncodingType,
  652. SIGNER_CERT *pSignerCert,
  653. HCERTSTORE *phSpcStore,
  654. PCCERT_CONTEXT *ppSigningCert)
  655. {
  656. HRESULT hr;
  657. if(!pSignerCert || !phSpcStore || !ppSigningCert)
  658. return E_INVALIDARG;
  659. //init
  660. *phSpcStore=NULL;
  661. if(pSignerCert->dwCertChoice==SIGNER_CERT_SPC_FILE)
  662. {
  663. hr=BuildStoreFromSpcFile(hPvkProv,
  664. dwKeySpec,
  665. hCryptProv,
  666. dwCertEncodingType,
  667. pSignerCert->pwszSpcFile,
  668. phSpcStore,
  669. ppSigningCert);
  670. }
  671. else
  672. {
  673. if(pSignerCert->dwCertChoice==SIGNER_CERT_STORE)
  674. {
  675. hr=BuildStoreFromStore(hPvkProv,
  676. dwKeySpec,
  677. hCryptProv,
  678. dwCertEncodingType,
  679. (pSignerCert->pCertStoreInfo),
  680. phSpcStore,
  681. ppSigningCert);
  682. }
  683. else
  684. hr=BuildStoreFromSpcChain(hPvkProv,
  685. dwKeySpec,
  686. hCryptProv,
  687. dwCertEncodingType,
  688. (pSignerCert->pSpcChainInfo),
  689. phSpcStore,
  690. ppSigningCert);
  691. }
  692. #if (0) //DSIE: Bug 284639, the fix is to also preserve 0x80070002 since we
  693. // really don't know what the impact will be for existing apps,
  694. // if we preserve all error codes.
  695. if(hr!=S_OK && hr!=CRYPT_E_NO_MATCH)
  696. hr=CERT_E_CHAINING;
  697. #else
  698. if(hr!=S_OK && hr!=CRYPT_E_NO_MATCH && hr!=0x80070002)
  699. hr=CERT_E_CHAINING;
  700. #endif
  701. return hr;
  702. }
  703. //-----------------------------------------------------------------------------
  704. //
  705. // Parse the private key information from a pCertContext's property
  706. // CERT_PVK_FILE_PROP_ID
  707. //
  708. //----------------------------------------------------------------------------
  709. BOOL GetProviderInfoFromCert(PCCERT_CONTEXT pCertContext,
  710. CRYPT_KEY_PROV_INFO *pKeyProvInfo)
  711. {
  712. BOOL fResult=FALSE;
  713. BYTE *pbData=NULL;
  714. BYTE *pbToFree=NULL;
  715. DWORD cbData=0;
  716. //init
  717. if(!pCertContext || !pKeyProvInfo)
  718. return FALSE;
  719. memset(pKeyProvInfo, 0, sizeof(CRYPT_KEY_PROV_INFO));
  720. //get the property
  721. if(!CertGetCertificateContextProperty(pCertContext,
  722. CERT_PVK_FILE_PROP_ID,
  723. NULL,
  724. &cbData))
  725. return FALSE;
  726. pbData=(BYTE *)malloc(cbData);
  727. if(!pbData)
  728. return FALSE;
  729. if(!CertGetCertificateContextProperty(pCertContext,
  730. CERT_PVK_FILE_PROP_ID,
  731. pbData,
  732. &cbData))
  733. goto CLEANUP;
  734. //get the information from the property
  735. pbToFree=pbData;
  736. //get the private key information
  737. cbData=sizeof(WCHAR)*(wcslen((LPWSTR)pbData)+1);
  738. pKeyProvInfo->pwszContainerName=(LPWSTR)malloc(cbData);
  739. if(!(pKeyProvInfo->pwszContainerName))
  740. goto CLEANUP;
  741. wcscpy(pKeyProvInfo->pwszContainerName,(LPWSTR)pbData);
  742. //get the key spec
  743. pbData = pbData + cbData;
  744. cbData=sizeof(WCHAR)*(wcslen((LPWSTR)pbData)+1);
  745. pKeyProvInfo->dwKeySpec=_wtol((LPWSTR)pbData);
  746. //get the provider type
  747. pbData = pbData + cbData;
  748. cbData=sizeof(WCHAR)*(wcslen((LPWSTR)pbData)+1);
  749. pKeyProvInfo->dwProvType=_wtol((LPWSTR)pbData);
  750. //get the provider name
  751. pbData = pbData + cbData;
  752. if(*((LPWSTR)pbData)!=L'\0')
  753. {
  754. cbData=sizeof(WCHAR)*(wcslen((LPWSTR)pbData)+1);
  755. pKeyProvInfo->pwszProvName=(LPWSTR)malloc(cbData);
  756. if(NULL == pKeyProvInfo->pwszProvName)
  757. goto CLEANUP;
  758. wcscpy(pKeyProvInfo->pwszProvName, (LPWSTR)pbData);
  759. }
  760. fResult=TRUE;
  761. CLEANUP:
  762. if(pbToFree)
  763. free(pbToFree);
  764. if(FALSE==fResult)
  765. {
  766. if(pKeyProvInfo->pwszContainerName)
  767. free( pKeyProvInfo->pwszContainerName);
  768. if(pKeyProvInfo->pwszProvName)
  769. free( pKeyProvInfo->pwszProvName);
  770. //memset the output to 0
  771. memset(pKeyProvInfo, 0, sizeof(CRYPT_KEY_PROV_INFO));
  772. }
  773. return fResult;
  774. }
  775. //+-------------------------------------------------------------------------
  776. // Get hCryptProv handle and key spec for the certificate
  777. //--------------------------------------------------------------------------
  778. BOOL WINAPI GetCryptProvFromCert(
  779. HWND hwnd,
  780. PCCERT_CONTEXT pCert,
  781. HCRYPTPROV *phCryptProv,
  782. DWORD *pdwKeySpec,
  783. BOOL *pfDidCryptAcquire,
  784. LPWSTR *ppwszTmpContainer,
  785. LPWSTR *ppwszProviderName,
  786. DWORD *pdwProviderType
  787. )
  788. {
  789. BOOL fResult=FALSE;
  790. WCHAR wszPublisher[45];
  791. CRYPT_KEY_PROV_INFO keyProvInfo;
  792. HRESULT hr;
  793. memset(&keyProvInfo, 0, sizeof(CRYPT_KEY_PROV_INFO));
  794. *ppwszTmpContainer=NULL;
  795. *phCryptProv=NULL;
  796. *pfDidCryptAcquire=FALSE;
  797. *ppwszProviderName=NULL;
  798. *pdwKeySpec=0;
  799. //first, try to get from the key container
  800. if(CryptProvFromCert(hwnd, pCert, phCryptProv,
  801. pdwKeySpec, pfDidCryptAcquire))
  802. return TRUE;
  803. //load from the resource of string L"publisher"
  804. if(0==LoadStringU(hInstance, IDS_Publisher, wszPublisher, 40))
  805. goto CLEANUP;
  806. //Get provider information from the property
  807. if(!GetProviderInfoFromCert(pCert, &keyProvInfo))
  808. {
  809. SetLastError((DWORD) CRYPT_E_NO_KEY_PROPERTY);
  810. goto CLEANUP;
  811. }
  812. //acquire context based on the private key file. A temporary
  813. //key container will be created, along with information
  814. //about the provider name and provider type, which are needed
  815. //to destroy the key container
  816. if(S_OK!=(hr=PvkGetCryptProv( hwnd,
  817. wszPublisher,
  818. keyProvInfo.pwszProvName,
  819. keyProvInfo.dwProvType,
  820. keyProvInfo.pwszContainerName,
  821. NULL,
  822. &(keyProvInfo.dwKeySpec),
  823. ppwszTmpContainer,
  824. phCryptProv)))
  825. {
  826. *phCryptProv=NULL;
  827. *ppwszTmpContainer=NULL;
  828. SetLastError((DWORD)hr);
  829. goto CLEANUP;
  830. }
  831. //copy the provder name
  832. if(keyProvInfo.pwszProvName)
  833. {
  834. *ppwszProviderName=(LPWSTR)malloc(
  835. sizeof(WCHAR)*(wcslen(keyProvInfo.pwszProvName)+1));
  836. if((*ppwszProviderName)==NULL)
  837. {
  838. SetLastError(E_OUTOFMEMORY);
  839. //free the hCrytProv
  840. PvkPrivateKeyReleaseContext(
  841. *phCryptProv,
  842. keyProvInfo.pwszProvName,
  843. keyProvInfo.dwProvType,
  844. *ppwszTmpContainer);
  845. *phCryptProv=NULL;
  846. *ppwszTmpContainer=NULL;
  847. goto CLEANUP;
  848. }
  849. wcscpy(*ppwszProviderName, keyProvInfo.pwszProvName);
  850. }
  851. //copy the provider type
  852. *pdwProviderType=keyProvInfo.dwProvType;
  853. //copy the key spec
  854. *pdwKeySpec=keyProvInfo.dwKeySpec;
  855. *pfDidCryptAcquire=TRUE;
  856. fResult=TRUE;
  857. CLEANUP:
  858. if(keyProvInfo.pwszProvName)
  859. free(keyProvInfo.pwszProvName);
  860. if(keyProvInfo.pwszContainerName)
  861. free(keyProvInfo.pwszContainerName);
  862. return fResult;
  863. }
  864. //+-------------------------------------------------------------------------
  865. // Free hCryptProv handle and key spec for the certificate
  866. //--------------------------------------------------------------------------
  867. void WINAPI FreeCryptProvFromCert(BOOL fAcquired,
  868. HCRYPTPROV hProv,
  869. LPWSTR pwszCapiProvider,
  870. DWORD dwProviderType,
  871. LPWSTR pwszTmpContainer)
  872. {
  873. if(fAcquired)
  874. {
  875. if (pwszTmpContainer)
  876. {
  877. // Delete the temporary container for the private key from
  878. // the provider
  879. PvkPrivateKeyReleaseContext(hProv,
  880. pwszCapiProvider,
  881. dwProviderType,
  882. pwszTmpContainer);
  883. if(pwszCapiProvider)
  884. free(pwszCapiProvider);
  885. }
  886. else
  887. {
  888. if (hProv)
  889. CryptReleaseContext(hProv, 0);
  890. }
  891. }
  892. }
  893. //+-------------------------------------------------------------------------
  894. //
  895. //This is a subst of GetCryptProvFromCert. This function does not consider
  896. //the private key file property of the certificate
  897. //+-------------------------------------------------------------------------
  898. BOOL WINAPI CryptProvFromCert(
  899. HWND hwnd,
  900. PCCERT_CONTEXT pCert,
  901. HCRYPTPROV *phCryptProv,
  902. DWORD *pdwKeySpec,
  903. BOOL *pfDidCryptAcquire
  904. )
  905. {
  906. return CryptAcquireCertificatePrivateKey(
  907. pCert,
  908. 0, //we do not do the compare. It will be done later.
  909. NULL,
  910. phCryptProv,
  911. pdwKeySpec,
  912. pfDidCryptAcquire);
  913. /*BOOL fResult;
  914. BOOL fDidCryptAcquire = FALSE;
  915. CERT_KEY_CONTEXT KeyContext;
  916. memset(&KeyContext, 0, sizeof(KeyContext));
  917. PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
  918. DWORD cbData;
  919. DWORD dwIdx;
  920. // Get either the CERT_KEY_CONTEXT_PROP_ID or
  921. // CERT_KEY_PROV_INFO_PROP_ID, or
  922. // CERT_PVK_FILE_PROP_ID for the Cert.
  923. cbData = sizeof(KeyContext);
  924. CertGetCertificateContextProperty(
  925. pCert,
  926. CERT_KEY_CONTEXT_PROP_ID,
  927. &KeyContext,
  928. &cbData
  929. );
  930. if (KeyContext.hCryptProv == 0)
  931. {
  932. cbData = 0;
  933. CertGetCertificateContextProperty(
  934. pCert,
  935. CERT_KEY_PROV_INFO_PROP_ID,
  936. NULL,
  937. &cbData
  938. );
  939. if (cbData == 0)
  940. {
  941. SetLastError((DWORD) CRYPT_E_NO_KEY_PROPERTY);
  942. goto ErrorReturn;
  943. }
  944. else
  945. {
  946. pKeyProvInfo = (PCRYPT_KEY_PROV_INFO) malloc(cbData);
  947. if (pKeyProvInfo == NULL) goto ErrorReturn;
  948. fResult = CertGetCertificateContextProperty(
  949. pCert,
  950. CERT_KEY_PROV_INFO_PROP_ID,
  951. pKeyProvInfo,
  952. &cbData
  953. );
  954. if (!fResult) goto ErrorReturn;
  955. if (PROV_RSA_FULL == pKeyProvInfo->dwProvType &&
  956. (NULL == pKeyProvInfo->pwszProvName ||
  957. L'\0' == *pKeyProvInfo->pwszProvName))
  958. fResult = CryptAcquireContextU(
  959. &KeyContext.hCryptProv,
  960. pKeyProvInfo->pwszContainerName,
  961. MS_ENHANCED_PROV_W,
  962. PROV_RSA_FULL,
  963. pKeyProvInfo->dwFlags & ~CERT_SET_KEY_CONTEXT_PROP_ID
  964. );
  965. else
  966. fResult = FALSE;
  967. if (!fResult)
  968. fResult = CryptAcquireContextU(
  969. &KeyContext.hCryptProv,
  970. pKeyProvInfo->pwszContainerName,
  971. pKeyProvInfo->pwszProvName,
  972. pKeyProvInfo->dwProvType,
  973. pKeyProvInfo->dwFlags & ~CERT_SET_KEY_CONTEXT_PROP_ID
  974. );
  975. if (!fResult) goto ErrorReturn;
  976. fDidCryptAcquire = TRUE;
  977. for (dwIdx = 0; dwIdx < pKeyProvInfo->cProvParam; dwIdx++)
  978. {
  979. PCRYPT_KEY_PROV_PARAM pKeyProvParam = &pKeyProvInfo->rgProvParam[dwIdx];
  980. fResult = CryptSetProvParam(
  981. KeyContext.hCryptProv,
  982. pKeyProvParam->dwParam,
  983. pKeyProvParam->pbData,
  984. pKeyProvParam->dwFlags
  985. );
  986. if (!fResult) goto ErrorReturn;
  987. }
  988. KeyContext.dwKeySpec = pKeyProvInfo->dwKeySpec;
  989. if (pKeyProvInfo->dwFlags & CERT_SET_KEY_CONTEXT_PROP_ID)
  990. {
  991. // Set the certificate's property so we only need to do the
  992. // acquire once
  993. KeyContext.cbSize = sizeof(KeyContext);
  994. fResult = CertSetCertificateContextProperty(
  995. pCert,
  996. CERT_KEY_CONTEXT_PROP_ID,
  997. 0, // dwFlags
  998. (void *) &KeyContext
  999. );
  1000. if (!fResult) goto ErrorReturn;
  1001. fDidCryptAcquire = FALSE;
  1002. }
  1003. }
  1004. }
  1005. fResult = TRUE;
  1006. goto CommonReturn;
  1007. ErrorReturn:
  1008. if (fDidCryptAcquire) {
  1009. DWORD dwErr = GetLastError();
  1010. CryptReleaseContext(KeyContext.hCryptProv, 0);
  1011. SetLastError(dwErr);
  1012. fDidCryptAcquire = FALSE;
  1013. }
  1014. KeyContext.hCryptProv = 0;
  1015. fResult = FALSE;
  1016. CommonReturn:
  1017. if (pKeyProvInfo)
  1018. free(pKeyProvInfo);
  1019. *phCryptProv = KeyContext.hCryptProv;
  1020. *pdwKeySpec = KeyContext.dwKeySpec;
  1021. *pfDidCryptAcquire = fDidCryptAcquire;
  1022. return fResult;*/
  1023. }
  1024. //+-----------------------------------------------------------------------
  1025. // Check the SIGNER_SUBJECT_INFO
  1026. //
  1027. //+-----------------------------------------------------------------------
  1028. BOOL CheckSigncodeSubjectInfo(
  1029. PSIGNER_SUBJECT_INFO pSubjectInfo)
  1030. {
  1031. if(!pSubjectInfo)
  1032. return FALSE;
  1033. //check pSubjectInfo
  1034. if(pSubjectInfo->cbSize < sizeof(SIGNER_SUBJECT_INFO))
  1035. return FALSE;
  1036. if(NULL==(pSubjectInfo->pdwIndex))
  1037. return FALSE;
  1038. //currently, we only allow index of 0
  1039. if(0!= (*(pSubjectInfo->pdwIndex)))
  1040. return FALSE;
  1041. if((pSubjectInfo->dwSubjectChoice!=SIGNER_SUBJECT_FILE)&&
  1042. (pSubjectInfo->dwSubjectChoice!=SIGNER_SUBJECT_BLOB))
  1043. return FALSE;
  1044. if(pSubjectInfo->dwSubjectChoice==SIGNER_SUBJECT_FILE)
  1045. {
  1046. if((pSubjectInfo->pSignerFileInfo)==NULL)
  1047. return FALSE;
  1048. //check SIGNER_FILE_INFO
  1049. if(pSubjectInfo->pSignerFileInfo->cbSize < sizeof(SIGNER_FILE_INFO))
  1050. return FALSE;
  1051. if((pSubjectInfo->pSignerFileInfo->pwszFileName)==NULL)
  1052. return FALSE;
  1053. }
  1054. else
  1055. {
  1056. if((pSubjectInfo->pSignerBlobInfo)==NULL)
  1057. return FALSE;
  1058. //check SIGNER_BLOB_INFO
  1059. if(pSubjectInfo->pSignerBlobInfo->cbSize < sizeof(SIGNER_BLOB_INFO))
  1060. return FALSE;
  1061. if(NULL==(pSubjectInfo->pSignerBlobInfo->pGuidSubject))
  1062. return FALSE;
  1063. if(0==(pSubjectInfo->pSignerBlobInfo->cbBlob))
  1064. return FALSE;
  1065. if(NULL==(pSubjectInfo->pSignerBlobInfo->pbBlob))
  1066. return FALSE;
  1067. }
  1068. return TRUE;
  1069. }
  1070. //+-----------------------------------------------------------------------
  1071. // Check the input parameters of Signcode. Make sure they are valid.
  1072. //
  1073. //+-----------------------------------------------------------------------
  1074. BOOL CheckSigncodeParam(
  1075. PSIGNER_SUBJECT_INFO pSubjectInfo,
  1076. PSIGNER_CERT pSignerCert,
  1077. PSIGNER_SIGNATURE_INFO pSignatureInfo,
  1078. PSIGNER_PROVIDER_INFO pProviderInfo)
  1079. {
  1080. //except for pPvkInfo and pProviderInfo, the rest are required.
  1081. if(!pSubjectInfo ||!pSignerCert || !pSignatureInfo)
  1082. return FALSE;
  1083. //check pSubjectInfo
  1084. if(FALSE==CheckSigncodeSubjectInfo(pSubjectInfo))
  1085. return FALSE;
  1086. //check pSignatureInfo
  1087. if(pSignatureInfo->cbSize < sizeof(SIGNER_SIGNATURE_INFO))
  1088. return FALSE;
  1089. //check the attributes in pSignatureInfo
  1090. if(pSignatureInfo->dwAttrChoice == SIGNER_AUTHCODE_ATTR)
  1091. {
  1092. if((pSignatureInfo->pAttrAuthcode)==NULL)
  1093. return FALSE;
  1094. //check pSignatureInfo->pAttrAuthcode
  1095. if(pSignatureInfo->pAttrAuthcode->cbSize < sizeof(SIGNER_ATTR_AUTHCODE))
  1096. return FALSE;
  1097. }
  1098. else
  1099. {
  1100. if(pSignatureInfo->dwAttrChoice !=SIGNER_NO_ATTR)
  1101. return FALSE;
  1102. }
  1103. //check provider info
  1104. if(pProviderInfo)
  1105. {
  1106. if(pProviderInfo->cbSize < sizeof(SIGNER_PROVIDER_INFO))
  1107. return FALSE;
  1108. //dwPvkType has to be valid
  1109. if((pProviderInfo->dwPvkChoice!=PVK_TYPE_FILE_NAME) &&
  1110. (pProviderInfo->dwPvkChoice!=PVK_TYPE_KEYCONTAINER) )
  1111. return FALSE;
  1112. if(pProviderInfo->dwPvkChoice==PVK_TYPE_FILE_NAME)
  1113. {
  1114. if(!(pProviderInfo->pwszPvkFileName))
  1115. return FALSE;
  1116. }
  1117. else
  1118. {
  1119. if(!(pProviderInfo->pwszKeyContainer))
  1120. return FALSE;
  1121. }
  1122. }
  1123. //check pSignerCert
  1124. if(pSignerCert->cbSize < sizeof(SIGNER_CERT))
  1125. return FALSE;
  1126. //check the dwCertChoice
  1127. if((pSignerCert->dwCertChoice!= SIGNER_CERT_SPC_FILE) &&
  1128. ((pSignerCert->dwCertChoice!= SIGNER_CERT_STORE)) &&
  1129. (pSignerCert->dwCertChoice!= SIGNER_CERT_SPC_CHAIN)
  1130. )
  1131. return FALSE;
  1132. //check the spc file situation
  1133. if(pSignerCert->dwCertChoice == SIGNER_CERT_SPC_FILE)
  1134. {
  1135. if(pSignerCert->pwszSpcFile==NULL)
  1136. return FALSE;
  1137. }
  1138. //check the cert store situation
  1139. if(pSignerCert->dwCertChoice==SIGNER_CERT_STORE)
  1140. {
  1141. //pCertStoreInfo has to be set
  1142. if((pSignerCert->pCertStoreInfo)==NULL)
  1143. return FALSE;
  1144. if((pSignerCert->pCertStoreInfo)->cbSize < sizeof(SIGNER_CERT_STORE_INFO))
  1145. return FALSE;
  1146. //pSigngingCert has to be set
  1147. if((pSignerCert->pCertStoreInfo)->pSigningCert == NULL )
  1148. return FALSE;
  1149. }
  1150. //check the SPC chain situation
  1151. if(pSignerCert->dwCertChoice==SIGNER_CERT_SPC_CHAIN)
  1152. {
  1153. //pCertStoreInfo has to be set
  1154. if((pSignerCert->pSpcChainInfo)==NULL)
  1155. return FALSE;
  1156. if((pSignerCert->pSpcChainInfo)->cbSize != sizeof(SIGNER_SPC_CHAIN_INFO))
  1157. return FALSE;
  1158. //pSigngingCert has to be set
  1159. if((pSignerCert->pSpcChainInfo)->pwszSpcFile == NULL )
  1160. return FALSE;
  1161. }
  1162. //end of the checking
  1163. return TRUE;
  1164. }
  1165. //-------------------------------------------------------------------------
  1166. //
  1167. // GetSubjectTypeFlags:
  1168. // Check the BASIC_CONSTRAINTS extension from the certificate
  1169. // to see if the certificate is a CA or end entity certs
  1170. //
  1171. //-------------------------------------------------------------------------
  1172. static DWORD GetSubjectTypeFlags(IN DWORD dwCertEncodingType,
  1173. IN PCCERT_CONTEXT pCert)
  1174. {
  1175. HRESULT hr = S_OK;
  1176. DWORD grfSubjectType = 0;
  1177. PCERT_EXTENSION pExt;
  1178. PCERT_BASIC_CONSTRAINTS_INFO pInfo = NULL;
  1179. DWORD cbInfo;
  1180. PKITRY {
  1181. if ((pExt = CertFindExtension(szOID_BASIC_CONSTRAINTS,
  1182. pCert->pCertInfo->cExtension,
  1183. pCert->pCertInfo->rgExtension)) == NULL)
  1184. PKITHROW(CRYPT_E_NO_MATCH);
  1185. cbInfo = 0;
  1186. CryptDecodeObject(dwCertEncodingType,
  1187. X509_BASIC_CONSTRAINTS,
  1188. pExt->Value.pbData,
  1189. pExt->Value.cbData,
  1190. 0, // dwFlags
  1191. NULL, // pInfo
  1192. &cbInfo);
  1193. if (cbInfo == 0)
  1194. PKITHROW(CRYPT_E_NO_MATCH);
  1195. pInfo = (PCERT_BASIC_CONSTRAINTS_INFO) malloc(cbInfo);
  1196. if(!pInfo)
  1197. PKITHROW(E_OUTOFMEMORY);
  1198. if (!CryptDecodeObject(dwCertEncodingType,
  1199. X509_BASIC_CONSTRAINTS,
  1200. pExt->Value.pbData,
  1201. pExt->Value.cbData,
  1202. 0, // dwFlags
  1203. pInfo,
  1204. &cbInfo))
  1205. PKITHROW(SignError());
  1206. if (pInfo->SubjectType.cbData > 0) {
  1207. BYTE bSubjectType = *pInfo->SubjectType.pbData;
  1208. if (bSubjectType & CERT_END_ENTITY_SUBJECT_FLAG)
  1209. grfSubjectType |= SIGNER_CERT_END_ENTITY_FLAG;
  1210. if (0 == (bSubjectType & CERT_CA_SUBJECT_FLAG))
  1211. grfSubjectType |= SIGNER_CERT_NOT_CA_FLAG;
  1212. }
  1213. }
  1214. PKICATCH(err) {
  1215. hr = err.pkiError;
  1216. } PKIEND;
  1217. if (pInfo) free(pInfo);
  1218. return grfSubjectType;
  1219. }
  1220. //-------------------------------------------------------------------------
  1221. //
  1222. // WSZtoSZ:
  1223. // Convert a wchar string to a multi-byte string.
  1224. //
  1225. //-------------------------------------------------------------------------
  1226. HRESULT WSZtoSZ(LPWSTR wsz, LPSTR *psz)
  1227. {
  1228. DWORD cbSize=0;
  1229. *psz=NULL;
  1230. if(!wsz)
  1231. return S_OK;
  1232. cbSize=WideCharToMultiByte(0,0,wsz,-1,
  1233. NULL,0,0,0);
  1234. if(cbSize==0)
  1235. return SignError();
  1236. *psz=(LPSTR)malloc(cbSize);
  1237. if(*psz==NULL)
  1238. return E_OUTOFMEMORY;
  1239. if(WideCharToMultiByte(0,0,wsz,-1,
  1240. *psz,cbSize,0,0))
  1241. {
  1242. return S_OK;
  1243. }
  1244. else
  1245. {
  1246. free(*psz);
  1247. return SignError();
  1248. }
  1249. }
  1250. //-------------------------------------------------------------------------
  1251. //
  1252. // BytesToBase64:
  1253. // convert bytes to base64 bstr
  1254. //
  1255. //-------------------------------------------------------------------------
  1256. HRESULT BytesToBase64(BYTE *pb, DWORD cb, CHAR **pszEncode, DWORD *pdwEncode)
  1257. {
  1258. DWORD dwErr;
  1259. DWORD cch;
  1260. CHAR *psz=NULL;
  1261. *pszEncode=NULL;
  1262. *pdwEncode=0;
  1263. if (cb == 0) {
  1264. return S_OK;
  1265. }
  1266. cch = 0;
  1267. if (!CryptBinaryToStringA(
  1268. pb,
  1269. cb,
  1270. CRYPT_STRING_BASE64,
  1271. NULL,
  1272. &cch
  1273. ))
  1274. return HRESULT_FROM_WIN32(GetLastError());
  1275. if (NULL == (psz=(CHAR *)malloc(cch * sizeof(char))))
  1276. return E_OUTOFMEMORY;
  1277. if (!CryptBinaryToStringA(
  1278. pb,
  1279. cb,
  1280. CRYPT_STRING_BASE64,
  1281. psz,
  1282. &cch
  1283. )) {
  1284. free(psz);
  1285. return HRESULT_FROM_WIN32(GetLastError());
  1286. } else {
  1287. *pszEncode=psz;
  1288. *pdwEncode=cch + 1; //plus 1 to include NULL
  1289. return S_OK;
  1290. }
  1291. }
  1292. //-------------------------------------------------------------------------
  1293. //
  1294. // BytesToBase64:
  1295. // conver base64 bstr to bytes
  1296. //
  1297. //-------------------------------------------------------------------------
  1298. HRESULT Base64ToBytes(CHAR *pEncode, DWORD cbEncode, BYTE **ppb, DWORD *pcb)
  1299. {
  1300. DWORD dwErr;
  1301. BYTE *pb;
  1302. DWORD cb;
  1303. *ppb = NULL;
  1304. *pcb = 0;
  1305. cb = 0;
  1306. if (!CryptStringToBinaryA(
  1307. pEncode,
  1308. cbEncode,
  1309. CRYPT_STRING_ANY,
  1310. NULL,
  1311. &cb,
  1312. NULL,
  1313. NULL))
  1314. return HRESULT_FROM_WIN32(GetLastError());
  1315. if (cb == 0)
  1316. return S_OK;
  1317. if (NULL == (pb = (BYTE *) malloc(cb)))
  1318. return E_OUTOFMEMORY;
  1319. if (!CryptStringToBinaryA(
  1320. pEncode,
  1321. cbEncode,
  1322. CRYPT_STRING_ANY,
  1323. pb,
  1324. &cb,
  1325. NULL,
  1326. NULL
  1327. )) {
  1328. free(pb);
  1329. return HRESULT_FROM_WIN32(GetLastError());
  1330. } else {
  1331. *ppb = pb;
  1332. *pcb = cb;
  1333. return S_OK;
  1334. }
  1335. }
  1336. //+-------------------------------------------------------------------------
  1337. // Find the the cert from the hprov
  1338. // Parameter Returns:
  1339. // pReturnCert - context of the cert found (must pass in cert context);
  1340. // Returns:
  1341. // S_OK - everything worked
  1342. // E_OUTOFMEMORY - memory failure
  1343. // E_INVALIDARG - no pReturnCert supplied
  1344. // CRYPT_E_NO_MATCH - could not locate certificate in store
  1345. //
  1346. //+-------------------------------------------------------------------------
  1347. HRESULT
  1348. SpcGetCertFromKey(IN DWORD dwCertEncodingType,
  1349. IN HCERTSTORE hStore,
  1350. IN HCRYPTPROV hProv,
  1351. IN DWORD dwKeySpec,
  1352. OUT PCCERT_CONTEXT* pReturnCert)
  1353. {
  1354. PCERT_PUBLIC_KEY_INFO psPubKeyInfo = NULL;
  1355. DWORD dwPubKeyInfo;
  1356. PCCERT_CONTEXT pCert = NULL;
  1357. PCCERT_CONTEXT pEnumCert = NULL;
  1358. DWORD grfCert = 0;
  1359. HRESULT hr = S_OK;
  1360. PKITRY {
  1361. if(!pReturnCert) PKITHROW(E_INVALIDARG);
  1362. // Get public key to compare certificates with
  1363. dwPubKeyInfo = 0;
  1364. CryptExportPublicKeyInfo(hProv,
  1365. dwKeySpec,
  1366. dwCertEncodingType,
  1367. NULL, // psPubKeyInfo
  1368. &dwPubKeyInfo);
  1369. if (dwPubKeyInfo == 0)
  1370. PKITHROW(SignError());
  1371. psPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) malloc(dwPubKeyInfo);
  1372. if(!psPubKeyInfo) PKITHROW(E_OUTOFMEMORY);
  1373. if (!CryptExportPublicKeyInfo(hProv,
  1374. dwKeySpec,
  1375. dwCertEncodingType,
  1376. psPubKeyInfo,
  1377. &dwPubKeyInfo))
  1378. PKITHROW(SignError());
  1379. // Find the "strongest" cert with a matching public key
  1380. while (TRUE) {
  1381. pEnumCert = CertEnumCertificatesInStore(hStore, pEnumCert);
  1382. if (pEnumCert) {
  1383. if (CertComparePublicKeyInfo(pEnumCert->dwCertEncodingType,
  1384. &pEnumCert->pCertInfo->SubjectPublicKeyInfo,
  1385. psPubKeyInfo)) {
  1386. // END_ENTITY, NOT_CA
  1387. DWORD grfEnumCert = GetSubjectTypeFlags(pEnumCert->dwCertEncodingType,
  1388. pEnumCert);
  1389. if (S_OK != SignIsGlueCert(pEnumCert))
  1390. grfEnumCert |= SIGNER_CERT_NOT_GLUE_FLAG;
  1391. if (!CertCompareCertificateName(pEnumCert->dwCertEncodingType,
  1392. &pEnumCert->pCertInfo->Issuer,
  1393. &pEnumCert->pCertInfo->Subject))
  1394. grfEnumCert |= SIGNER_CERT_NOT_SELF_SIGNED_FLAG;
  1395. if (grfEnumCert >= grfCert) {
  1396. // Found a signer cert with a stronger match
  1397. if (pCert)
  1398. CertFreeCertificateContext(pCert);
  1399. grfCert = grfEnumCert;
  1400. if (grfCert == SIGNER_CERT_ALL_FLAGS) {
  1401. pCert = pEnumCert;
  1402. break;
  1403. } else
  1404. // Not a perfect match. Check for a better signer cert.
  1405. pCert = CertDuplicateCertificateContext(pEnumCert);
  1406. }
  1407. }
  1408. } else
  1409. break;
  1410. }
  1411. if (pCert == NULL)
  1412. PKITHROW(CRYPT_E_NO_MATCH);
  1413. if (!CertSetCertificateContextProperty(pCert,
  1414. CERT_KEY_PROV_HANDLE_PROP_ID,
  1415. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  1416. (void *) hProv))
  1417. PKITHROW(SignError());
  1418. }
  1419. PKICATCH(err) {
  1420. hr = err.pkiError;
  1421. if (pCert) {
  1422. CertFreeCertificateContext(pCert);
  1423. pCert = NULL;
  1424. }
  1425. } PKIEND;
  1426. *pReturnCert = pCert;
  1427. if (psPubKeyInfo)
  1428. free(psPubKeyInfo);
  1429. return hr;
  1430. }
  1431. ///-------------------------------------------------------------------------
  1432. // Authenticode routines (not necessary for all implementations)
  1433. //+-------------------------------------------------------------------------
  1434. //If all of the following three conditions are true, we should not put
  1435. // commercial or individual authenticated attributes into signer info
  1436. //
  1437. //1. the enhanced key usage extension of the signer's certificate has no code signing usage (szOID_PKIX_KP_CODE_SIGNING)
  1438. //2. basic constraints extension of the signer's cert is missing, or it is neither commercial nor individual
  1439. //3. user did not specify -individual or -commercial in signcode.exe.
  1440. //--------------------------------------------------------------------------
  1441. BOOL NeedStatementTypeAttr(IN PCCERT_CONTEXT pSignerCert,
  1442. IN BOOL fCommercial,
  1443. IN BOOL fIndividual)
  1444. {
  1445. BOOL fNeedStatementTypeAttr=FALSE;
  1446. PCERT_EXTENSION pEKUExt=NULL;
  1447. PCERT_EXTENSION pRestrictionExt=NULL;
  1448. DWORD cPolicyId=0;
  1449. PCERT_POLICY_ID pPolicyId=NULL;
  1450. BOOL fPolicyCommercial = FALSE;
  1451. BOOL fPolicyIndividual = FALSE;
  1452. BOOL fCodeSiginigEKU=FALSE;
  1453. PCERT_KEY_USAGE_RESTRICTION_INFO pInfo = NULL;
  1454. DWORD cbInfo=0;
  1455. PCERT_ENHKEY_USAGE pEKUInfo=NULL;
  1456. DWORD dwIndex=0;
  1457. if(!pSignerCert)
  1458. return FALSE;
  1459. //check for condition # 3
  1460. if(fCommercial || fIndividual)
  1461. return TRUE;
  1462. //now we know user did not specify -individual or -commerical options
  1463. //if the cert has enhanced key usage extension
  1464. pEKUExt = CertFindExtension(szOID_ENHANCED_KEY_USAGE,
  1465. pSignerCert->pCertInfo->cExtension,
  1466. pSignerCert->pCertInfo->rgExtension);
  1467. pRestrictionExt = CertFindExtension(szOID_KEY_USAGE_RESTRICTION,
  1468. pSignerCert->pCertInfo->cExtension,
  1469. pSignerCert->pCertInfo->rgExtension);
  1470. if((!pEKUExt) && (!pRestrictionExt))
  1471. return FALSE;
  1472. if(pEKUExt)
  1473. {
  1474. cbInfo=0;
  1475. if(CryptDecodeObject(X509_ASN_ENCODING,
  1476. X509_ENHANCED_KEY_USAGE,
  1477. pEKUExt->Value.pbData,
  1478. pEKUExt->Value.cbData,
  1479. 0, // dwFlags
  1480. NULL, // pInfo
  1481. &cbInfo) && (cbInfo != 0))
  1482. {
  1483. pEKUInfo = (PCERT_ENHKEY_USAGE) malloc(cbInfo);
  1484. if(pEKUInfo)
  1485. {
  1486. if(CryptDecodeObject(X509_ASN_ENCODING,
  1487. X509_ENHANCED_KEY_USAGE,
  1488. pEKUExt->Value.pbData,
  1489. pEKUExt->Value.cbData,
  1490. 0, // dwFlags
  1491. pEKUInfo, // pInfo
  1492. &cbInfo) && (cbInfo != 0))
  1493. {
  1494. for(dwIndex=0; dwIndex < pEKUInfo->cUsageIdentifier; dwIndex++)
  1495. {
  1496. if(0==strcmp(szOID_PKIX_KP_CODE_SIGNING,
  1497. pEKUInfo->rgpszUsageIdentifier[dwIndex]))
  1498. fCodeSiginigEKU=TRUE;
  1499. if(0==strcmp(SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID,
  1500. pEKUInfo->rgpszUsageIdentifier[dwIndex]))
  1501. fPolicyCommercial=TRUE;
  1502. if(0==strcmp(SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID,
  1503. pEKUInfo->rgpszUsageIdentifier[dwIndex]))
  1504. fPolicyIndividual=TRUE;
  1505. }
  1506. }
  1507. }
  1508. }
  1509. }
  1510. if(pRestrictionExt)
  1511. {
  1512. cbInfo = 0;
  1513. if(CryptDecodeObject(X509_ASN_ENCODING,
  1514. X509_KEY_USAGE_RESTRICTION,
  1515. pRestrictionExt->Value.pbData,
  1516. pRestrictionExt->Value.cbData,
  1517. 0, // dwFlags
  1518. NULL, // pInfo
  1519. &cbInfo) && (cbInfo != 0))
  1520. {
  1521. pInfo = (PCERT_KEY_USAGE_RESTRICTION_INFO) malloc(cbInfo);
  1522. if(pInfo)
  1523. {
  1524. if (CryptDecodeObject(X509_ASN_ENCODING,
  1525. X509_KEY_USAGE_RESTRICTION,
  1526. pRestrictionExt->Value.pbData,
  1527. pRestrictionExt->Value.cbData,
  1528. 0, // dwFlags
  1529. pInfo,
  1530. &cbInfo))
  1531. {
  1532. if (pInfo->cCertPolicyId)
  1533. {
  1534. cPolicyId = pInfo->cCertPolicyId;
  1535. pPolicyId = pInfo->rgCertPolicyId;
  1536. for ( ; cPolicyId > 0; cPolicyId--, pPolicyId++)
  1537. {
  1538. DWORD cElementId = pPolicyId->cCertPolicyElementId;
  1539. LPSTR *ppszElementId = pPolicyId->rgpszCertPolicyElementId;
  1540. for ( ; cElementId > 0; cElementId--, ppszElementId++)
  1541. {
  1542. if (strcmp(*ppszElementId,
  1543. SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID) == 0)
  1544. {
  1545. fPolicyCommercial = TRUE;
  1546. }
  1547. if (strcmp(*ppszElementId,
  1548. SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID) == 0)
  1549. fPolicyIndividual = TRUE;
  1550. }
  1551. }
  1552. }
  1553. }
  1554. }
  1555. }
  1556. }
  1557. //free the memory
  1558. if(pInfo)
  1559. free(pInfo);
  1560. if(pEKUInfo)
  1561. free(pEKUInfo);
  1562. //if any of the value is true in the properties,
  1563. //we need to add the statement type attribute
  1564. if( fPolicyCommercial || fPolicyIndividual || fCodeSiginigEKU)
  1565. return TRUE;
  1566. return FALSE;
  1567. }
  1568. //+-------------------------------------------------------------------------
  1569. //
  1570. // The function decides whether to sign the certificate as a commerical,
  1571. // or individual. The default is the certificate's highest capability. If fCommercial
  1572. // is set and the cert can not signly commercially, an error is returned.
  1573. // Same for fIndividual.
  1574. //
  1575. //--------------------------------------------------------------------------
  1576. HRESULT CheckCommercial(PCCERT_CONTEXT pSignerCert, BOOL fCommercial,
  1577. BOOL fIndividual, BOOL *pfCommercial)
  1578. {
  1579. HRESULT hr = S_OK;
  1580. BOOL fPolicyCommercial = FALSE;
  1581. BOOL fPolicyIndividual = FALSE;
  1582. PCERT_EXTENSION pExt;
  1583. PCERT_KEY_USAGE_RESTRICTION_INFO pInfo = NULL;
  1584. DWORD cbInfo;
  1585. PCERT_EXTENSION pEKUExt=NULL;
  1586. PCERT_ENHKEY_USAGE pUsage=NULL;
  1587. DWORD cCount=0;
  1588. if(!pfCommercial)
  1589. return E_INVALIDARG;
  1590. //init
  1591. *pfCommercial=FALSE;
  1592. //fCommercial and fIndividual can not be set at the same time
  1593. if(fCommercial && fIndividual)
  1594. return E_INVALIDARG;
  1595. PKITRY {
  1596. //first look into the cert extension szOID_KEY_USAGE_RESTRICTION
  1597. pExt = CertFindExtension(szOID_KEY_USAGE_RESTRICTION,
  1598. pSignerCert->pCertInfo->cExtension,
  1599. pSignerCert->pCertInfo->rgExtension);
  1600. if(pExt)
  1601. {
  1602. cbInfo = 0;
  1603. CryptDecodeObject(X509_ASN_ENCODING,
  1604. X509_KEY_USAGE_RESTRICTION,
  1605. pExt->Value.pbData,
  1606. pExt->Value.cbData,
  1607. 0, // dwFlags
  1608. NULL, // pInfo
  1609. &cbInfo);
  1610. if (cbInfo == 0)
  1611. PKITHROW(SignError());
  1612. pInfo = (PCERT_KEY_USAGE_RESTRICTION_INFO) malloc(cbInfo);
  1613. if(!pInfo)
  1614. PKITHROW(E_OUTOFMEMORY);
  1615. if (!CryptDecodeObject(X509_ASN_ENCODING,
  1616. X509_KEY_USAGE_RESTRICTION,
  1617. pExt->Value.pbData,
  1618. pExt->Value.cbData,
  1619. 0, // dwFlags
  1620. pInfo,
  1621. &cbInfo))
  1622. PKITHROW(SignError());
  1623. if (pInfo->cCertPolicyId)
  1624. {
  1625. DWORD cPolicyId;
  1626. PCERT_POLICY_ID pPolicyId;
  1627. cPolicyId = pInfo->cCertPolicyId;
  1628. pPolicyId = pInfo->rgCertPolicyId;
  1629. for ( ; cPolicyId > 0; cPolicyId--, pPolicyId++)
  1630. {
  1631. DWORD cElementId = pPolicyId->cCertPolicyElementId;
  1632. LPSTR *ppszElementId = pPolicyId->rgpszCertPolicyElementId;
  1633. for ( ; cElementId > 0; cElementId--, ppszElementId++)
  1634. {
  1635. if (strcmp(*ppszElementId,
  1636. SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID) == 0)
  1637. {
  1638. fPolicyCommercial = TRUE;
  1639. }
  1640. if (strcmp(*ppszElementId,
  1641. SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID) == 0)
  1642. fPolicyIndividual = TRUE;
  1643. }
  1644. }
  1645. } //end of pInfo->cCertPolicyId
  1646. } //end of pExt
  1647. //now
  1648. }
  1649. PKICATCH(err)
  1650. {
  1651. hr = err.pkiError;
  1652. } PKIEND;
  1653. if (pInfo)
  1654. {
  1655. free(pInfo);
  1656. pInfo=NULL;
  1657. }
  1658. if(hr!=S_OK)
  1659. return hr;
  1660. //if either of the policy is set, we check for the EKU extension
  1661. if((!fPolicyCommercial) && (!fPolicyIndividual))
  1662. {
  1663. pExt = CertFindExtension(szOID_ENHANCED_KEY_USAGE,
  1664. pSignerCert->pCertInfo->cExtension,
  1665. pSignerCert->pCertInfo->rgExtension);
  1666. if(pExt)
  1667. {
  1668. cbInfo = 0;
  1669. if(CryptDecodeObject(X509_ASN_ENCODING,
  1670. X509_ENHANCED_KEY_USAGE,
  1671. pExt->Value.pbData,
  1672. pExt->Value.cbData,
  1673. 0,
  1674. NULL,
  1675. &cbInfo) && (cbInfo != 0))
  1676. {
  1677. pUsage = (PCERT_ENHKEY_USAGE) malloc(cbInfo);
  1678. if(pUsage)
  1679. {
  1680. if (CryptDecodeObject(X509_ASN_ENCODING,
  1681. X509_ENHANCED_KEY_USAGE,
  1682. pExt->Value.pbData,
  1683. pExt->Value.cbData,
  1684. 0, // dwFlags
  1685. pUsage,
  1686. &cbInfo))
  1687. {
  1688. for(cCount=0; cCount< pUsage->cUsageIdentifier; cCount++)
  1689. {
  1690. if (strcmp((pUsage->rgpszUsageIdentifier)[cCount],
  1691. SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID) == 0)
  1692. {
  1693. fPolicyCommercial = TRUE;
  1694. }
  1695. if (strcmp((pUsage->rgpszUsageIdentifier)[cCount],
  1696. SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID) == 0)
  1697. {
  1698. fPolicyIndividual = TRUE;
  1699. }
  1700. }
  1701. }
  1702. }
  1703. }
  1704. }
  1705. }
  1706. if(pUsage)
  1707. {
  1708. free(pUsage);
  1709. pUsage=NULL;
  1710. }
  1711. //if either of the policy is set, we use individual
  1712. if(!fPolicyCommercial && !fPolicyIndividual)
  1713. fPolicyIndividual=TRUE;
  1714. //default
  1715. if((!fCommercial) && (!fIndividual))
  1716. {
  1717. if(fPolicyCommercial)
  1718. *pfCommercial=TRUE;
  1719. else
  1720. *pfCommercial=FALSE;
  1721. return S_OK;
  1722. }
  1723. if(fCommercial && (!fIndividual))
  1724. {
  1725. if(fPolicyCommercial)
  1726. {
  1727. *pfCommercial=TRUE;
  1728. return S_OK;
  1729. }
  1730. else
  1731. return TYPE_E_TYPEMISMATCH;
  1732. }
  1733. //the following is fIndividual and !fCommercial
  1734. if(fPolicyIndividual)
  1735. {
  1736. *pfCommercial=FALSE;
  1737. return S_OK;
  1738. }
  1739. else
  1740. return TYPE_E_TYPEMISMATCH;
  1741. }
  1742. //+-------------------------------------------------------------------------
  1743. // Encode the StatementType authenticated attribute value
  1744. //--------------------------------------------------------------------------
  1745. HRESULT CreateStatementType(IN BOOL fCommercial,
  1746. OUT BYTE **ppbEncoded,
  1747. IN OUT DWORD *pcbEncoded)
  1748. {
  1749. HRESULT hr = S_OK;
  1750. PBYTE pbEncoded = NULL;
  1751. DWORD cbEncoded;
  1752. LPSTR pszIndividual = SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID;
  1753. LPSTR pszCommercial = SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID;
  1754. SPC_STATEMENT_TYPE StatementType;
  1755. StatementType.cKeyPurposeId = 1;
  1756. if (fCommercial)
  1757. StatementType.rgpszKeyPurposeId = &pszCommercial;
  1758. else
  1759. StatementType.rgpszKeyPurposeId = &pszIndividual;
  1760. PKITRY {
  1761. cbEncoded = 0;
  1762. CryptEncodeObject(X509_ASN_ENCODING,
  1763. SPC_STATEMENT_TYPE_STRUCT,
  1764. &StatementType,
  1765. NULL, // pbEncoded
  1766. &cbEncoded);
  1767. if (cbEncoded == 0)
  1768. PKITHROW(SignError());
  1769. pbEncoded = (BYTE *) malloc(cbEncoded);
  1770. if (pbEncoded == NULL)
  1771. PKITHROW(E_OUTOFMEMORY);
  1772. if (!CryptEncodeObject(X509_ASN_ENCODING,
  1773. SPC_STATEMENT_TYPE_STRUCT,
  1774. &StatementType,
  1775. pbEncoded,
  1776. &cbEncoded))
  1777. PKITHROW(SignError());
  1778. }
  1779. PKICATCH(err) {
  1780. if (pbEncoded) {
  1781. free(pbEncoded);
  1782. pbEncoded = NULL;
  1783. }
  1784. cbEncoded = 0;
  1785. hr = err.pkiError;
  1786. } PKIEND;
  1787. *ppbEncoded = pbEncoded;
  1788. *pcbEncoded = cbEncoded;
  1789. return hr;
  1790. }
  1791. //+-------------------------------------------------------------------------
  1792. // Encode the SpOpusInfo authenticated attribute value
  1793. //--------------------------------------------------------------------------
  1794. HRESULT CreateOpusInfo(IN LPCWSTR pwszOpusName,
  1795. IN LPCWSTR pwszOpusInfo,
  1796. OUT BYTE **ppbEncoded,
  1797. IN OUT DWORD *pcbEncoded)
  1798. {
  1799. HRESULT hr = S_OK;
  1800. BYTE *pbEncoded = NULL;
  1801. DWORD cbEncoded;
  1802. SPC_LINK MoreInfo;
  1803. SPC_SP_OPUS_INFO sSpcOpusInfo;
  1804. ZeroMemory(&sSpcOpusInfo, sizeof(SPC_SP_OPUS_INFO));
  1805. sSpcOpusInfo.pwszProgramName = (LPWSTR) pwszOpusName;
  1806. if (pwszOpusInfo) {
  1807. MoreInfo.dwLinkChoice = SPC_URL_LINK_CHOICE;
  1808. //
  1809. // To be backwards compatible with IE 3.0 WinVerifyTrust the
  1810. // following is set to an even length to inhibit the possibility
  1811. // of an 0x7f length in the encoded ASN.
  1812. // In IE 3.0 an 0x81 is erroneously prepended before a
  1813. // 0x7f length when the OPUS info is re-encoded before hashing. Making
  1814. // the length of pwszUrl even precludes this from happening.
  1815. //
  1816. // Note, the pwszUrl is first converted to multibyte before being
  1817. // encoded. Its the multibyte length that must have an even length.
  1818. int cchMultiByte;
  1819. cchMultiByte = WideCharToMultiByte(CP_ACP,
  1820. 0, // dwFlags
  1821. pwszOpusInfo,
  1822. -1, // cchWideChar, -1 => null terminated
  1823. NULL, // lpMultiByteStr
  1824. 0, // cchMultiByte
  1825. NULL, // lpDefaultChar
  1826. NULL // lpfUsedDefaultChar
  1827. );
  1828. // cchMultiByte includes the null terminator
  1829. if (cchMultiByte > 1 && ((cchMultiByte - 1) & 1)) {
  1830. // Odd length. Add extra space to end.
  1831. int Len = wcslen(pwszOpusInfo);
  1832. MoreInfo.pwszUrl = (LPWSTR) _alloca((Len + 2) * sizeof(WCHAR));
  1833. wcscpy(MoreInfo.pwszUrl, pwszOpusInfo);
  1834. wcscpy(MoreInfo.pwszUrl + Len, L" ");
  1835. } else
  1836. MoreInfo.pwszUrl = (LPWSTR) pwszOpusInfo;
  1837. sSpcOpusInfo.pMoreInfo = &MoreInfo;
  1838. }
  1839. PKITRY {
  1840. cbEncoded = 0;
  1841. CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1842. SPC_SP_OPUS_INFO_STRUCT,
  1843. &sSpcOpusInfo,
  1844. NULL, // pbEncoded
  1845. &cbEncoded);
  1846. if (cbEncoded == 0)
  1847. PKITHROW(SignError());
  1848. pbEncoded = (BYTE *) malloc(cbEncoded);
  1849. if (pbEncoded == NULL)
  1850. PKITHROW(E_OUTOFMEMORY);
  1851. if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1852. SPC_SP_OPUS_INFO_STRUCT,
  1853. &sSpcOpusInfo,
  1854. pbEncoded,
  1855. &cbEncoded))
  1856. PKITHROW(SignError());
  1857. }
  1858. PKICATCH(err) {
  1859. if (pbEncoded) {
  1860. free(pbEncoded);
  1861. pbEncoded = NULL;
  1862. }
  1863. cbEncoded = 0;
  1864. hr = err.pkiError;
  1865. } PKIEND;
  1866. *ppbEncoded = pbEncoded;
  1867. *pcbEncoded = cbEncoded;
  1868. return hr;
  1869. }
  1870. //+-------------------------------------------------------------------------
  1871. // Checks if the certificate a glue certificate
  1872. // in IE30
  1873. // Returns: S_OK - Is a glue certificate
  1874. // S_FALSE - Not a certificate
  1875. // CRYPT_E_OSS_ERROR + Oss error - Encode or Decode error.
  1876. //+-------------------------------------------------------------------------
  1877. HRESULT SignIsGlueCert(IN PCCERT_CONTEXT pCert)
  1878. {
  1879. HRESULT hr = S_OK;
  1880. PCERT_NAME_BLOB pName = &pCert->pCertInfo->Subject;
  1881. PCERT_NAME_INFO pNameInfo = NULL;
  1882. DWORD cbNameInfo;
  1883. PKITRY {
  1884. cbNameInfo = 0;
  1885. CryptDecodeObject(X509_ASN_ENCODING,
  1886. X509_NAME,
  1887. pName->pbData,
  1888. pName->cbData,
  1889. 0, // dwFlags
  1890. NULL, // pNameInfo
  1891. &cbNameInfo);
  1892. if (cbNameInfo == 0)
  1893. PKITHROW(SignError());
  1894. pNameInfo = (PCERT_NAME_INFO) malloc(cbNameInfo);
  1895. if(!pNameInfo)
  1896. return E_OUTOFMEMORY;
  1897. if (!CryptDecodeObject(X509_ASN_ENCODING,
  1898. X509_NAME,
  1899. pName->pbData,
  1900. pName->cbData,
  1901. 0, // dwFlags
  1902. pNameInfo,
  1903. &cbNameInfo))
  1904. PKITHROW(SignError());
  1905. if(!CertFindRDNAttr(SPC_GLUE_RDN_OBJID, pNameInfo) != NULL)
  1906. hr = S_FALSE;
  1907. }
  1908. PKICATCH (err) {
  1909. hr = err.pkiError;
  1910. } PKIEND;
  1911. if (pNameInfo) free(pNameInfo);
  1912. return hr;
  1913. }
  1914. //+-------------------------------------------------------------------------
  1915. // Skip over the identifier and length octets in an ASN encoded blob.
  1916. // Returns the number of bytes skipped.
  1917. //
  1918. // For an invalid identifier or length octet returns 0.
  1919. //--------------------------------------------------------------------------
  1920. static DWORD SkipOverIdentifierAndLengthOctets(
  1921. IN const BYTE *pbDER,
  1922. IN DWORD cbDER
  1923. )
  1924. {
  1925. #define TAG_MASK 0x1f
  1926. DWORD cb;
  1927. DWORD cbLength;
  1928. const BYTE *pb = pbDER;
  1929. // Need minimum of 2 bytes
  1930. if (cbDER < 2)
  1931. return 0;
  1932. // Skip over the identifier octet(s)
  1933. if (TAG_MASK == (*pb++ & TAG_MASK)) {
  1934. // high-tag-number form
  1935. for (cb=2; *pb++ & 0x80; cb++) {
  1936. if (cb >= cbDER)
  1937. return 0;
  1938. }
  1939. } else
  1940. // low-tag-number form
  1941. cb = 1;
  1942. // need at least one more byte for length
  1943. if (cb >= cbDER)
  1944. return 0;
  1945. if (0x80 == *pb)
  1946. // Indefinite
  1947. cb++;
  1948. else if ((cbLength = *pb) & 0x80) {
  1949. cbLength &= ~0x80; // low 7 bits have number of bytes
  1950. cb += cbLength + 1;
  1951. if (cb > cbDER)
  1952. return 0;
  1953. } else
  1954. cb++;
  1955. return cb;
  1956. }
  1957. //--------------------------------------------------------------------------
  1958. //
  1959. // Skip over the tag and length
  1960. //----------------------------------------------------------------------------
  1961. BOOL WINAPI SignNoContentWrap(IN const BYTE *pbDER,
  1962. IN DWORD cbDER)
  1963. {
  1964. DWORD cb;
  1965. cb = SkipOverIdentifierAndLengthOctets(pbDER, cbDER);
  1966. if (cb > 0 && cb < cbDER && pbDER[cb] == 0x02)
  1967. return TRUE;
  1968. else
  1969. return FALSE;
  1970. }
  1971. #define SH1_HASH_LENGTH 20
  1972. //+-----------------------------------------------------------------------
  1973. // Make sure that the certificate is valid for timestamp
  1974. //------------------------------------------------------------------------
  1975. /*BOOL ValidTimestampCert(PCCERT_CONTEXT pCertContext)
  1976. {
  1977. BOOL fValid=FALSE;
  1978. DWORD cbSize=0;
  1979. PCERT_ENHKEY_USAGE pCertEKU=NULL;
  1980. BYTE *pbaSignersThumbPrint=NULL;
  1981. DWORD dwIndex=0;
  1982. static BYTE baVerisignTimeStampThumbPrint[SH1_HASH_LENGTH] =
  1983. { 0x38, 0x73, 0xB6, 0x99, 0xF3, 0x5B, 0x9C, 0xCC, 0x36, 0x62,
  1984. 0xB6, 0x48, 0x3A, 0x96, 0xBD, 0x6E, 0xEC, 0x97, 0xCF, 0xB7 };
  1985. cbSize = 0;
  1986. if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID,
  1987. NULL, &cbSize)))
  1988. goto CLEANUP;
  1989. pbaSignersThumbPrint=(BYTE *)malloc(cbSize);
  1990. if(!pbaSignersThumbPrint)
  1991. goto CLEANUP;
  1992. if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID,
  1993. pbaSignersThumbPrint, &cbSize)))
  1994. goto CLEANUP;
  1995. //
  1996. // 1st, check to see if it's Verisign's first timestamp certificate
  1997. if(cbSize!=sizeof(baVerisignTimeStampThumbPrint)/sizeof(baVerisignTimeStampThumbPrint[0]))
  1998. goto CLEANUP;
  1999. if (memcmp(pbaSignersThumbPrint, baVerisignTimeStampThumbPrint, cbSize) == 0)
  2000. {
  2001. fValid=TRUE;
  2002. goto CLEANUP;
  2003. }
  2004. //
  2005. // see if the certificate has the proper enhanced key usage OID
  2006. //
  2007. cbSize = 0;
  2008. if(!CertGetEnhancedKeyUsage(pCertContext,
  2009. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  2010. NULL,
  2011. &cbSize) || (cbSize==0))
  2012. goto CLEANUP;
  2013. pCertEKU = (PCERT_ENHKEY_USAGE)malloc(cbSize);
  2014. if(!pCertEKU)
  2015. goto CLEANUP;
  2016. if (!(CertGetEnhancedKeyUsage(pCertContext,
  2017. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  2018. pCertEKU,
  2019. &cbSize)))
  2020. goto CLEANUP;
  2021. for (dwIndex = 0; dwIndex < pCertEKU->cUsageIdentifier; dwIndex++)
  2022. {
  2023. if (strcmp(pCertEKU->rgpszUsageIdentifier[dwIndex], szOID_KP_TIME_STAMP_SIGNING) == 0)
  2024. {
  2025. fValid=TRUE;
  2026. break;
  2027. }
  2028. if (strcmp(pCertEKU->rgpszUsageIdentifier[dwIndex], szOID_PKIX_KP_TIMESTAMP_SIGNING) == 0)
  2029. {
  2030. fValid=TRUE;
  2031. break;
  2032. }
  2033. }
  2034. CLEANUP:
  2035. if(pbaSignersThumbPrint)
  2036. free(pbaSignersThumbPrint);
  2037. if(pCertEKU)
  2038. free(pCertEKU);
  2039. return fValid;
  2040. } */
  2041. //-------------------------------------------------------------------------
  2042. //
  2043. // Call GetLastError and convert the return code to HRESULT
  2044. //--------------------------------------------------------------------------
  2045. HRESULT WINAPI SignError ()
  2046. {
  2047. DWORD dw = GetLastError ();
  2048. HRESULT hr;
  2049. if ( dw <= (DWORD) 0xFFFF )
  2050. hr = HRESULT_FROM_WIN32 ( dw );
  2051. else
  2052. hr = dw;
  2053. if ( ! FAILED ( hr ) )
  2054. {
  2055. // somebody failed a call without properly setting an error condition
  2056. hr = E_UNEXPECTED;
  2057. }
  2058. return hr;
  2059. }