Leaked source code of windows server 2003
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.

4714 lines
136 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: makecert.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //+-------------------------------------------------------------------------
  11. //
  12. // MakeCert - x509 certificate generator
  13. //
  14. // Generates test certificates for Software Publishers. The default
  15. // root key and certificate is stored as a program resource.
  16. //
  17. // HansHu 2/20/96 created
  18. // Philh 5/17/96 changed to use wincert
  19. // Xiaohs 5/12/97 localization and change the command line options
  20. //
  21. //--------------------------------------------------------------------------
  22. #define _CRYPT32_
  23. #include "global.hxx"
  24. //+-------------------------------------------------------------------------
  25. // contants
  26. //--------------------------------------------------------------------------
  27. //allow max 10 extensions per certificate
  28. #define MAX_EXT_CNT 10
  29. //+-------------------------------------------------------------------------
  30. // Parameters configurable via command line arguments
  31. //--------------------------------------------------------------------------
  32. BOOL fUseSubjectPvkFile = FALSE;
  33. BOOL fUseSubjectKeyContainer = FALSE;
  34. BOOL fUseIssuerPvkFile = FALSE;
  35. BOOL fSetSubjectName = FALSE; //use has specify the -n option
  36. #if (1) //DSIE: Bug 205195
  37. BOOL fPrivateKeyExportable = FALSE;
  38. #endif
  39. WCHAR* wszSubjectKey = NULL;
  40. WCHAR* wszSubjectCertFile = NULL;
  41. WCHAR* wszSubjectStore = NULL;
  42. WCHAR* wszSubjectStoreLocation = NULL;
  43. DWORD dwSubjectStoreFlag = CERT_SYSTEM_STORE_CURRENT_USER;
  44. WCHAR* wszIssuerKey = NULL;
  45. WCHAR* wszIssuerCertFile = NULL;
  46. WCHAR* wszIssuerStore = NULL;
  47. WCHAR* wszIssuerStoreLocation = NULL;
  48. DWORD dwIssuerStoreFlag = CERT_SYSTEM_STORE_CURRENT_USER;
  49. WCHAR* wszIssuerCertName = NULL;
  50. DWORD dwIssuerKeySpec = 0;
  51. WCHAR* wszSubjectX500Name = NULL;
  52. WCHAR* wszSubjectRequestFile = NULL;
  53. WCHAR* wszPolicyLink = NULL;
  54. WCHAR* wszOutputFile = NULL;
  55. WCHAR* wszAuthority = NULL;
  56. WCHAR* wszAlgorithm = NULL;
  57. WCHAR* wszCertType = NULL;
  58. WCHAR* wszIssuerKeyType = NULL;
  59. WCHAR* wszSubjectKeyType = NULL;
  60. WCHAR* wszEKUOids = NULL;
  61. DWORD dwKeySpec = 0;
  62. BOOL fCertIndividual = FALSE;
  63. BOOL fCertCommercial = FALSE;
  64. BOOL fSelfSigned = FALSE;
  65. BOOL fGlueCert = FALSE;
  66. BOOL fNetscapeClientAuth = FALSE;
  67. BOOL fNoPubKeyPara = FALSE;
  68. BOOL fNoVerifyPublic = FALSE;
  69. LPWSTR wszIssuerProviderName = NULL;
  70. DWORD dwIssuerProviderType = PROV_RSA_FULL;
  71. LPWSTR wszSubjectProviderName = NULL;
  72. DWORD dwSubjectProviderType = PROV_RSA_FULL;
  73. ALG_ID algidHash = CALG_MD5;
  74. ULONG ulSerialNumber = 0; // In future, allow serial nubmers of larger size
  75. BOOL fSetSerialNumber = FALSE;
  76. DWORD dwCertStoreEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  77. BOOL fIssuerInformation = FALSE;
  78. BOOL fSubjectInformation = FALSE;
  79. LPWSTR wszDhParaCertFile = NULL;
  80. DWORD dwKeyBitLen = 0;
  81. WCHAR wszGlue[10];
  82. WCHAR wszKey[10];
  83. WCHAR wszName[40];
  84. WCHAR wszRoot[40];
  85. WCHAR wszMakeCertRoot[40]; //used for indicating to use the root.cer. Root is also a registry name
  86. WCHAR wszPlus[10];
  87. WCHAR wszNULL[10];
  88. FILETIME g_ftNotBefore = { 0, 0 };
  89. FILETIME g_ftNotAfter = { 0, 0 };
  90. FILETIME g_ftZero = { 0, 0 };
  91. long nMonths = -1;
  92. long pathLenConstraint = -1;
  93. BYTE certTypes = 0; // must be of type BYTE
  94. CHAR* szSignatureAlgObjId = NULL;
  95. static CERT_RDN_ATTR GlueRDNAttr=
  96. {
  97. SPC_GLUE_RDN_OBJID, CERT_RDN_PRINTABLE_STRING,
  98. {0, (BYTE *) wszGlue }
  99. };
  100. //Global Data for loading the string
  101. #define OPTION_SWITCH_SIZE 5
  102. HMODULE hModule=NULL;
  103. //---------------------------------------------------------------------------
  104. // Get the hModule hanlder and init two DLLMain.
  105. //
  106. //---------------------------------------------------------------------------
  107. BOOL InitModule()
  108. {
  109. if(!(hModule=GetModuleHandle(NULL)))
  110. return FALSE;
  111. return TRUE;
  112. }
  113. //-------------------------------------------------------------------------
  114. //
  115. // BasicUsage()
  116. //
  117. //
  118. //-------------------------------------------------------------------------
  119. static void BasicUsage()
  120. {
  121. IDSwprintf(hModule,IDS_SYNTAX);
  122. IDSwprintf(hModule,IDS_BASIC_OPTIONS);
  123. IDSwprintf(hModule,IDS_OPTION_SK_DESC);
  124. #if (1) //DSIE: Bug 205195.
  125. IDSwprintf(hModule,IDS_OPTION_PE_DESC);
  126. #endif
  127. IDSwprintf(hModule,IDS_OPTION_SS_DESC);
  128. IDSwprintf(hModule,IDS_OPTION_SS_DESC1);
  129. IDSwprintf(hModule,IDS_OPTION_SR_DESC);
  130. IDS_IDS_IDS_IDSwprintf(hModule,IDS_OPTION_VALUES_DEFAULT, IDS_OPTION_CU,
  131. IDS_OPTION_LM,IDS_OPTION_CU );
  132. IDSwprintf(hModule,IDS_OPTION_SERIAL_DESC);
  133. IDSwprintf(hModule,IDS_OPTION_AUTH_DESC);
  134. IDS_IDS_IDSwprintf(hModule,IDS_OPTION_VALUES_2, IDS_OPTION_AUTH_IND,
  135. IDS_OPTION_AUTH_COM);
  136. IDSwprintf(hModule,IDS_OPTION_N_DESC);
  137. IDSwprintf(hModule,IDS_OPTION_BASIC_DESC);
  138. IDSwprintf(hModule,IDS_OPTION_EXTENDED_DESC);
  139. }
  140. //-------------------------------------------------------------------------
  141. //
  142. // ExtendedUsage()
  143. //
  144. //
  145. //-------------------------------------------------------------------------
  146. static void ExtendedUsage()
  147. {
  148. IDSwprintf(hModule,IDS_SYNTAX);
  149. IDSwprintf(hModule,IDS_EXTENDED_OPTIONS);
  150. IDSwprintf(hModule,IDS_OPTION_SC_DESC);
  151. IDSwprintf(hModule,IDS_OPTION_SV_DESC);
  152. IDSwprintf(hModule,IDS_OPTION_IC_DESC);
  153. IDSwprintf(hModule,IDS_OPTION_IK_DESC);
  154. IDSwprintf(hModule,IDS_OPTION_IV_DESC);
  155. IDSwprintf(hModule,IDS_OPTION_IS_DESC);
  156. IDSwprintf(hModule,IDS_OPTION_IR_DESC);
  157. IDS_IDS_IDS_IDSwprintf(hModule,IDS_OPTION_VALUES_DEFAULT, IDS_OPTION_CU,
  158. IDS_OPTION_LM,IDS_OPTION_CU );
  159. IDSwprintf(hModule,IDS_OPTION_IN_DESC);
  160. IDSwprintf(hModule,IDS_OPTION_ALGO_DESC, IDS_OPTION_ALGO);
  161. IDS_IDS_IDS_IDSwprintf(hModule,IDS_OPTION_VALUES_DEFAULT,IDS_OPTION_ALGO_MD5,
  162. IDS_OPTION_ALGO_SHA, IDS_OPTION_ALGO_MD5);
  163. IDSwprintf(hModule,IDS_OPTION_IP_DESC);
  164. IDSwprintf(hModule,IDS_OPTION_IY_DESC);
  165. IDSwprintf(hModule,IDS_OPTION_SP_DESC);
  166. IDSwprintf(hModule,IDS_OPTION_SY_DESC);
  167. IDSwprintf(hModule,IDS_OPTION_IKY_DESC);
  168. IDS_IDS_IDS_IDSwprintf(hModule,IDS_OPTION_VALUES_KY, IDS_OPTION_KY_SIG,
  169. IDS_OPTION_KY_EXC,IDS_OPTION_KY_SIG);
  170. IDSwprintf(hModule,IDS_OPTION_SKY_DESC);
  171. IDS_IDS_IDS_IDSwprintf(hModule,IDS_OPTION_VALUES_KY, IDS_OPTION_KY_SIG,
  172. IDS_OPTION_KY_EXC,IDS_OPTION_KY_SIG);
  173. IDSwprintf(hModule,IDS_OPTION_L_DESC);
  174. IDSwprintf(hModule,IDS_OPTION_CY_DESC);
  175. IDS_IDS_IDSwprintf(hModule,IDS_OPTION_VALUES_2, IDS_OPTION_CY_END,
  176. IDS_OPTION_CY_AUTH);
  177. IDSwprintf(hModule,IDS_OPTION_B_DESC);
  178. IDSwprintf(hModule,IDS_OPTION_M_DESC);
  179. IDSwprintf(hModule,IDS_OPTION_E_DESC);
  180. IDSwprintf(hModule,IDS_OPTION_H_DESC);
  181. // IDSwprintf(hModule,IDS_OPTION_G_DESC);
  182. IDSwprintf(hModule,IDS_OPTION_KEY_LEN_DESC);
  183. IDSwprintf(hModule,IDS_OPTION_R_DESC);
  184. IDSwprintf(hModule,IDS_OPTION_NSCP_DESC);
  185. IDSwprintf(hModule,IDS_OPTION_ENHKEY_USAGE_DESC);
  186. IDSwprintf(hModule,IDS_OPTION_BASIC_DESC);
  187. IDSwprintf(hModule,IDS_OPTION_EXTENDED_DESC);
  188. }
  189. static void UndocumentedUsage()
  190. {
  191. IDSwprintf(hModule,IDS_SYNTAX);
  192. IDSwprintf(hModule,IDS_OPTION_SQ_DESC);
  193. IDSwprintf(hModule,IDS_OPTION_NOPUBKEYPARA_DESC);
  194. IDSwprintf(hModule,IDS_OPTION_DH_PARA_DESC);
  195. IDSwprintf(hModule,IDS_OPTION_NOPUBVERIFY_DESC);
  196. }
  197. //+=========================================================================
  198. // Local Support Functions
  199. //==========================================================================
  200. //+-------------------------------------------------------------------------
  201. // Error output routines
  202. //--------------------------------------------------------------------------
  203. void PrintLastError(int ids)
  204. {
  205. DWORD dwErr = GetLastError();
  206. IDS_IDS_DW_DWwprintf(hModule,IDS_ERR_LAST, ids, dwErr, dwErr);
  207. }
  208. //+-------------------------------------------------------------------------
  209. // Allocation and free macros
  210. //--------------------------------------------------------------------------
  211. #define MakeCertAlloc(p1) ToolUtlAlloc(p1, hModule, IDS_ERR_DESC_ALLOC)
  212. #define MakeCertFree(p1) ToolUtlFree(p1)
  213. //-----------------------------------------------------------------------------
  214. //
  215. // Calculate the number of days
  216. //-----------------------------------------------------------------------------
  217. WORD DaysInMonth(WORD wMonth, WORD wYear)
  218. {
  219. static int mpMonthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  220. // J F M A M J J A S O N D
  221. WORD w = (WORD)mpMonthDays[wMonth];
  222. if ((wMonth == 2) && (wYear % 4 == 0) && (wYear%400 == 0 || wYear%100 != 0))
  223. {
  224. w += 1;
  225. }
  226. return w;
  227. }
  228. //-----------------------------------------------------------------------------
  229. //
  230. // Convert the string into a FILETIME. Let OLE do a bunch of work for us.
  231. //----------------------------------------------------------------------------
  232. BOOL FtFromWStr(LPCWSTR wsz, FILETIME* pft)
  233. {
  234. memset(pft, 0, sizeof(*pft));
  235. WCHAR wszMonth[3];
  236. DWORD lcid=0;
  237. WORD langid=0;
  238. //make sure wsz follows the mm/dd/yyyy
  239. if(wcslen(wsz)!=wcslen(L"mm/dd/yyyy"))
  240. return FALSE;
  241. //make sure wsz starts with "mm"
  242. wszMonth[0]=wsz[0];
  243. wszMonth[1]=wsz[1];
  244. wszMonth[2]=L'\0';
  245. if(!((_wtol(wszMonth)>0)&&(_wtol(wszMonth)<=12)))
  246. return FALSE;
  247. if (wsz)
  248. {
  249. //
  250. // The DATE Type
  251. //
  252. // The DATE type is implemented using an 8-byte floating-point number.
  253. // Days are represented by whole number increments starting with 30
  254. // December 1899, midnight as time zero. Hour values are expressed
  255. // as the absolute value of the fractional part of the number.
  256. //
  257. // We are using the English locale since the input format
  258. // should always be mm/dd/yyyy
  259. //
  260. langid=MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  261. lcid = MAKELCID (langid, SORT_DEFAULT);
  262. DATE date;
  263. if (VarDateFromStr((LPWSTR)wsz, lcid, 0, &date) != S_OK)
  264. { return FALSE; }
  265. if (date < 0)
  266. { return FALSE; } // not implemented
  267. double days = date;
  268. double hours = ((days - (LONG) days) * 24);
  269. double minutes= ((hours - (LONG) hours) * 60);
  270. double seconds= ((minutes - (LONG) minutes) * 60);
  271. double ms = ((seconds - (LONG) seconds) * 1000);
  272. SYSTEMTIME st;
  273. st.wYear = 1899;
  274. st.wMonth = 12;
  275. ULONG wDay = 30 + (ULONG)days;
  276. st.wHour = (WORD)hours;
  277. st.wMinute = (WORD)minutes;
  278. st.wSecond = (WORD)seconds;
  279. st.wMilliseconds = (WORD)ms;
  280. //
  281. // Correct for rounding errors in the arithmetic
  282. //
  283. if (st.wMilliseconds >= 0.5)
  284. st.wSecond += 1;
  285. st.wMilliseconds = 0;
  286. if (st.wSecond >= 60)
  287. {
  288. st.wMinute += 1;
  289. st.wSecond -= 60;
  290. }
  291. if (st.wMinute >= 60)
  292. {
  293. st.wHour += 1;
  294. st.wMinute -= 60;
  295. }
  296. if (st.wHour >= 24)
  297. {
  298. st.wHour -= 24;
  299. }
  300. while (wDay > DaysInMonth(st.wMonth, st.wYear))
  301. {
  302. wDay -= DaysInMonth(st.wMonth, st.wYear);
  303. st.wMonth += 1;
  304. if (st.wMonth > 12)
  305. {
  306. st.wMonth = 1;
  307. st.wYear += 1;
  308. }
  309. }
  310. st.wDay = (WORD)wDay;
  311. st.wDayOfWeek = 0;
  312. FILETIME ft;
  313. SystemTimeToFileTime(&st, &ft);
  314. LocalFileTimeToFileTime(&ft, pft);
  315. return TRUE;
  316. }
  317. else
  318. return FALSE;
  319. }
  320. //-------------------------------------------------------------------------
  321. //
  322. // Set the parameters. Each parameter can only be set once
  323. //
  324. //--------------------------------------------------------------------------
  325. BOOL SetParam(WCHAR **pwszParam, WCHAR *wszValue)
  326. {
  327. if(*pwszParam!=NULL)
  328. {
  329. IDSwprintf(hModule,IDS_ERR_TOO_MANY_PARAM);
  330. return FALSE;
  331. }
  332. *pwszParam=wszValue;
  333. if(NULL==wszValue)
  334. return FALSE;
  335. return TRUE;
  336. }
  337. //--------------------------------------------------------------------------
  338. //
  339. // Command Line Parsing
  340. //
  341. //--------------------------------------------------------------------------
  342. static BOOL ParseCommandLine(int argc, WCHAR* wargv[])
  343. {
  344. for ( int i = 1; i < argc; ++i )
  345. {
  346. WCHAR* p = wargv[i];
  347. if(IDSwcsnicmp(hModule,p, IDS_SWITCH1, 1)!=0 &&
  348. IDSwcsnicmp(hModule,p,IDS_SWITCH2, 1)!=0)
  349. {
  350. if(!SetParam(&wszOutputFile,p))
  351. goto BasicErr;
  352. else
  353. continue;
  354. }
  355. //move over to the real option
  356. ++p;
  357. if(IDSwcsicmp(hModule,p, IDS_OPTION_SERIAL)==0)
  358. {
  359. i++;
  360. p=wargv[i];
  361. if(NULL==p)
  362. goto BasicErr;
  363. ulSerialNumber=_wtol(p);
  364. fSetSerialNumber=TRUE;
  365. continue;
  366. }
  367. if(IDSwcsicmp(hModule,p, IDS_OPTION_H)==0)
  368. {
  369. i++;
  370. p=wargv[i];
  371. if(NULL==p)
  372. goto ExtendedErr;
  373. pathLenConstraint=_wtol(p);
  374. if(pathLenConstraint < 0)
  375. goto ExtendedErr;
  376. continue;
  377. }
  378. if(IDSwcsicmp(hModule,p, IDS_OPTION_CY)==0)
  379. {
  380. i++;
  381. p=wargv[i];
  382. if(!SetParam(&wszCertType, p))
  383. goto ExtendedErr;
  384. continue;
  385. }
  386. if(IDSwcsicmp(hModule,p, IDS_OPTION_M)==0)
  387. {
  388. i++;
  389. p=wargv[i];
  390. if(NULL==p)
  391. goto ExtendedErr;
  392. nMonths=_wtol(p);
  393. if(nMonths < 0)
  394. goto ExtendedErr;
  395. continue;
  396. }
  397. if(IDSwcsicmp(hModule,p, IDS_OPTION_B)==0)
  398. {
  399. i++;
  400. p=wargv[i];
  401. if(NULL==p)
  402. goto ExtendedErr;
  403. if(!FtFromWStr(p, &g_ftNotBefore))
  404. {
  405. IDSwprintf(hModule, IDS_ERR_INVALID_B);
  406. goto ExtendedErr;
  407. }
  408. continue;
  409. }
  410. if(IDSwcsicmp(hModule,p, IDS_OPTION_E)==0)
  411. {
  412. i++;
  413. p=wargv[i];
  414. if(NULL==p)
  415. goto ExtendedErr;
  416. if(!FtFromWStr(p, &g_ftNotAfter))
  417. {
  418. IDSwprintf(hModule, IDS_ERR_INVALID_E);
  419. goto ExtendedErr;
  420. }
  421. continue;
  422. }
  423. if(IDSwcsicmp(hModule,p, IDS_OPTION_AUTH)==0)
  424. {
  425. i++;
  426. p=wargv[i];
  427. if(!SetParam(&wszAuthority, p))
  428. goto BasicErr;
  429. continue;
  430. }
  431. if(IDSwcsicmp(hModule,p, IDS_OPTION_R)==0)
  432. {
  433. fSelfSigned=TRUE;
  434. continue;
  435. }
  436. if(IDSwcsicmp(hModule,p, IDS_OPTION_SK)==0)
  437. {
  438. i++;
  439. p=wargv[i];
  440. if(!SetParam(&wszSubjectKey, p))
  441. {
  442. if(TRUE==fUseSubjectPvkFile)
  443. IDSwprintf(hModule, IDS_ERR_SK_SV);
  444. goto BasicErr;
  445. }
  446. fUseSubjectKeyContainer=TRUE;
  447. fSubjectInformation=TRUE;
  448. continue;
  449. }
  450. if(IDSwcsicmp(hModule,p, IDS_OPTION_SQ)==0)
  451. {
  452. i++;
  453. p=wargv[i];
  454. if(!SetParam(&wszSubjectRequestFile, p))
  455. goto UndocumentedErr;
  456. continue;
  457. }
  458. if(IDSwcsicmp(hModule,p, IDS_OPTION_SV)==0)
  459. {
  460. i++;
  461. p=wargv[i];
  462. if(!SetParam(&wszSubjectKey, p))
  463. {
  464. if(TRUE==fUseSubjectKeyContainer)
  465. IDSwprintf(hModule, IDS_ERR_SK_SV);
  466. goto ExtendedErr;
  467. }
  468. fSubjectInformation=TRUE;
  469. fUseSubjectPvkFile=TRUE;
  470. continue;
  471. }
  472. if(IDSwcsicmp(hModule,p, IDS_OPTION_SC)==0)
  473. {
  474. i++;
  475. p=wargv[i];
  476. if(!SetParam(&wszSubjectCertFile, p))
  477. goto ExtendedErr;
  478. fSubjectInformation=TRUE;
  479. continue;
  480. }
  481. if(IDSwcsicmp(hModule,p, IDS_OPTION_SS)==0)
  482. {
  483. i++;
  484. p=wargv[i];
  485. if(!SetParam(&wszSubjectStore, p))
  486. goto BasicErr;
  487. continue;
  488. }
  489. if(IDSwcsicmp(hModule,p, IDS_OPTION_SR)==0)
  490. {
  491. i++;
  492. p=wargv[i];
  493. if(!SetParam(&wszSubjectStoreLocation, p))
  494. goto BasicErr;
  495. continue;
  496. }
  497. if(IDSwcsicmp(hModule,p, IDS_OPTION_N)==0)
  498. {
  499. i++;
  500. p=wargv[i];
  501. if(!SetParam(&wszSubjectX500Name, p))
  502. goto BasicErr;
  503. fSetSubjectName = TRUE;
  504. continue;
  505. }
  506. if(IDSwcsicmp(hModule,p, IDS_OPTION_IP)==0)
  507. {
  508. i++;
  509. p=wargv[i];
  510. if(!SetParam(&wszIssuerProviderName, p))
  511. goto ExtendedErr;
  512. fIssuerInformation = TRUE;
  513. continue;
  514. }
  515. if(IDSwcsicmp(hModule,p, IDS_OPTION_IY)==0)
  516. {
  517. i++;
  518. p=wargv[i];
  519. if(NULL==p)
  520. goto ExtendedErr;
  521. dwIssuerProviderType=_wtol(p);
  522. fIssuerInformation = TRUE;
  523. continue;
  524. }
  525. if(IDSwcsicmp(hModule,p, IDS_OPTION_SP)==0)
  526. {
  527. i++;
  528. p=wargv[i];
  529. if(!SetParam(&wszSubjectProviderName, p))
  530. goto ExtendedErr;
  531. fSubjectInformation=TRUE;
  532. continue;
  533. }
  534. if(IDSwcsicmp(hModule,p, IDS_OPTION_SY)==0)
  535. {
  536. i++;
  537. p=wargv[i];
  538. if(NULL==p)
  539. goto ExtendedErr;
  540. dwSubjectProviderType=_wtol(p);
  541. fSubjectInformation=TRUE;
  542. continue;
  543. }
  544. if(IDSwcsicmp(hModule,p, IDS_OPTION_IK)==0)
  545. {
  546. i++;
  547. p=wargv[i];
  548. if(!SetParam(&wszIssuerKey, p))
  549. goto ExtendedErr;
  550. fIssuerInformation = TRUE;
  551. continue;
  552. }
  553. if(IDSwcsicmp(hModule,p, IDS_OPTION_IV)==0)
  554. {
  555. i++;
  556. p=wargv[i];
  557. if(!SetParam(&wszIssuerKey, p))
  558. goto ExtendedErr;
  559. fUseIssuerPvkFile=TRUE;
  560. fIssuerInformation = TRUE;
  561. continue;
  562. }
  563. if(IDSwcsicmp(hModule,p, IDS_OPTION_IS)==0)
  564. {
  565. i++;
  566. p=wargv[i];
  567. if(!SetParam(&wszIssuerStore, p))
  568. goto ExtendedErr;
  569. fIssuerInformation = TRUE;
  570. continue;
  571. }
  572. if(IDSwcsicmp(hModule,p, IDS_OPTION_IR)==0)
  573. {
  574. i++;
  575. p=wargv[i];
  576. if(!SetParam(&wszIssuerStoreLocation,p))
  577. goto ExtendedErr;
  578. fIssuerInformation = TRUE;
  579. continue;
  580. }
  581. if(IDSwcsicmp(hModule,p, IDS_OPTION_IN)==0)
  582. {
  583. i++;
  584. p=wargv[i];
  585. if(!SetParam(&wszIssuerCertName,p))
  586. goto ExtendedErr;
  587. fIssuerInformation = TRUE;
  588. continue;
  589. }
  590. if(IDSwcsicmp(hModule,p, IDS_OPTION_IC)==0)
  591. {
  592. i++;
  593. p=wargv[i];
  594. if(!SetParam(&wszIssuerCertFile, p))
  595. goto ExtendedErr;
  596. fIssuerInformation = TRUE;
  597. continue;
  598. }
  599. if(IDSwcsicmp(hModule,p, IDS_OPTION_L)==0)
  600. {
  601. i++;
  602. p=wargv[i];
  603. if(!SetParam(&wszPolicyLink, p))
  604. goto ExtendedErr;
  605. continue;
  606. }
  607. if(IDSwcsicmp(hModule,p, IDS_OPTION_SKY)==0)
  608. {
  609. i++;
  610. p=wargv[i];
  611. if(!SetParam(&wszSubjectKeyType, p))
  612. goto ExtendedErr;
  613. fSubjectInformation=TRUE;
  614. continue;
  615. }
  616. if(IDSwcsicmp(hModule,p, IDS_OPTION_IKY)==0)
  617. {
  618. i++;
  619. p=wargv[i];
  620. if(!SetParam(&wszIssuerKeyType, p))
  621. goto ExtendedErr;
  622. fIssuerInformation = TRUE;
  623. continue;
  624. }
  625. if(IDSwcsicmp(hModule,p, IDS_OPTION_ALGO)==0)
  626. {
  627. i++;
  628. p=wargv[i];
  629. if(!SetParam(&wszAlgorithm, p))
  630. goto ExtendedErr;
  631. continue;
  632. }
  633. if (IDSwcsicmp(hModule,p, IDS_OPTION_ENHKEY_USAGE)==0)
  634. {
  635. i++;
  636. p=wargv[i];
  637. if (!SetParam(&wszEKUOids, p))
  638. goto ExtendedErr;
  639. continue;
  640. }
  641. if(IDSwcsicmp(hModule,p, IDS_OPTION_NSCP)==0)
  642. {
  643. fNetscapeClientAuth = TRUE;
  644. continue;
  645. }
  646. if(IDSwcsicmp(hModule,p, IDS_OPTION_NOPUBVERIFY)==0)
  647. {
  648. fNoVerifyPublic = TRUE;
  649. continue;
  650. }
  651. if(IDSwcsicmp(hModule,p, IDS_OPTION_EXTENDED)==0)
  652. {
  653. //display extended options
  654. goto ExtendedErr;
  655. }
  656. if(IDSwcsicmp(hModule,p, IDS_OPTION_TEST)==0)
  657. {
  658. //display extended options
  659. goto UndocumentedErr;
  660. }
  661. if(IDSwcsicmp(hModule,p, IDS_OPTION_NOPUBKEYPARA)==0)
  662. {
  663. fNoPubKeyPara = TRUE;
  664. continue;
  665. }
  666. if(IDSwcsicmp(hModule,p, IDS_OPTION_DH_PARA)==0)
  667. {
  668. i++;
  669. p=wargv[i];
  670. if(!SetParam(&wszDhParaCertFile, p))
  671. goto UndocumentedErr;
  672. continue;
  673. }
  674. if(IDSwcsicmp(hModule,p, IDS_OPTION_KEY_LEN)==0)
  675. {
  676. i++;
  677. p=wargv[i];
  678. if(NULL==p)
  679. goto UndocumentedErr;
  680. dwKeyBitLen=_wtol(p);
  681. continue;
  682. }
  683. if(IDSwcsicmp(hModule,p, IDS_OPTION_PE)==0)
  684. {
  685. fPrivateKeyExportable=TRUE;
  686. continue;
  687. }
  688. //display basic options
  689. goto BasicErr;
  690. }
  691. //Only change container name if request private key
  692. //to be exportable. This way we maintain backward
  693. //compatibility, and allow user to request private
  694. //key to be marked as exportable.
  695. //Note: If the private key is not marked as exportable,
  696. // the hardcoded container name, "JoeSoft", is
  697. // always used, which means more than one cert
  698. // can share the same key pair.
  699. //Note2: If the user specifies the container name, use that one instead
  700. if (fPrivateKeyExportable && (wszSubjectKey == NULL))
  701. {
  702. UUID uuidContainerName;
  703. RPC_STATUS rpcs;
  704. rpcs = UuidCreate(&uuidContainerName);
  705. if ((rpcs != RPC_S_OK) &&
  706. (rpcs != RPC_S_UUID_LOCAL_ONLY) &&
  707. (rpcs != RPC_S_UUID_NO_ADDRESS))
  708. {
  709. IDSwprintf(hModule, IDS_ERR_PE_CONTAINER);
  710. goto BasicErr;
  711. }
  712. if (RPC_S_OK != UuidToStringU(&uuidContainerName, &wszSubjectKey))
  713. {
  714. IDSwprintf(hModule, IDS_ERR_PE_CONTAINER);
  715. goto BasicErr;
  716. }
  717. }
  718. //make sure the either output file or the subject' cert store is set
  719. if((wszOutputFile==NULL) && (wszSubjectStore==NULL))
  720. {
  721. IDSwprintf(hModule, IDS_ERR_NO_OUTPUT);
  722. goto BasicErr;
  723. }
  724. //set the authority
  725. if(wszAuthority)
  726. {
  727. if(IDSwcsicmp(hModule,wszAuthority, IDS_OPTION_AUTH_IND) == 0)
  728. fCertIndividual = TRUE;
  729. else
  730. {
  731. if(IDSwcsicmp(hModule,wszAuthority, IDS_OPTION_AUTH_COM) == 0)
  732. fCertCommercial = TRUE;
  733. else
  734. {
  735. IDSwprintf(hModule,IDS_ERR_NO_AUTH);
  736. goto BasicErr;
  737. }
  738. }
  739. }
  740. //set the algorithm
  741. if(wszAlgorithm)
  742. {
  743. if(IDSwcsicmp(hModule,wszAlgorithm, IDS_OPTION_ALGO_SHA) == 0)
  744. algidHash = CALG_SHA;
  745. else
  746. {
  747. if(IDSwcsicmp(hModule,wszAlgorithm, IDS_OPTION_ALGO_MD5) == 0)
  748. algidHash = CALG_MD5;
  749. else
  750. {
  751. IDSwprintf(hModule,IDS_ERR_NO_ALGO);
  752. goto ExtendedErr;
  753. }
  754. }
  755. }
  756. //set the cert type
  757. if(wszCertType)
  758. {
  759. if(IDSwcsicmp(hModule,wszCertType, IDS_OPTION_CY_END) == 0)
  760. certTypes |= CERT_END_ENTITY_SUBJECT_FLAG;
  761. else
  762. {
  763. if(IDSwcsicmp(hModule,wszCertType, IDS_OPTION_CY_AUTH) == 0)
  764. certTypes |= CERT_CA_SUBJECT_FLAG;
  765. else
  766. {
  767. IDSwprintf(hModule,IDS_ERR_NO_CY);
  768. goto ExtendedErr;
  769. }
  770. }
  771. }
  772. //set the issuer key type
  773. if(wszIssuerKeyType)
  774. {
  775. if(IDSwcsicmp(hModule,wszIssuerKeyType, IDS_OPTION_KY_SIG) == 0)
  776. dwIssuerKeySpec = AT_SIGNATURE;
  777. else
  778. {
  779. if(IDSwcsicmp(hModule,wszIssuerKeyType, IDS_OPTION_KY_EXC) == 0)
  780. dwIssuerKeySpec = AT_KEYEXCHANGE;
  781. else
  782. dwIssuerKeySpec=_wtol(wszIssuerKeyType);
  783. }
  784. }
  785. //set the subject key type
  786. if(wszSubjectKeyType)
  787. {
  788. if(IDSwcsicmp(hModule,wszSubjectKeyType, IDS_OPTION_KY_SIG) == 0)
  789. dwKeySpec = AT_SIGNATURE;
  790. else
  791. {
  792. if(IDSwcsicmp(hModule,wszSubjectKeyType, IDS_OPTION_KY_EXC) == 0)
  793. dwKeySpec = AT_KEYEXCHANGE;
  794. else
  795. dwKeySpec=_wtol(wszSubjectKeyType);
  796. }
  797. }
  798. //determing the issuer store location
  799. if(wszIssuerStoreLocation)
  800. {
  801. if(IDSwcsicmp(hModule,wszIssuerStoreLocation, IDS_OPTION_CU) == 0)
  802. dwIssuerStoreFlag = CERT_SYSTEM_STORE_CURRENT_USER;
  803. else
  804. {
  805. if(IDSwcsicmp(hModule,wszIssuerStoreLocation, IDS_OPTION_LM) == 0)
  806. dwIssuerStoreFlag = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  807. else
  808. {
  809. IDSwprintf(hModule,IDS_ERR_NO_IR);
  810. goto ExtendedErr;
  811. }
  812. }
  813. }
  814. //determind the subject store location
  815. if(wszSubjectStoreLocation)
  816. {
  817. if(IDSwcsicmp(hModule,wszSubjectStoreLocation, IDS_OPTION_CU) == 0)
  818. dwSubjectStoreFlag = CERT_SYSTEM_STORE_CURRENT_USER;
  819. else
  820. {
  821. if(IDSwcsicmp(hModule,wszSubjectStoreLocation, IDS_OPTION_LM) == 0)
  822. dwSubjectStoreFlag = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  823. else
  824. {
  825. IDSwprintf(hModule,IDS_ERR_NO_IR);
  826. goto BasicErr;
  827. }
  828. }
  829. }
  830. //wszIssuerStore and wszIssuerKey can not be set at the same time
  831. if(wszIssuerKey || wszIssuerProviderName || wszIssuerKeyType)
  832. {
  833. if(wszIssuerStore || wszIssuerCertName)
  834. {
  835. //remind user that -ik, -iv, -ip can not be
  836. //set with -is, -in options
  837. IDSwprintf(hModule,IDS_ERR_TOO_MANY_STORE_KEY);
  838. goto ExtendedErr;
  839. }
  840. }
  841. //wszCertFile and wszCertName can not be set at the same time
  842. if(wszIssuerCertFile && wszIssuerCertName)
  843. {
  844. IDSwprintf(hModule, IDS_ERR_CERT_FILE_NAME);
  845. goto ExtendedErr;
  846. }
  847. //is wszIsserCertFile is NULL
  848. if(wszIssuerCertFile==NULL)
  849. {
  850. //we init wszIssuerKey to "MakeCertRoot" if there is no store
  851. //information
  852. if(wszIssuerStore==NULL)
  853. {
  854. if(wszIssuerKey)
  855. {
  856. //if wszIssuerKey is set, we have to set the IssuerCertFile
  857. IDSwprintf(hModule, IDS_ERR_NO_ISSUER_CER_FILE);
  858. goto ExtendedErr;
  859. }
  860. else
  861. {
  862. wszIssuerKey=wszMakeCertRoot;
  863. }
  864. }
  865. }
  866. else
  867. {
  868. //either wszIssuerStore or wszIssuerKey should be set
  869. if((!wszIssuerStore) && (!wszIssuerKey))
  870. {
  871. IDSwprintf(hModule, IDS_ERR_EITHER_STORE_OR_KEY);
  872. goto ExtendedErr;
  873. }
  874. }
  875. //for self signed certificate, user should not supply
  876. //issuer information
  877. if(fIssuerInformation && fSelfSigned)
  878. {
  879. IDSwprintf(hModule, IDS_NO_ISSUER_FOR_SELF_SIGNED);
  880. goto ExtendedErr;
  881. }
  882. //user can not request a self signed certificate with
  883. //a PKCS10 file. We neither generate or have access
  884. //to the private key
  885. if(fSelfSigned && wszSubjectRequestFile)
  886. {
  887. IDSwprintf(hModule, IDS_NO_PKCS10_AND_SELF_SIGNED);
  888. goto ExtendedErr;
  889. }
  890. if(fSubjectInformation && wszSubjectRequestFile)
  891. {
  892. IDSwprintf(hModule, IDS_NO_PKCS10_AND_SUBJECT_PVK);
  893. goto ExtendedErr;
  894. }
  895. //for self signed certificate, copy the provider type
  896. //to the issuer so that the signatureAlgObjID will
  897. //be corrrect
  898. if(fSelfSigned)
  899. dwIssuerProviderType = dwSubjectProviderType;
  900. // Set the signature and public key algorithm parameters
  901. if (PROV_DSS == dwIssuerProviderType ||
  902. PROV_DSS_DH == dwIssuerProviderType)
  903. szSignatureAlgObjId = szOID_X957_SHA1DSA;
  904. else if (algidHash == CALG_SHA)
  905. szSignatureAlgObjId = szOID_OIWSEC_sha1RSASign;
  906. else
  907. szSignatureAlgObjId = szOID_RSA_MD5RSA;
  908. return TRUE;
  909. BasicErr:
  910. BasicUsage();
  911. return FALSE;
  912. ExtendedErr:
  913. ExtendedUsage();
  914. return FALSE;
  915. UndocumentedErr:
  916. UndocumentedUsage();
  917. return FALSE;
  918. }
  919. static BOOL MakeCert();
  920. //+-------------------------------------------------------------------------
  921. // Check if creating a self signed certificate
  922. //--------------------------------------------------------------------------
  923. static BOOL IsSelfSignedCert()
  924. {
  925. return fSelfSigned;
  926. }
  927. //--------------------------------------------------------------------------
  928. //
  929. // wmain
  930. //
  931. //--------------------------------------------------------------------------
  932. extern "C" int __cdecl wmain(int argc, WCHAR ** wargv)
  933. {
  934. int status = 0;
  935. //get the module handle
  936. if(!InitModule())
  937. return -1;
  938. //load the string for Glue cert attribute
  939. if(!LoadStringU(hModule, IDS_GLUE,wszGlue, sizeof(wszGlue)/sizeof(wszGlue[0])))
  940. return -1;
  941. //load the string for wszSubjectKey and wszSubjectX500Name
  942. if(!LoadStringU(hModule, IDS_JOE_SOFT,
  943. wszKey, sizeof(wszKey)/sizeof(wszKey[0]))
  944. || !LoadStringU(hModule, IDS_JOE_NAME,
  945. wszName, sizeof(wszName)/sizeof(wszName[0]))
  946. || !LoadStringU(hModule, IDS_MAKECERT_ROOT,
  947. wszMakeCertRoot, sizeof(wszMakeCertRoot)/sizeof(wszMakeCertRoot[0]))
  948. || !LoadStringU(hModule, IDS_PLUS,
  949. wszPlus, sizeof(wszPlus)/sizeof(wszPlus[0]))
  950. || !LoadStringU(hModule, IDS_ROOT,
  951. wszRoot, sizeof(wszRoot)/sizeof(wszRoot[0]))
  952. )
  953. return -1;
  954. LoadStringU(hModule, IDS_NULL,
  955. wszNULL, sizeof(wszNULL)/sizeof(wszNULL[0]));
  956. // Parse the command line
  957. if (!ParseCommandLine(argc, wargv))
  958. {
  959. return -1;
  960. }
  961. //init wszSubjectKey and wszSubjectX500Name
  962. if(wszSubjectKey==NULL)
  963. wszSubjectKey=wszKey;
  964. if(wszSubjectX500Name==NULL)
  965. wszSubjectX500Name=wszName;
  966. if (FAILED(CoInitialize(NULL)))
  967. {
  968. IDSwprintf(hModule,IDS_ERR_COINIT);
  969. return -1;
  970. }
  971. // Get to work and make the certificate
  972. if (!MakeCert())
  973. {
  974. CoUninitialize();
  975. goto ErrorReturn;
  976. }
  977. //print out the success information
  978. IDSwprintf(hModule,IDS_SUCCEEDED);
  979. CommonReturn:
  980. CoUninitialize();
  981. return status;
  982. ErrorReturn:
  983. status = -1;
  984. IDSwprintf(hModule,IDS_ERR_FAILED);
  985. goto CommonReturn;
  986. }
  987. //+=========================================================================
  988. // MakeCert support functions
  989. //==========================================================================
  990. static BOOL IsRootKey();
  991. static PCCERT_CONTEXT GetRootCertContext();
  992. static HCRYPTPROV GetRootProv(OUT LPWSTR *ppwszTmpContainer);
  993. static PCCERT_CONTEXT GetIssuerCertContext();
  994. static BOOL VerifyIssuerKey(
  995. IN HCRYPTPROV hProv,
  996. IN PCERT_PUBLIC_KEY_INFO pIssuerKeyInfo
  997. );
  998. static HCRYPTPROV GetIssuerProv(OUT LPWSTR *ppwszTmpContainer);
  999. static HCRYPTPROV GetSubjectProv(OUT LPWSTR *ppwszTmpContainer);
  1000. static HCRYPTPROV GetProvFromStore(IN LPWSTR pwszStoreName);
  1001. static BOOL GetPublicKey(
  1002. HCRYPTPROV hProv,
  1003. PCERT_PUBLIC_KEY_INFO *ppPubKeyInfo
  1004. );
  1005. static BOOL GetSubject(
  1006. OUT PCCERT_CONTEXT *ppCertContext,
  1007. OUT BYTE **ppbEncodedName,
  1008. OUT DWORD *pcbEncodedName
  1009. );
  1010. static BOOL GetRequestInfo(
  1011. OUT PCERT_REQUEST_INFO *ppStuff);
  1012. static BOOL EncodeSubject(
  1013. OUT BYTE **ppbEncoded,
  1014. IN OUT DWORD *pcbEncoded
  1015. );
  1016. static BOOL SignAndEncodeCert(
  1017. HCRYPTPROV hProv,
  1018. PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
  1019. BYTE *pbToBeSigned,
  1020. DWORD cbToBeSigned,
  1021. BYTE **ppbEncoded,
  1022. DWORD *pcbEncoded
  1023. );
  1024. static BOOL CreateAuthorityKeyId(
  1025. IN HCRYPTPROV hProv,
  1026. PCERT_INFO pIssuerCert,
  1027. OUT BYTE **ppbEncoded,
  1028. IN OUT DWORD *pcbEncoded
  1029. );
  1030. static BOOL CreateSpcSpAgency(
  1031. OUT BYTE **ppbEncoded,
  1032. IN OUT DWORD *pcbEncoded
  1033. );
  1034. static BOOL CreateEnhancedKeyUsage(
  1035. OUT BYTE **ppbEncoded,
  1036. IN OUT DWORD *pcbEncoded
  1037. );
  1038. static BOOL CreateKeyUsage(
  1039. OUT BYTE **ppbEncoded,
  1040. IN OUT DWORD *pcbEncoded
  1041. );
  1042. static BOOL CreateBasicConstraints(
  1043. OUT BYTE **ppbEncoded,
  1044. IN OUT DWORD *pcbEncoded
  1045. );
  1046. static void BytesToWStr(ULONG cb, void* pv, LPWSTR wsz);
  1047. BOOL SaveCertToStore(HCRYPTPROV hProv,
  1048. DWORD dwEncodingType,
  1049. LPWSTR wszStore,
  1050. DWORD dwFlag,
  1051. BYTE *pbEncodedCert,
  1052. DWORD cbEncodedCert,
  1053. LPWSTR wszPvk,
  1054. BOOL fPvkFile,
  1055. DWORD dwKeySpecification,
  1056. LPWSTR wszCapiProv,
  1057. DWORD dwCapiProvType);
  1058. PCCERT_CONTEXT GetIssuerCertAndStore(HCERTSTORE *phCertStore, BOOL *pfMore);
  1059. HRESULT GetCertHashFromFile(LPWSTR pwszCertFile,
  1060. BYTE **ppHash,
  1061. DWORD *pcbHash,
  1062. BOOL *pfMore);
  1063. BOOL EmptySubject(CERT_NAME_BLOB *pSubject);
  1064. BOOL GetExtensionsFromRequest(PCERT_REQUEST_INFO pReqInfo, DWORD *pdwCount, PCERT_EXTENSIONS **pprgExtensions);
  1065. //+=========================================================================
  1066. // Support functions to generate DH keys having the 'Q'parameter
  1067. //==========================================================================
  1068. static BOOL GenDhKey(
  1069. IN HCRYPTPROV hProv,
  1070. IN DWORD dwFlags
  1071. );
  1072. static BOOL UpdateDhPublicKey(
  1073. IN OUT PCERT_PUBLIC_KEY_INFO *ppPubKeyInfo
  1074. );
  1075. static BOOL IsDh3Csp();
  1076. //+-------------------------------------------------------------------------
  1077. // Make the subject certificate. If the subject doesn't have a private
  1078. // key, then, create.
  1079. //--------------------------------------------------------------------------
  1080. static BOOL MakeCert()
  1081. {
  1082. BOOL fResult;
  1083. HCRYPTPROV hIssuerProv = 0;
  1084. LPWSTR pwszTmpIssuerContainer = NULL;
  1085. BOOL fDidIssuerAcquire=FALSE;
  1086. LPWSTR pwszTmpIssuerProvName=NULL;
  1087. DWORD dwTmpIssuerProvType;
  1088. PCCERT_CONTEXT pIssuerCertContext = NULL;
  1089. HCERTSTORE hIssuerCertStore=NULL;
  1090. PCERT_INFO pIssuerCert =NULL; // not allocated
  1091. PCERT_REQUEST_INFO pReqInfo =NULL;
  1092. HCRYPTPROV hSubjectProv = 0;
  1093. LPWSTR pwszTmpSubjectContainer = NULL;
  1094. PCCERT_CONTEXT pSubjectCertContext = NULL;
  1095. DWORD dwRequestExtensions=0;
  1096. PCERT_EXTENSIONS *rgpRequestExtensions=NULL;
  1097. DWORD dwExtIndex=0;
  1098. DWORD dwPerExt=0;
  1099. DWORD dwExistExt=0;
  1100. PCERT_PUBLIC_KEY_INFO pSubjectPubKeyInfo = NULL; // not allocated
  1101. PCERT_PUBLIC_KEY_INFO pAllocSubjectPubKeyInfo = NULL;
  1102. BYTE *pbSubjectEncoded = NULL;
  1103. DWORD cbSubjectEncoded =0;
  1104. BYTE *pbKeyIdEncoded = NULL;
  1105. DWORD cbKeyIdEncoded =0;
  1106. BYTE *pbSerialNumber = NULL;
  1107. DWORD cbSerialNumber = 0;
  1108. BYTE *pbSpcSpAgencyEncoded = NULL;
  1109. DWORD cbSpcSpAgencyEncoded =0;
  1110. BYTE *pbSpcCommonNameEncoded = NULL;
  1111. DWORD cbSpcCommonNameEncoded =0;
  1112. BYTE *pbKeyUsageEncoded = NULL;
  1113. DWORD cbKeyUsageEncoded =0;
  1114. BYTE *pbFinancialCriteria = NULL;
  1115. DWORD cbFinancialCriteria =0;
  1116. BYTE *pbBasicConstraintsEncoded = NULL;
  1117. DWORD cbBasicConstraintsEncoded =0;
  1118. BYTE *pbCertEncoded = NULL;
  1119. DWORD cbCertEncoded =0;
  1120. BYTE *pbEKUEncoded = NULL;
  1121. DWORD cbEKUEncoded = 0;
  1122. CERT_INFO Cert;
  1123. GUID SerialNumber;
  1124. CERT_EXTENSION *rgExt=NULL;
  1125. DWORD dwExtAlloc=0;
  1126. DWORD cExt = 0;
  1127. CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = {
  1128. szSignatureAlgObjId, 0, 0
  1129. };
  1130. BYTE *pbIssuerEncoded; // not allocated
  1131. DWORD cbIssuerEncoded;
  1132. if (wszSubjectRequestFile)
  1133. {
  1134. if (!GetRequestInfo(&pReqInfo))
  1135. {
  1136. IDSwprintf(hModule,IDS_INVALID_REQUEST_FILE, wszSubjectRequestFile);
  1137. goto ErrorReturn;
  1138. }
  1139. pSubjectPubKeyInfo = &(pReqInfo->SubjectPublicKeyInfo);
  1140. if(!GetExtensionsFromRequest(pReqInfo, &dwRequestExtensions, &rgpRequestExtensions))
  1141. {
  1142. IDSwprintf(hModule,IDS_INVALID_ATTR_REQUEST_FILE, wszSubjectRequestFile);
  1143. goto ErrorReturn;
  1144. }
  1145. //if the subject informatin is empt or user has supplied the subject
  1146. //name through the command line, we use the command line options
  1147. if(fSetSubjectName || wszSubjectCertFile || EmptySubject(&(pReqInfo->Subject)))
  1148. {
  1149. if (wszSubjectCertFile)
  1150. {
  1151. // Get encoded subject name and public key from the subject cert
  1152. if (!GetSubject(&pSubjectCertContext,
  1153. &pbSubjectEncoded, &cbSubjectEncoded))
  1154. goto ErrorReturn;
  1155. }
  1156. else
  1157. {
  1158. // Encode the subject name
  1159. if (!EncodeSubject(&pbSubjectEncoded, &cbSubjectEncoded))
  1160. goto ErrorReturn;
  1161. }
  1162. }
  1163. else
  1164. {
  1165. cbSubjectEncoded = pReqInfo->Subject.cbData;
  1166. pbSubjectEncoded = (BYTE *) MakeCertAlloc(cbSubjectEncoded);
  1167. if(NULL == pbSubjectEncoded)
  1168. goto ErrorReturn;
  1169. memcpy(pbSubjectEncoded, pReqInfo->Subject.pbData, cbSubjectEncoded);
  1170. }
  1171. }
  1172. else
  1173. {
  1174. if (wszSubjectCertFile)
  1175. {
  1176. // Get encoded subject name and public key from the subject cert
  1177. if (!GetSubject(&pSubjectCertContext,
  1178. &pbSubjectEncoded, &cbSubjectEncoded))
  1179. goto ErrorReturn;
  1180. pSubjectPubKeyInfo = &pSubjectCertContext->pCertInfo->SubjectPublicKeyInfo;
  1181. pbSerialNumber = pSubjectCertContext->pCertInfo->SerialNumber.pbData;
  1182. cbSerialNumber = pSubjectCertContext->pCertInfo->SerialNumber.cbData;
  1183. }
  1184. else
  1185. {
  1186. //
  1187. // Get access to the subject's (public) key, creating it if necessary
  1188. //
  1189. if (0 == (hSubjectProv = GetSubjectProv(&pwszTmpSubjectContainer)))
  1190. goto ErrorReturn;
  1191. if (!GetPublicKey(hSubjectProv, &pAllocSubjectPubKeyInfo))
  1192. goto ErrorReturn;
  1193. pSubjectPubKeyInfo = pAllocSubjectPubKeyInfo;
  1194. //
  1195. // Encode the subject name
  1196. //
  1197. if (!EncodeSubject(&pbSubjectEncoded, &cbSubjectEncoded))
  1198. goto ErrorReturn;
  1199. }
  1200. }
  1201. //
  1202. // Get access to the issuer's (private) key
  1203. //
  1204. if( IsSelfSignedCert())
  1205. {
  1206. hIssuerProv=hSubjectProv;
  1207. dwIssuerKeySpec=dwKeySpec;
  1208. pbIssuerEncoded = pbSubjectEncoded;
  1209. cbIssuerEncoded = cbSubjectEncoded;
  1210. pIssuerCert = &Cert;
  1211. if (!VerifyIssuerKey(hIssuerProv, pSubjectPubKeyInfo))
  1212. goto ErrorReturn;
  1213. }
  1214. else
  1215. {
  1216. //get the hProv from the certificate store
  1217. if(wszIssuerStore)
  1218. {
  1219. BOOL fMore=FALSE;
  1220. pwszTmpIssuerContainer=NULL;
  1221. //get the non-root private key set based on the store name
  1222. //first, get the certificate context from the cert store
  1223. if(NULL==(pIssuerCertContext=GetIssuerCertAndStore(
  1224. &hIssuerCertStore,
  1225. &fMore)))
  1226. {
  1227. if(fMore==FALSE)
  1228. IDSwprintf(hModule, IDS_ERR_NO_ISSUER_CERT,
  1229. wszIssuerStore);
  1230. else
  1231. IDSwprintf(hModule, IDS_ERR_MORE_ISSUER_CERT,
  1232. wszIssuerStore);
  1233. goto ErrorReturn;
  1234. }
  1235. //second, get the hProv from the certifcate context
  1236. if(!GetCryptProvFromCert(
  1237. NULL,
  1238. pIssuerCertContext,
  1239. &hIssuerProv,
  1240. &dwIssuerKeySpec,
  1241. &fDidIssuerAcquire,
  1242. &pwszTmpIssuerContainer,
  1243. &pwszTmpIssuerProvName,
  1244. &dwTmpIssuerProvType))
  1245. {
  1246. IDSwprintf(hModule, IDS_ERR_NO_PROV_FROM_CERT);
  1247. goto ErrorReturn;
  1248. }
  1249. }
  1250. else
  1251. {
  1252. if (0 == (hIssuerProv = GetIssuerProv(&pwszTmpIssuerContainer)))
  1253. goto ErrorReturn;
  1254. // Get the Issuer's Certificate
  1255. if (NULL == (pIssuerCertContext = GetIssuerCertContext()))
  1256. goto ErrorReturn;
  1257. }
  1258. // Verify the issuer's key. Its public key must match the one
  1259. // in the issuer's provider
  1260. //
  1261. pIssuerCert = pIssuerCertContext->pCertInfo;
  1262. if ((!fNoVerifyPublic) && (!VerifyIssuerKey(hIssuerProv, &pIssuerCert->SubjectPublicKeyInfo)))
  1263. goto ErrorReturn;
  1264. pbIssuerEncoded = pIssuerCert->Subject.pbData;
  1265. cbIssuerEncoded = pIssuerCert->Subject.cbData;
  1266. }
  1267. //
  1268. // Update the CERT_INFO
  1269. //
  1270. memset(&Cert, 0, sizeof(Cert));
  1271. Cert.dwVersion = CERT_V3;
  1272. if (0 != cbSerialNumber) {
  1273. Cert.SerialNumber.pbData = pbSerialNumber;
  1274. Cert.SerialNumber.cbData = cbSerialNumber;
  1275. } else if (fSetSerialNumber) {
  1276. Cert.SerialNumber.pbData = (BYTE *) &ulSerialNumber;
  1277. Cert.SerialNumber.cbData = sizeof(ulSerialNumber);
  1278. } else if (0 == Cert.SerialNumber.cbData) {
  1279. CoCreateGuid(&SerialNumber);
  1280. Cert.SerialNumber.pbData = (BYTE *) &SerialNumber;
  1281. Cert.SerialNumber.cbData = sizeof(SerialNumber);
  1282. }
  1283. Cert.SignatureAlgorithm = SignatureAlgorithm;
  1284. Cert.Issuer.pbData = pbIssuerEncoded;
  1285. Cert.Issuer.cbData = cbIssuerEncoded;
  1286. {
  1287. SYSTEMTIME st;
  1288. //decide NotBefore
  1289. // Let the user override the default validity endpoints
  1290. //
  1291. if (CompareFileTime(&g_ftNotBefore, &g_ftZero) != 0)
  1292. {
  1293. Cert.NotBefore = g_ftNotBefore;
  1294. }
  1295. else
  1296. {
  1297. // Default validity: now through end of 2039
  1298. GetSystemTimeAsFileTime(&Cert.NotBefore);
  1299. }
  1300. //decide NotAfter
  1301. if (CompareFileTime(&g_ftNotAfter, &g_ftZero) != 0)
  1302. {
  1303. Cert.NotAfter = g_ftNotAfter;
  1304. }
  1305. else
  1306. {
  1307. memset(&st, 0, sizeof(st));
  1308. st.wYear = 2039;
  1309. st.wMonth = 12;
  1310. st.wDay = 31;
  1311. st.wHour = 23;
  1312. st.wMinute= 59;
  1313. st.wSecond= 59;
  1314. SystemTimeToFileTime(&st, &Cert.NotAfter);
  1315. }
  1316. //add the number of months
  1317. if (nMonths >= 0)
  1318. {
  1319. //if the user has specified NotAfter with -E switch, error
  1320. if(CompareFileTime(&g_ftNotAfter, &g_ftZero) != 0)
  1321. goto ErrorReturn;
  1322. if (nMonths > 0)
  1323. {
  1324. FILETIME tempFT;
  1325. DWORD dwMonth;
  1326. SYSTEMTIME tempST;
  1327. BOOL fFirstDayOfMonth;
  1328. //
  1329. // Cert.NotBefore is stored as UTC, but the user has entered
  1330. // nMonths based on local time, so convert to local time, then:
  1331. // NotAfter = (NotBefore - 1 second) + nMonths
  1332. //
  1333. if (!FileTimeToLocalFileTime(&Cert.NotBefore, &tempFT))
  1334. goto ErrorReturn;
  1335. //
  1336. // if the day is the first day of the month, then subtract
  1337. // one second after the months are added to the NotBefore
  1338. // time instead of before the months are added, otherwise
  1339. // we could end up with the wrong ending date.
  1340. //
  1341. if (FileTimeToSystemTime(&tempFT, &tempST)) {
  1342. fFirstDayOfMonth = (tempST.wDay == 1);
  1343. }
  1344. else {
  1345. goto ErrorReturn;
  1346. }
  1347. // Subtract one second from the starting date, and then
  1348. // add the number of months to that time
  1349. //
  1350. // FILETIME is in units of 100 nanoseconds (10**-7)
  1351. if (!fFirstDayOfMonth) {
  1352. unsigned __int64* pli = (unsigned __int64*) &tempFT;
  1353. *pli -= 10000000; // ten million
  1354. }
  1355. if (!FileTimeToSystemTime(&tempFT, &st))
  1356. goto ErrorReturn;
  1357. dwMonth = (DWORD) nMonths + st.wMonth;
  1358. while (dwMonth > 12)
  1359. {
  1360. dwMonth -= 12;
  1361. st.wYear += 1;
  1362. }
  1363. st.wMonth = (WORD) dwMonth;
  1364. //
  1365. // This loop is because the ending month may not have as
  1366. // many days as the starting month... so the initial
  1367. // ending day may not even exist, thus, loop until we
  1368. // find one that does or we go below 28 (no month ever has
  1369. // less than 28 days)
  1370. //
  1371. while(!SystemTimeToFileTime(&st, &tempFT)) {
  1372. if(st.wDay >= 29 )
  1373. st.wDay--;
  1374. else
  1375. goto ErrorReturn;
  1376. }
  1377. //
  1378. // if first day of month then subtract our one second
  1379. // after month calculations
  1380. //
  1381. if (fFirstDayOfMonth) {
  1382. unsigned __int64* pli = (unsigned __int64*) &tempFT;
  1383. *pli -= 10000000; // ten million
  1384. }
  1385. if (!LocalFileTimeToFileTime(&tempFT, &Cert.NotAfter))
  1386. goto ErrorReturn;
  1387. }
  1388. else {
  1389. if (!FileTimeToSystemTime(&Cert.NotBefore, &st))
  1390. goto ErrorReturn;
  1391. if (!SystemTimeToFileTime(&st, &Cert.NotAfter))
  1392. goto ErrorReturn;
  1393. }
  1394. }
  1395. }
  1396. Cert.Subject.pbData = pbSubjectEncoded;
  1397. Cert.Subject.cbData = cbSubjectEncoded;
  1398. Cert.SubjectPublicKeyInfo = *pSubjectPubKeyInfo;
  1399. //allocate memory to hold all the extensions
  1400. dwExtAlloc = MAX_EXT_CNT;
  1401. for(dwExtIndex=0; dwExtIndex < dwRequestExtensions; dwExtIndex++)
  1402. dwExtAlloc += (rgpRequestExtensions[dwExtIndex])->cExtension;
  1403. rgExt = (CERT_EXTENSION *)MakeCertAlloc(dwExtAlloc * sizeof(CERT_EXTENSION));
  1404. if(NULL == rgExt)
  1405. goto ErrorReturn;
  1406. memset(rgExt, 0, dwExtAlloc * sizeof(CERT_EXTENSION));
  1407. cExt=0;
  1408. // Cert Extensions
  1409. if (fNetscapeClientAuth) {
  1410. // Set Netscape specific extensions
  1411. static BYTE rgXxxxData[] = { 0x30, 0x03, 0x02, 0x01, 0x00 };
  1412. rgExt[cExt].pszObjId = "2.5.29.19";
  1413. rgExt[cExt].fCritical = FALSE;
  1414. rgExt[cExt].Value.pbData = rgXxxxData;
  1415. rgExt[cExt].Value.cbData = sizeof(rgXxxxData);
  1416. cExt++;
  1417. static BYTE rgNscpData[] = { 0x03, 0x02, 0x07, 0x80 };
  1418. rgExt[cExt].pszObjId = "2.16.840.1.113730.1.1";
  1419. rgExt[cExt].fCritical = FALSE;
  1420. rgExt[cExt].Value.pbData = rgNscpData;
  1421. rgExt[cExt].Value.cbData = sizeof(rgNscpData);
  1422. cExt++;
  1423. }
  1424. if (pathLenConstraint >= 0 || certTypes) {
  1425. if (!CreateBasicConstraints(
  1426. &pbBasicConstraintsEncoded,
  1427. &cbBasicConstraintsEncoded))
  1428. goto ErrorReturn;
  1429. rgExt[cExt].pszObjId = szOID_BASIC_CONSTRAINTS2;
  1430. rgExt[cExt].fCritical = TRUE;
  1431. rgExt[cExt].Value.pbData = pbBasicConstraintsEncoded;
  1432. rgExt[cExt].Value.cbData = cbBasicConstraintsEncoded;
  1433. cExt++;
  1434. }
  1435. if (fCertCommercial || fCertIndividual) {
  1436. if (!CreateKeyUsage(
  1437. &pbKeyUsageEncoded,
  1438. &cbKeyUsageEncoded))
  1439. goto ErrorReturn;
  1440. rgExt[cExt].pszObjId = szOID_KEY_USAGE_RESTRICTION;
  1441. rgExt[cExt].fCritical = TRUE;
  1442. rgExt[cExt].Value.pbData = pbKeyUsageEncoded;
  1443. rgExt[cExt].Value.cbData = cbKeyUsageEncoded;
  1444. cExt++;
  1445. }
  1446. if (wszPolicyLink) {
  1447. if (!CreateSpcSpAgency(
  1448. &pbSpcSpAgencyEncoded,
  1449. &cbSpcSpAgencyEncoded))
  1450. goto ErrorReturn;
  1451. rgExt[cExt].pszObjId = SPC_SP_AGENCY_INFO_OBJID;
  1452. rgExt[cExt].fCritical = FALSE;
  1453. rgExt[cExt].Value.pbData = pbSpcSpAgencyEncoded;
  1454. rgExt[cExt].Value.cbData = cbSpcSpAgencyEncoded;
  1455. cExt++;
  1456. }
  1457. //if user has specified fCertCommercial or fCertIndividual,
  1458. //we add the code signing oid to the EKU extensions
  1459. if (wszEKUOids || fCertCommercial || fCertIndividual) {
  1460. if (!CreateEnhancedKeyUsage(
  1461. &pbEKUEncoded,
  1462. &cbEKUEncoded))
  1463. goto ErrorReturn;
  1464. rgExt[cExt].pszObjId = szOID_ENHANCED_KEY_USAGE;
  1465. rgExt[cExt].fCritical = FALSE;
  1466. rgExt[cExt].Value.pbData = pbEKUEncoded;
  1467. rgExt[cExt].Value.cbData = cbEKUEncoded;
  1468. cExt++;
  1469. }
  1470. if (!CreateAuthorityKeyId(
  1471. hIssuerProv,
  1472. pIssuerCert,
  1473. &pbKeyIdEncoded,
  1474. &cbKeyIdEncoded))
  1475. goto ErrorReturn;
  1476. rgExt[cExt].pszObjId = szOID_AUTHORITY_KEY_IDENTIFIER;
  1477. rgExt[cExt].fCritical = FALSE;
  1478. rgExt[cExt].Value.pbData = pbKeyIdEncoded;
  1479. rgExt[cExt].Value.cbData = cbKeyIdEncoded;
  1480. cExt++;
  1481. //we now combine the extension from the certificate request file.
  1482. //In case of duplication of extensions, the command line options
  1483. //have higher priority
  1484. for(dwExtIndex=0; dwExtIndex < dwRequestExtensions; dwExtIndex++)
  1485. {
  1486. for(dwPerExt=0; dwPerExt < rgpRequestExtensions[dwExtIndex]->cExtension; dwPerExt++)
  1487. {
  1488. for(dwExistExt=0; dwExistExt<cExt; dwExistExt++)
  1489. {
  1490. if(0 == strcmp(rgExt[dwExistExt].pszObjId,
  1491. (rgpRequestExtensions[dwExtIndex]->rgExtension[dwPerExt]).pszObjId))
  1492. break;
  1493. }
  1494. //we merge if this is a new extension
  1495. if(dwExistExt == cExt)
  1496. {
  1497. memcpy(&(rgExt[cExt]), &(rgpRequestExtensions[dwExtIndex]->rgExtension[dwPerExt]), sizeof(CERT_EXTENSION));
  1498. cExt++;
  1499. }
  1500. }
  1501. }
  1502. Cert.rgExtension = rgExt;
  1503. Cert.cExtension = cExt;
  1504. //
  1505. // Sign and encode the certificate
  1506. //
  1507. cbCertEncoded = 0;
  1508. CryptSignAndEncodeCertificate(
  1509. hIssuerProv,
  1510. dwIssuerKeySpec,
  1511. X509_ASN_ENCODING,
  1512. X509_CERT_TO_BE_SIGNED,
  1513. &Cert,
  1514. &Cert.SignatureAlgorithm,
  1515. NULL, // pvHashAuxInfo
  1516. NULL, // pbEncoded
  1517. &cbCertEncoded
  1518. );
  1519. if (cbCertEncoded == 0) {
  1520. PrintLastError(IDS_ERR_SIGN_ENCODE_CB);
  1521. goto ErrorReturn;
  1522. }
  1523. pbCertEncoded = (BYTE *) MakeCertAlloc(cbCertEncoded);
  1524. if (pbCertEncoded == NULL) goto ErrorReturn;
  1525. if (!CryptSignAndEncodeCertificate(
  1526. hIssuerProv,
  1527. dwIssuerKeySpec,
  1528. X509_ASN_ENCODING,
  1529. X509_CERT_TO_BE_SIGNED,
  1530. &Cert,
  1531. &Cert.SignatureAlgorithm,
  1532. NULL, // pvHashAuxInfo
  1533. pbCertEncoded,
  1534. &cbCertEncoded
  1535. )) {
  1536. PrintLastError(IDS_ERR_SIGN_ENCODE);
  1537. goto ErrorReturn;
  1538. }
  1539. //output the encoded certificate to an output file
  1540. if(wszOutputFile)
  1541. {
  1542. if (S_OK!=OpenAndWriteToFile(wszOutputFile, pbCertEncoded, cbCertEncoded))
  1543. {
  1544. PrintLastError(IDS_ERR_DESC_WRITE);
  1545. goto ErrorReturn;
  1546. }
  1547. }
  1548. //output the encoded certificate to an cerificate store
  1549. if(wszSubjectStore)
  1550. {
  1551. if((!SaveCertToStore(hSubjectProv, dwCertStoreEncodingType,
  1552. wszSubjectStore, dwSubjectStoreFlag,
  1553. pbCertEncoded, cbCertEncoded, wszSubjectKey, fUseSubjectPvkFile,
  1554. dwKeySpec, wszSubjectProviderName, dwSubjectProviderType)))
  1555. {
  1556. PrintLastError(IDS_ERR_DESC_SAVE_STORE);
  1557. goto ErrorReturn;
  1558. }
  1559. }
  1560. fResult = TRUE;
  1561. goto CommonReturn;
  1562. ErrorReturn:
  1563. fResult = FALSE;
  1564. CommonReturn:
  1565. if((!IsSelfSignedCert()) && hIssuerProv)
  1566. {
  1567. if(wszIssuerStore)
  1568. {
  1569. FreeCryptProvFromCert(fDidIssuerAcquire,
  1570. hIssuerProv,
  1571. pwszTmpIssuerProvName,
  1572. dwTmpIssuerProvType,
  1573. pwszTmpIssuerContainer);
  1574. }
  1575. else
  1576. {
  1577. PvkFreeCryptProv(hIssuerProv, wszIssuerProviderName,
  1578. dwIssuerProviderType, pwszTmpIssuerContainer);
  1579. }
  1580. }
  1581. PvkFreeCryptProv(hSubjectProv, wszSubjectProviderName,
  1582. dwSubjectProviderType,pwszTmpSubjectContainer);
  1583. if (pIssuerCertContext)
  1584. CertFreeCertificateContext(pIssuerCertContext);
  1585. if(hIssuerCertStore)
  1586. CertCloseStore(hIssuerCertStore, 0);
  1587. if (pSubjectCertContext)
  1588. CertFreeCertificateContext(pSubjectCertContext);
  1589. //pReqInfo is allocated via CryptQueryObject
  1590. if (pReqInfo)
  1591. LocalFree((HLOCAL)pReqInfo);
  1592. if (pAllocSubjectPubKeyInfo)
  1593. MakeCertFree(pAllocSubjectPubKeyInfo);
  1594. if (pbSubjectEncoded)
  1595. MakeCertFree(pbSubjectEncoded);
  1596. if (pbKeyIdEncoded)
  1597. MakeCertFree(pbKeyIdEncoded);
  1598. if (pbSpcSpAgencyEncoded)
  1599. MakeCertFree(pbSpcSpAgencyEncoded);
  1600. if (pbEKUEncoded)
  1601. MakeCertFree(pbEKUEncoded);
  1602. if (pbSpcCommonNameEncoded)
  1603. MakeCertFree(pbSpcCommonNameEncoded);
  1604. if (pbKeyUsageEncoded)
  1605. MakeCertFree(pbKeyUsageEncoded);
  1606. if (pbFinancialCriteria)
  1607. MakeCertFree(pbFinancialCriteria);
  1608. if (pbBasicConstraintsEncoded)
  1609. MakeCertFree(pbBasicConstraintsEncoded);
  1610. if (pbCertEncoded)
  1611. MakeCertFree(pbCertEncoded);
  1612. if (rgpRequestExtensions)
  1613. {
  1614. for(dwExtIndex=0; dwExtIndex<dwRequestExtensions; dwExtIndex++)
  1615. {
  1616. if(rgpRequestExtensions[dwExtIndex])
  1617. MakeCertFree(rgpRequestExtensions[dwExtIndex]);
  1618. }
  1619. MakeCertFree(rgpRequestExtensions);
  1620. }
  1621. if (rgExt)
  1622. MakeCertFree(rgExt);
  1623. return fResult;
  1624. }
  1625. //+-------------------------------------------------------------------------
  1626. // save the certificate to a certificate store. Attach private key information
  1627. // to the certificate
  1628. //--------------------------------------------------------------------------
  1629. BOOL SaveCertToStore(
  1630. HCRYPTPROV hProv, DWORD dwEncodingType,
  1631. LPWSTR wszStore, DWORD dwFlag,
  1632. BYTE *pbEncodedCert, DWORD cbEncodedCert,
  1633. LPWSTR wszPvk, BOOL fPvkFile,
  1634. DWORD dwKeySpecification,
  1635. LPWSTR wszCapiProv, DWORD dwCapiProvType)
  1636. {
  1637. BOOL fResult=FALSE;
  1638. HCERTSTORE hStore=NULL;
  1639. PCCERT_CONTEXT pCertContext=NULL;
  1640. CRYPT_KEY_PROV_INFO KeyProvInfo;
  1641. CRYPT_DATA_BLOB dataBlob;
  1642. DWORD cwchar;
  1643. LPWSTR pwszPvkProperty=NULL;
  1644. HRESULT hr=S_OK;
  1645. HCRYPTPROV hDefaultProvName=NULL;
  1646. DWORD cbData=0;
  1647. LPSTR pszName=NULL;
  1648. LPWSTR pwszName=NULL;
  1649. //init
  1650. memset(&KeyProvInfo, 0, sizeof(CRYPT_KEY_PROV_INFO));
  1651. //open a cert store
  1652. hStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  1653. dwEncodingType,
  1654. hProv,
  1655. CERT_STORE_NO_CRYPT_RELEASE_FLAG|dwFlag,
  1656. wszStore);
  1657. if(hStore==NULL)
  1658. goto CLEANUP;
  1659. //add the encoded certificate to store
  1660. if(!CertAddEncodedCertificateToStore(
  1661. hStore,
  1662. X509_ASN_ENCODING,
  1663. pbEncodedCert,
  1664. cbEncodedCert,
  1665. CERT_STORE_ADD_REPLACE_EXISTING,
  1666. &pCertContext))
  1667. goto CLEANUP;
  1668. //if user has specified a request file, there is no need to
  1669. //add the private key property
  1670. if(wszSubjectRequestFile)
  1671. {
  1672. fResult = TRUE;
  1673. goto CLEANUP;
  1674. }
  1675. //add properties to the certificate
  1676. KeyProvInfo.pwszContainerName=wszPvk;
  1677. KeyProvInfo.pwszProvName=wszCapiProv,
  1678. KeyProvInfo.dwProvType=dwCapiProvType,
  1679. KeyProvInfo.dwKeySpec=dwKeySpecification;
  1680. //if wszCapiProv is NULL, we get the default provider name
  1681. if(NULL==wszCapiProv)
  1682. {
  1683. //get the default provider
  1684. if(CryptAcquireContext(&hDefaultProvName,
  1685. NULL,
  1686. NULL,
  1687. KeyProvInfo.dwProvType,
  1688. CRYPT_VERIFYCONTEXT))
  1689. {
  1690. //get the provider name
  1691. if(CryptGetProvParam(hDefaultProvName,
  1692. PP_NAME,
  1693. NULL,
  1694. &cbData,
  1695. 0) && (0!=cbData))
  1696. {
  1697. if(pszName=(LPSTR)MakeCertAlloc(cbData))
  1698. {
  1699. if(CryptGetProvParam(hDefaultProvName,
  1700. PP_NAME,
  1701. (BYTE *)pszName,
  1702. &cbData,
  1703. 0))
  1704. {
  1705. pwszName=MkWStr(pszName);
  1706. KeyProvInfo.pwszProvName=pwszName;
  1707. }
  1708. }
  1709. }
  1710. }
  1711. }
  1712. //free the provider as we want
  1713. if(hDefaultProvName)
  1714. CryptReleaseContext(hDefaultProvName, 0);
  1715. hDefaultProvName=NULL;
  1716. if(fPvkFile)
  1717. {
  1718. //add the property related to private key file
  1719. if(S_OK != (hr=ComposePvkString(&KeyProvInfo,
  1720. &pwszPvkProperty,
  1721. &cwchar)))
  1722. {
  1723. SetLastError(hr);
  1724. goto CLEANUP;
  1725. }
  1726. //set up
  1727. dataBlob.cbData=cwchar*sizeof(WCHAR);
  1728. dataBlob.pbData=(BYTE *)pwszPvkProperty;
  1729. if(!CertSetCertificateContextProperty(
  1730. pCertContext,
  1731. CERT_PVK_FILE_PROP_ID,
  1732. 0,
  1733. &dataBlob))
  1734. goto CLEANUP;
  1735. }
  1736. else
  1737. {
  1738. if (dwSubjectStoreFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE)
  1739. KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
  1740. //add property related to the key container
  1741. if(!CertSetCertificateContextProperty(
  1742. pCertContext,
  1743. CERT_KEY_PROV_INFO_PROP_ID,
  1744. 0,
  1745. &KeyProvInfo))
  1746. goto CLEANUP;
  1747. }
  1748. fResult=TRUE;
  1749. CLEANUP:
  1750. //free the cert context
  1751. if(pCertContext)
  1752. CertFreeCertificateContext(pCertContext);
  1753. //free the cert store
  1754. if(hStore)
  1755. CertCloseStore(hStore, 0);
  1756. if(pwszPvkProperty)
  1757. MakeCertFree(pwszPvkProperty);
  1758. if(pszName)
  1759. MakeCertFree(pszName);
  1760. if(pwszName)
  1761. FreeWStr(pwszName);
  1762. if(hDefaultProvName)
  1763. CryptReleaseContext(hDefaultProvName, 0);
  1764. return fResult;
  1765. }
  1766. //+-------------------------------------------------------------------------
  1767. // Check if the root issuer.
  1768. //--------------------------------------------------------------------------
  1769. static BOOL IsRootKey()
  1770. {
  1771. if(IDSwcsicmp(hModule,(WCHAR *)wszIssuerKey, IDS_MAKECERT_ROOT) != 0)
  1772. return FALSE;
  1773. //in orde to be sure that we are using the default root, wszIssuerCertFile
  1774. //has to NULL
  1775. if(wszIssuerCertFile!=NULL)
  1776. return FALSE;
  1777. return TRUE;
  1778. }
  1779. //+-------------------------------------------------------------------------
  1780. // Get the root's certificate from the program's resources
  1781. //--------------------------------------------------------------------------
  1782. static PCCERT_CONTEXT GetRootCertContext()
  1783. {
  1784. PCCERT_CONTEXT pCert = NULL;
  1785. HRSRC hRes;
  1786. CHAR szCer[10];
  1787. //load the string CER
  1788. if(!LoadStringA(hModule, IDS_CER, szCer, sizeof(szCer)/sizeof(szCer[0])))
  1789. {
  1790. IDSwprintf(hModule,IDS_ERR_LOAD_ROOT);
  1791. return pCert;
  1792. }
  1793. //
  1794. // The root certificate is stored as a resource of ours.
  1795. // Load it...
  1796. //
  1797. if (0 != (hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_ROOTCERTIFICATE),
  1798. szCer))) {
  1799. HGLOBAL hglobRes;
  1800. if (NULL != (hglobRes = LoadResource(NULL, hRes))) {
  1801. BYTE *pbRes;
  1802. DWORD cbRes;
  1803. cbRes = SizeofResource(NULL, hRes);
  1804. pbRes = (BYTE *) LockResource(hglobRes);
  1805. if (cbRes && pbRes)
  1806. pCert = CertCreateCertificateContext(X509_ASN_ENCODING, pbRes, cbRes);
  1807. UnlockResource(hglobRes);
  1808. FreeResource(hglobRes);
  1809. }
  1810. }
  1811. if (pCert == NULL)
  1812. IDSwprintf(hModule,IDS_ERR_LOAD_ROOT);
  1813. return pCert;
  1814. }
  1815. //+-------------------------------------------------------------------------
  1816. // Get the root's private key from the program's resources and create
  1817. // a temporary key provider container
  1818. //--------------------------------------------------------------------------
  1819. static HCRYPTPROV GetRootProv(OUT LPWSTR *ppwszTmpContainer)
  1820. {
  1821. HCRYPTPROV hProv = 0;
  1822. HRSRC hRes;
  1823. CHAR szPvk[10];
  1824. WCHAR wszRootSig[40];
  1825. //load the string CER
  1826. if(!LoadStringA(hModule, IDS_PVK, szPvk, sizeof(szPvk)/sizeof(szPvk[0])))
  1827. {
  1828. IDSwprintf(hModule,IDS_ERR_ROOT_KEY);
  1829. return hProv;
  1830. }
  1831. //load the string "Root Signature"
  1832. if(!LoadStringU(hModule, IDS_ROOT_SIGNATURE, wszRootSig, sizeof(wszRootSig)/sizeof(wszRootSig[0])))
  1833. {
  1834. IDSwprintf(hModule,IDS_ERR_ROOT_KEY);
  1835. return hProv;
  1836. }
  1837. *ppwszTmpContainer = NULL;
  1838. if (0 != (hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_PVKROOT), szPvk)))
  1839. {
  1840. HGLOBAL hglobRes;
  1841. if (NULL != (hglobRes = LoadResource(NULL, hRes))) {
  1842. BYTE *pbRes;
  1843. DWORD cbRes;
  1844. cbRes = SizeofResource(NULL, hRes);
  1845. pbRes = (BYTE *) LockResource(hglobRes);
  1846. if (cbRes && pbRes) {
  1847. PvkPrivateKeyAcquireContextFromMemory(
  1848. wszIssuerProviderName,
  1849. dwIssuerProviderType,
  1850. pbRes,
  1851. cbRes,
  1852. NULL, // hwndOwner
  1853. wszRootSig,
  1854. &dwIssuerKeySpec,
  1855. &hProv,
  1856. ppwszTmpContainer
  1857. );
  1858. }
  1859. UnlockResource(hglobRes);
  1860. FreeResource(hglobRes);
  1861. }
  1862. }
  1863. if (hProv == 0)
  1864. IDSwprintf(hModule,IDS_ERR_ROOT_KEY);
  1865. return hProv;
  1866. }
  1867. //+-------------------------------------------------------------------------
  1868. // Get the issuer's certificate
  1869. //--------------------------------------------------------------------------
  1870. static PCCERT_CONTEXT GetIssuerCertContext()
  1871. {
  1872. if (IsRootKey())
  1873. {
  1874. PCCERT_CONTEXT pCert = NULL;
  1875. wszIssuerKey=wszRoot;
  1876. // Get root certificate from the program's resources
  1877. pCert=GetRootCertContext();
  1878. wszIssuerKey=wszMakeCertRoot;
  1879. return pCert;
  1880. }
  1881. else {
  1882. PCCERT_CONTEXT pCert = NULL;
  1883. BYTE *pb;
  1884. DWORD cb;
  1885. //make sure we have issuer's certificate
  1886. if(wszIssuerCertFile)
  1887. {
  1888. if (S_OK==RetrieveBLOBFromFile(wszIssuerCertFile,&cb, &pb))
  1889. {
  1890. pCert = CertCreateCertificateContext(X509_ASN_ENCODING, pb, cb);
  1891. UnmapViewOfFile(pb);
  1892. }
  1893. }
  1894. if (pCert == NULL)
  1895. IDSwprintf(hModule,IDS_ERR_LOAD_ISSUER, wszIssuerCertFile);
  1896. return pCert;
  1897. }
  1898. }
  1899. //+-------------------------------------------------------------------------
  1900. // Verify the issuer's certificate. The public key in the certificate
  1901. // must match the public key associated with the private key in the
  1902. // issuer's provider
  1903. //--------------------------------------------------------------------------
  1904. static BOOL VerifyIssuerKey(
  1905. IN HCRYPTPROV hProv,
  1906. IN PCERT_PUBLIC_KEY_INFO pIssuerKeyInfo
  1907. )
  1908. {
  1909. BOOL fResult;
  1910. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
  1911. DWORD cbPubKeyInfo;
  1912. // Get issuer's public key
  1913. cbPubKeyInfo = 0;
  1914. CryptExportPublicKeyInfo(
  1915. hProv,
  1916. dwIssuerKeySpec,
  1917. X509_ASN_ENCODING,
  1918. NULL, // pPubKeyInfo
  1919. &cbPubKeyInfo
  1920. );
  1921. if (cbPubKeyInfo == 0)
  1922. {
  1923. PrintLastError(IDS_ERR_EXPORT_PUB);
  1924. goto ErrorReturn;
  1925. }
  1926. if (NULL == (pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) MakeCertAlloc(cbPubKeyInfo)))
  1927. goto ErrorReturn;
  1928. if (!CryptExportPublicKeyInfo(
  1929. hProv,
  1930. dwIssuerKeySpec,
  1931. X509_ASN_ENCODING,
  1932. pPubKeyInfo,
  1933. &cbPubKeyInfo
  1934. )) {
  1935. PrintLastError(IDS_ERR_EXPORT_PUB);
  1936. goto ErrorReturn;
  1937. }
  1938. if (!CertComparePublicKeyInfo(
  1939. X509_ASN_ENCODING,
  1940. pIssuerKeyInfo,
  1941. pPubKeyInfo)) {
  1942. // This might be the test root with an incorrectly
  1943. // encoded public key. Convert to the capi representation and
  1944. // compare.
  1945. BYTE rgProvKey[256];
  1946. BYTE rgCertKey[256];
  1947. DWORD cbProvKey = sizeof(rgProvKey);
  1948. DWORD cbCertKey = sizeof(rgCertKey);
  1949. if (!CryptDecodeObject(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
  1950. pIssuerKeyInfo->PublicKey.pbData,
  1951. pIssuerKeyInfo->PublicKey.cbData,
  1952. 0, // dwFlags
  1953. rgProvKey,
  1954. &cbProvKey) ||
  1955. !CryptDecodeObject(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
  1956. pPubKeyInfo->PublicKey.pbData,
  1957. pPubKeyInfo->PublicKey.cbData,
  1958. 0, // dwFlags
  1959. rgCertKey,
  1960. &cbCertKey) ||
  1961. cbProvKey == 0 || cbProvKey != cbCertKey ||
  1962. memcmp(rgProvKey, rgCertKey, cbProvKey) != 0) {
  1963. IDSwprintf(hModule,IDS_ERR_MISMATCH);
  1964. goto ErrorReturn;
  1965. }
  1966. }
  1967. fResult = TRUE;
  1968. goto CommonReturn;
  1969. ErrorReturn:
  1970. fResult = FALSE;
  1971. CommonReturn:
  1972. if (pPubKeyInfo)
  1973. MakeCertFree(pPubKeyInfo);
  1974. return fResult;
  1975. }
  1976. //+-------------------------------------------------------------------------
  1977. // Get the issuer's private signature key provider
  1978. //--------------------------------------------------------------------------
  1979. static HCRYPTPROV GetIssuerProv(OUT LPWSTR *ppwszTmpContainer)
  1980. {
  1981. HCRYPTPROV hProv=0;
  1982. WCHAR wszIssuerSig[40];
  1983. //load the string "Issuer Signature"
  1984. if(!LoadStringU(hModule, IDS_ISSUER_SIGNATURE, wszIssuerSig, sizeof(wszIssuerSig)/sizeof(wszIssuerSig[0])))
  1985. {
  1986. IDSwprintf(hModule,IDS_ERR_ROOT_KEY);
  1987. return NULL;
  1988. }
  1989. if (IsRootKey())
  1990. {
  1991. wszIssuerKey=wszRoot;
  1992. // Get root key from the program's resoures and create a temporary
  1993. // key container
  1994. hProv = GetRootProv(ppwszTmpContainer);
  1995. wszIssuerKey=wszMakeCertRoot;
  1996. }
  1997. else
  1998. {
  1999. // get the non-root private key set from either pvk file
  2000. // of the key container
  2001. if(fUseIssuerPvkFile)
  2002. {
  2003. if(S_OK!=PvkGetCryptProv(
  2004. NULL,
  2005. wszIssuerSig,
  2006. wszIssuerProviderName,
  2007. dwIssuerProviderType,
  2008. wszIssuerKey,
  2009. NULL,
  2010. &dwIssuerKeySpec,
  2011. ppwszTmpContainer,
  2012. &hProv))
  2013. hProv=0;
  2014. }
  2015. else
  2016. {
  2017. if(S_OK!=PvkGetCryptProv(
  2018. NULL,
  2019. wszIssuerSig,
  2020. wszIssuerProviderName,
  2021. dwIssuerProviderType,
  2022. NULL,
  2023. wszIssuerKey,
  2024. &dwIssuerKeySpec,
  2025. ppwszTmpContainer,
  2026. &hProv))
  2027. hProv=0;
  2028. }
  2029. if (hProv == 0)
  2030. IDSwprintf(hModule,IDS_ERR_ISSUER_KEY, wszIssuerKey);
  2031. }
  2032. return hProv;
  2033. }
  2034. //+-------------------------------------------------------------------------
  2035. // Get the subject's private key provider
  2036. //--------------------------------------------------------------------------
  2037. static HCRYPTPROV GetSubjectProv(OUT LPWSTR *ppwszTmpContainer)
  2038. {
  2039. HCRYPTPROV hProv=0;
  2040. WCHAR wszKeyName[40];
  2041. int ids;
  2042. WCHAR *wszRegKeyName=NULL;
  2043. BOOL fResult;
  2044. HCRYPTKEY hKey=NULL;
  2045. DWORD dwFlags = 0;
  2046. DWORD dwRequiredKeySpec;
  2047. HCRYPTKEY hPubKey;
  2048. UUID TmpContainerUuid;
  2049. if(dwKeySpec==AT_SIGNATURE)
  2050. ids=IDS_SUB_SIG;
  2051. else
  2052. ids=IDS_SUB_EXCHANGE;
  2053. //load the string
  2054. if(!LoadStringU(hModule, ids, wszKeyName, sizeof(wszKeyName)/sizeof(wszKeyName[0])))
  2055. goto CreateKeyError;
  2056. //try to get the hProv from either a private key file or
  2057. //key container
  2058. if(fUseSubjectPvkFile)
  2059. {
  2060. // Try to open the PVK file if it already exists:
  2061. if(S_OK != PvkGetCryptProv(NULL,
  2062. wszKeyName,
  2063. wszSubjectProviderName,
  2064. dwSubjectProviderType,
  2065. wszSubjectKey,
  2066. NULL,
  2067. &dwKeySpec,
  2068. ppwszTmpContainer,
  2069. &hProv))
  2070. hProv=0;
  2071. }
  2072. else // try to open the key container to see if it exists:
  2073. {
  2074. if (dwSubjectStoreFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE)
  2075. {
  2076. // For machine keysets, we have to do all this ourselves:
  2077. if(!CryptAcquireContextU(&hProv,
  2078. wszSubjectKey,
  2079. wszSubjectProviderName,
  2080. dwSubjectProviderType,
  2081. CRYPT_MACHINE_KEYSET))
  2082. hProv=0;
  2083. else
  2084. {
  2085. //try to figure out the key specification
  2086. if(dwKeySpec==0)
  2087. dwRequiredKeySpec=AT_SIGNATURE;
  2088. else
  2089. dwRequiredKeySpec=dwKeySpec;
  2090. //make sure dwKeySpec is the correct key spec
  2091. if (CryptGetUserKey(hProv,
  2092. dwRequiredKeySpec,
  2093. &hPubKey))
  2094. {
  2095. CryptDestroyKey(hPubKey);
  2096. dwKeySpec = dwRequiredKeySpec;
  2097. }
  2098. else
  2099. {
  2100. //we fail if user required another key spec
  2101. if(dwKeySpec != 0)
  2102. {
  2103. // Doesn't have the specified public key
  2104. CryptReleaseContext(hProv, 0);
  2105. hProv = 0;
  2106. }
  2107. else
  2108. {
  2109. //now we try AT_EXCHANGE key
  2110. dwRequiredKeySpec=AT_KEYEXCHANGE;
  2111. if (CryptGetUserKey(hProv,
  2112. dwRequiredKeySpec,
  2113. &hPubKey))
  2114. {
  2115. CryptDestroyKey(hPubKey);
  2116. dwKeySpec = dwRequiredKeySpec;
  2117. }
  2118. else
  2119. {
  2120. // Doesn't have the specified public key
  2121. CryptReleaseContext(hProv, 0);
  2122. hProv = 0;
  2123. }
  2124. }
  2125. }
  2126. }
  2127. }
  2128. else
  2129. {
  2130. // For user keysets we can use this function to try to acquire the key:
  2131. if(S_OK != PvkGetCryptProv(NULL,
  2132. wszKeyName,
  2133. wszSubjectProviderName,
  2134. dwSubjectProviderType,
  2135. NULL,
  2136. wszSubjectKey,
  2137. &dwKeySpec,
  2138. ppwszTmpContainer,
  2139. &hProv))
  2140. hProv=0;
  2141. }
  2142. }
  2143. // If the keyset didn't already exist, generate a new private keyset:
  2144. if (0 == hProv)
  2145. {
  2146. //now that we have to generate private keys, generate
  2147. //AT_SIGNATURE key by default:
  2148. if(dwKeySpec==0)
  2149. dwKeySpec=AT_SIGNATURE;
  2150. //when the subject PVK file is used
  2151. if(fUseSubjectPvkFile)
  2152. {
  2153. // Create a temporary keyset to load the private key into
  2154. if (CoCreateGuid((GUID *)&TmpContainerUuid) != S_OK)
  2155. {
  2156. goto CreateKeyError;
  2157. }
  2158. if (NULL == (wszRegKeyName = (LPWSTR) MakeCertAlloc
  2159. (((sizeof(UUID) * 2 + 1) * sizeof(WCHAR)))))
  2160. goto CreateKeyError;
  2161. BytesToWStr(sizeof(UUID), &TmpContainerUuid, wszRegKeyName);
  2162. // Open a new key container
  2163. if (!CryptAcquireContextU(
  2164. &hProv,
  2165. wszRegKeyName,
  2166. wszSubjectProviderName,
  2167. dwSubjectProviderType,
  2168. CRYPT_NEWKEYSET // dwFlags
  2169. ))
  2170. goto CreateKeyError;
  2171. // generate new keys in the key container
  2172. if (AT_KEYEXCHANGE == dwKeySpec &&
  2173. PROV_DSS_DH == dwSubjectProviderType) {
  2174. if (!GenDhKey(
  2175. hProv,
  2176. CRYPT_EXPORTABLE // dwFlags
  2177. ))
  2178. goto ErrorReturn;
  2179. } else if (!CryptGenKey(
  2180. hProv,
  2181. dwKeySpec,
  2182. (dwKeyBitLen << 16) | CRYPT_EXPORTABLE,
  2183. &hKey
  2184. ))
  2185. goto CreateKeyError;
  2186. else
  2187. CryptDestroyKey(hKey);
  2188. // Save the key into the file and delete from the provider
  2189. //
  2190. HANDLE hFile = CreateFileU(
  2191. wszSubjectKey,
  2192. GENERIC_READ | GENERIC_WRITE,
  2193. FILE_SHARE_READ,
  2194. NULL, // lpsa
  2195. CREATE_NEW,
  2196. FILE_ATTRIBUTE_NORMAL,
  2197. NULL // hTemplateFile
  2198. );
  2199. if (hFile == INVALID_HANDLE_VALUE)
  2200. {
  2201. if (GetLastError() == ERROR_FILE_EXISTS)
  2202. IDSwprintf(hModule,IDS_ERR_SUB_FILE_EXIST, wszSubjectKey);
  2203. else
  2204. IDSwprintf(hModule,IDS_ERR_SUB_FILE_CREATE, wszSubjectKey);
  2205. fResult = FALSE;
  2206. }
  2207. else
  2208. {
  2209. dwFlags = 0;
  2210. if (AT_KEYEXCHANGE == dwKeySpec &&
  2211. PROV_DSS_DH == dwSubjectProviderType &&
  2212. IsDh3Csp())
  2213. dwFlags |= CRYPT_BLOB_VER3;
  2214. fResult = PvkPrivateKeySave(
  2215. hProv,
  2216. hFile,
  2217. dwKeySpec,
  2218. NULL, // hwndOwner
  2219. wszKeyName,
  2220. dwFlags
  2221. );
  2222. }
  2223. //release hProv
  2224. CryptReleaseContext(hProv, 0);
  2225. fResult &= CryptAcquireContextU(
  2226. &hProv,
  2227. wszRegKeyName,
  2228. wszSubjectProviderName,
  2229. dwSubjectProviderType,
  2230. CRYPT_DELETEKEYSET);
  2231. hProv = 0;
  2232. if (hFile != INVALID_HANDLE_VALUE)
  2233. {
  2234. CloseHandle(hFile);
  2235. if (!fResult)
  2236. DeleteFileU(wszSubjectKey);
  2237. }
  2238. if (!fResult)
  2239. goto CreateKeyError;
  2240. //get hProv
  2241. if(S_OK != PvkGetCryptProv(NULL,
  2242. wszKeyName,
  2243. wszSubjectProviderName,
  2244. dwSubjectProviderType,
  2245. wszSubjectKey,
  2246. NULL,
  2247. &dwKeySpec,
  2248. ppwszTmpContainer,
  2249. &hProv))
  2250. hProv=0;
  2251. }
  2252. else
  2253. { // If we're not using a PVK file:
  2254. // generate a machine keyset if the cert is going to the machine store
  2255. dwFlags = CRYPT_NEWKEYSET;
  2256. if (dwSubjectStoreFlag == CERT_SYSTEM_STORE_LOCAL_MACHINE)
  2257. dwFlags |= CRYPT_MACHINE_KEYSET;
  2258. // Open a new key container
  2259. if (!CryptAcquireContextU(
  2260. &hProv,
  2261. wszSubjectKey,
  2262. wszSubjectProviderName,
  2263. dwSubjectProviderType,
  2264. dwFlags // dwFlags
  2265. ))
  2266. goto CreateKeyError;
  2267. // Before, dwFlags contained flags for CryptAcquireContext.
  2268. // Now these are flags to CSPGenKey
  2269. dwFlags = 0;
  2270. if (fPrivateKeyExportable)
  2271. dwFlags |= CRYPT_EXPORTABLE;
  2272. if (AT_KEYEXCHANGE == dwKeySpec &&
  2273. PROV_DSS_DH == dwSubjectProviderType) {
  2274. if (!GenDhKey(
  2275. hProv,
  2276. dwFlags // dwFlags
  2277. ))
  2278. goto ErrorReturn;
  2279. } else if (!CryptGenKey(
  2280. hProv,
  2281. dwKeySpec,
  2282. (dwKeyBitLen << 16) | dwFlags,
  2283. &hKey
  2284. ))
  2285. goto CreateKeyError;
  2286. else
  2287. CryptDestroyKey(hKey);
  2288. //try to get the user key
  2289. if (CryptGetUserKey(
  2290. hProv,
  2291. dwKeySpec,
  2292. &hKey
  2293. ))
  2294. {
  2295. CryptDestroyKey(hKey);
  2296. }
  2297. else
  2298. {
  2299. // Doesn't have the specified public key
  2300. CryptReleaseContext(hProv, 0);
  2301. hProv=0;
  2302. }
  2303. }
  2304. if (0 == hProv )
  2305. {
  2306. IDSwprintf(hModule,IDS_ERR_SUB_KEY, wszSubjectKey);
  2307. goto ErrorReturn;
  2308. }
  2309. }//hProv==0
  2310. goto CommonReturn;
  2311. CreateKeyError:
  2312. IDSwprintf(hModule,IDS_ERR_SUB_KEY_CREATE, wszSubjectKey);
  2313. ErrorReturn:
  2314. if (hProv)
  2315. {
  2316. CryptReleaseContext(hProv, 0);
  2317. hProv = 0;
  2318. }
  2319. CommonReturn:
  2320. if(wszRegKeyName)
  2321. MakeCertFree(wszRegKeyName);
  2322. return hProv;
  2323. }
  2324. //+-------------------------------------------------------------------------
  2325. // Allocate and get the public key info for the provider
  2326. //--------------------------------------------------------------------------
  2327. static BOOL GetPublicKey(
  2328. HCRYPTPROV hProv,
  2329. PCERT_PUBLIC_KEY_INFO *ppPubKeyInfo
  2330. )
  2331. {
  2332. BOOL fResult;
  2333. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
  2334. DWORD cbPubKeyInfo;
  2335. cbPubKeyInfo = 0;
  2336. CryptExportPublicKeyInfo(
  2337. hProv,
  2338. dwKeySpec,
  2339. X509_ASN_ENCODING,
  2340. NULL, // pPubKeyInfo
  2341. &cbPubKeyInfo
  2342. );
  2343. if (cbPubKeyInfo == 0) {
  2344. PrintLastError(IDS_ERR_EXPORT_PUB);
  2345. goto ErrorReturn;
  2346. }
  2347. if (NULL == (pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) MakeCertAlloc(cbPubKeyInfo)))
  2348. goto ErrorReturn;
  2349. if (!CryptExportPublicKeyInfo(
  2350. hProv,
  2351. dwKeySpec,
  2352. X509_ASN_ENCODING,
  2353. pPubKeyInfo,
  2354. &cbPubKeyInfo
  2355. )) {
  2356. PrintLastError(IDS_ERR_EXPORT_PUB);
  2357. goto ErrorReturn;
  2358. }
  2359. if (fNoPubKeyPara) {
  2360. pPubKeyInfo->Algorithm.Parameters.cbData = 0;
  2361. pPubKeyInfo->Algorithm.Parameters.pbData = NULL;
  2362. }
  2363. if (AT_KEYEXCHANGE == dwKeySpec && PROV_DSS_DH == dwSubjectProviderType) {
  2364. if (!UpdateDhPublicKey(&pPubKeyInfo))
  2365. goto ErrorReturn;
  2366. }
  2367. fResult = TRUE;
  2368. goto CommonReturn;
  2369. ErrorReturn:
  2370. fResult = FALSE;
  2371. if (pPubKeyInfo) {
  2372. MakeCertFree(pPubKeyInfo);
  2373. pPubKeyInfo = NULL;
  2374. }
  2375. CommonReturn:
  2376. *ppPubKeyInfo = pPubKeyInfo;
  2377. return fResult;
  2378. }
  2379. //+-------------------------------------------------------------------------
  2380. // Encode the Glue Name from the input name by prepending the following
  2381. // CERT_RDN_ATTR:
  2382. // pszObjID = SPC_GLUE_RDN_OBJID
  2383. // dwValueType = CERT_RDN_PRINTABLE_STRING
  2384. // Value = "Glue"
  2385. //--------------------------------------------------------------------------
  2386. static BOOL EncodeGlueName(
  2387. IN PCERT_NAME_BLOB pName,
  2388. OUT BYTE **ppbEncodedGlueName,
  2389. OUT DWORD *pcbEncodedGlueName
  2390. )
  2391. {
  2392. BOOL fResult;
  2393. PCERT_NAME_INFO pNameInfo = NULL;
  2394. DWORD cbNameInfo;
  2395. CERT_NAME_INFO GlueNameInfo;
  2396. DWORD cGlueRDN;
  2397. PCERT_RDN pGlueRDN = NULL;
  2398. BYTE *pbEncodedGlueName = NULL;
  2399. DWORD cbEncodedGlueName;
  2400. DWORD i;
  2401. cbNameInfo = 0;
  2402. CryptDecodeObject(X509_ASN_ENCODING, X509_UNICODE_NAME,
  2403. pName->pbData,
  2404. pName->cbData,
  2405. 0, // dwFlags
  2406. NULL, // pNameInfo
  2407. &cbNameInfo
  2408. );
  2409. if (cbNameInfo == 0) goto ErrorReturn;
  2410. if (NULL == (pNameInfo = (PCERT_NAME_INFO) MakeCertAlloc(cbNameInfo)))
  2411. goto ErrorReturn;
  2412. if (!CryptDecodeObject(X509_ASN_ENCODING, X509_UNICODE_NAME,
  2413. pName->pbData,
  2414. pName->cbData,
  2415. 0, // dwFlags
  2416. pNameInfo,
  2417. &cbNameInfo)) goto ErrorReturn;
  2418. cGlueRDN = pNameInfo->cRDN + 1;
  2419. if (NULL == (pGlueRDN = (PCERT_RDN) MakeCertAlloc(cGlueRDN * sizeof(CERT_RDN))))
  2420. goto ErrorReturn;
  2421. pGlueRDN[0].cRDNAttr = 1;
  2422. pGlueRDN[0].rgRDNAttr = &GlueRDNAttr;
  2423. for (i = 1; i < cGlueRDN; i++)
  2424. pGlueRDN[i] = pNameInfo->rgRDN[i - 1];
  2425. GlueNameInfo.cRDN = cGlueRDN;
  2426. GlueNameInfo.rgRDN = pGlueRDN;
  2427. cbEncodedGlueName = 0;
  2428. CryptEncodeObject(X509_ASN_ENCODING, X509_UNICODE_NAME,
  2429. &GlueNameInfo,
  2430. NULL, // pbEncodedGlueName
  2431. &cbEncodedGlueName
  2432. );
  2433. if (cbEncodedGlueName == 0) goto ErrorReturn;
  2434. if (NULL == (pbEncodedGlueName = (BYTE *) MakeCertAlloc(cbEncodedGlueName)))
  2435. goto ErrorReturn;
  2436. if (!CryptEncodeObject(X509_ASN_ENCODING, X509_UNICODE_NAME,
  2437. &GlueNameInfo,
  2438. pbEncodedGlueName,
  2439. &cbEncodedGlueName)) goto ErrorReturn;
  2440. fResult = TRUE;
  2441. goto CommonReturn;
  2442. ErrorReturn:
  2443. if (pbEncodedGlueName) {
  2444. MakeCertFree(pbEncodedGlueName);
  2445. pbEncodedGlueName = NULL;
  2446. }
  2447. cbEncodedGlueName = 0;
  2448. fResult = FALSE;
  2449. CommonReturn:
  2450. if (pNameInfo)
  2451. MakeCertFree(pNameInfo);
  2452. if (pGlueRDN)
  2453. MakeCertFree(pGlueRDN);
  2454. *ppbEncodedGlueName = pbEncodedGlueName;
  2455. *pcbEncodedGlueName = cbEncodedGlueName;
  2456. return fResult;
  2457. }
  2458. //+-------------------------------------------------------------------------
  2459. // Get the subject's cert context and encoded name
  2460. //--------------------------------------------------------------------------
  2461. static BOOL GetRequestInfo(OUT CERT_REQUEST_INFO **ppCertInfo)
  2462. {
  2463. BOOL fResult = FALSE;
  2464. fResult = CryptQueryObject(
  2465. CERT_QUERY_OBJECT_FILE,
  2466. wszSubjectRequestFile,
  2467. CERT_QUERY_CONTENT_FLAG_PKCS10,
  2468. CERT_QUERY_FORMAT_FLAG_ALL,
  2469. CRYPT_DECODE_ALLOC_FLAG,
  2470. NULL,
  2471. NULL,
  2472. NULL,
  2473. NULL,
  2474. NULL,
  2475. (const void **)ppCertInfo);
  2476. return fResult;
  2477. }
  2478. //+-------------------------------------------------------------------------
  2479. // GetExtensionsFromRequest
  2480. //
  2481. // We get all the requested extensions from the PKCS10 request
  2482. //--------------------------------------------------------------------------
  2483. BOOL GetExtensionsFromRequest(PCERT_REQUEST_INFO pReqInfo, DWORD *pdwCount, PCERT_EXTENSIONS **pprgExtensions)
  2484. {
  2485. DWORD dwIndex = 0;
  2486. BOOL fResult = FALSE;
  2487. PCRYPT_ATTRIBUTE pAttr=NULL;
  2488. DWORD cbData=0;
  2489. *pdwCount =0;
  2490. *pprgExtensions=NULL;
  2491. if(!pReqInfo)
  2492. goto CLEANUP;
  2493. // Look for the RSA extension OID first:
  2494. for(dwIndex=0; dwIndex < pReqInfo->cAttribute; dwIndex++)
  2495. {
  2496. if(0 == strcmp((pReqInfo->rgAttribute[dwIndex]).pszObjId, szOID_RSA_certExtensions))
  2497. break;
  2498. }
  2499. if( dwIndex == pReqInfo->cAttribute)
  2500. {
  2501. // We could not find the RSA OID. Try the old Microsoft OID next:
  2502. for(dwIndex=0; dwIndex < pReqInfo->cAttribute; dwIndex++)
  2503. {
  2504. if(0 == strcmp((pReqInfo->rgAttribute[dwIndex]).pszObjId, SPC_CERT_EXTENSIONS_OBJID))
  2505. break;
  2506. }
  2507. if( dwIndex == pReqInfo->cAttribute)
  2508. {
  2509. // We could not find the requested extensions.
  2510. fResult = TRUE;
  2511. goto CLEANUP;
  2512. }
  2513. }
  2514. pAttr=&(pReqInfo->rgAttribute[dwIndex]);
  2515. if(0 == pAttr->cValue)
  2516. {
  2517. fResult=TRUE;
  2518. goto CLEANUP;
  2519. }
  2520. *pprgExtensions = (PCERT_EXTENSIONS *)MakeCertAlloc((pAttr->cValue) * sizeof(PCERT_EXTENSIONS));
  2521. if(NULL == (*pprgExtensions))
  2522. goto CLEANUP;
  2523. memset(*pprgExtensions, 0, (pAttr->cValue) * sizeof(PCERT_EXTENSIONS));
  2524. for(dwIndex=0; dwIndex<pAttr->cValue; dwIndex++)
  2525. {
  2526. cbData = 0;
  2527. if(!CryptDecodeObject(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  2528. X509_EXTENSIONS,
  2529. pAttr->rgValue[dwIndex].pbData,
  2530. pAttr->rgValue[dwIndex].cbData,
  2531. 0,
  2532. NULL,
  2533. &cbData))
  2534. goto CLEANUP;
  2535. (*pprgExtensions)[dwIndex]=(PCERT_EXTENSIONS)MakeCertAlloc(cbData);
  2536. if(NULL == (*pprgExtensions)[dwIndex])
  2537. goto CLEANUP;
  2538. if(!CryptDecodeObject(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  2539. X509_EXTENSIONS,
  2540. pAttr->rgValue[dwIndex].pbData,
  2541. pAttr->rgValue[dwIndex].cbData,
  2542. 0,
  2543. (*pprgExtensions)[dwIndex],
  2544. &cbData))
  2545. goto CLEANUP;
  2546. }
  2547. *pdwCount=pAttr->cValue;
  2548. fResult = TRUE;
  2549. CLEANUP:
  2550. if(FALSE == fResult)
  2551. {
  2552. //we need to free the memory
  2553. if(*pprgExtensions)
  2554. {
  2555. for(dwIndex=0; dwIndex<pAttr->cValue; dwIndex++)
  2556. {
  2557. if((*pprgExtensions)[dwIndex])
  2558. MakeCertFree((*pprgExtensions)[dwIndex]);
  2559. }
  2560. MakeCertFree(*pprgExtensions);
  2561. *pprgExtensions = NULL;
  2562. }
  2563. *pdwCount=0;
  2564. }
  2565. return fResult;
  2566. }
  2567. //+-------------------------------------------------------------------------
  2568. // Get the subject's cert context and encoded name
  2569. //--------------------------------------------------------------------------
  2570. static BOOL GetSubject(
  2571. OUT PCCERT_CONTEXT *ppCertContext,
  2572. OUT BYTE **ppbEncodedName,
  2573. OUT DWORD *pcbEncodedName
  2574. )
  2575. {
  2576. BOOL fResult;
  2577. PCCERT_CONTEXT pCert = NULL;
  2578. BYTE *pb;
  2579. DWORD cb;
  2580. BYTE *pbEncodedName = NULL;
  2581. DWORD cbEncodedName;
  2582. if (S_OK==RetrieveBLOBFromFile(wszSubjectCertFile,&cb, &pb))
  2583. {
  2584. pCert = CertCreateCertificateContext(X509_ASN_ENCODING, pb, cb);
  2585. UnmapViewOfFile(pb);
  2586. }
  2587. if (pCert == NULL)
  2588. goto BadFile;
  2589. if (0 == (cbEncodedName = pCert->pCertInfo->Subject.cbData))
  2590. goto BadFile;
  2591. if (fGlueCert ) {
  2592. if (!EncodeGlueName(
  2593. &pCert->pCertInfo->Subject,
  2594. &pbEncodedName,
  2595. &cbEncodedName))
  2596. goto ErrorReturn;
  2597. } else {
  2598. if (NULL == (pbEncodedName = (BYTE *) MakeCertAlloc(cbEncodedName)))
  2599. goto ErrorReturn;
  2600. memcpy(pbEncodedName, pCert->pCertInfo->Subject.pbData, cbEncodedName);
  2601. }
  2602. fResult = TRUE;
  2603. goto CommonReturn;
  2604. BadFile:
  2605. IDSwprintf(hModule, IDS_ERR_CANNOT_LOAD_SUB_CERT,
  2606. wszSubjectCertFile);
  2607. ErrorReturn:
  2608. if (pbEncodedName) {
  2609. MakeCertFree(pbEncodedName);
  2610. pbEncodedName = NULL;
  2611. }
  2612. cbEncodedName = 0;
  2613. if (pCert) {
  2614. CertFreeCertificateContext(pCert);
  2615. pCert = NULL;
  2616. }
  2617. fResult = FALSE;
  2618. CommonReturn:
  2619. *ppCertContext = pCert;
  2620. *ppbEncodedName = pbEncodedName;
  2621. *pcbEncodedName = cbEncodedName;
  2622. return fResult;
  2623. }
  2624. //+-------------------------------------------------------------------------
  2625. // Convert and encode the subject's X500 formatted name
  2626. //--------------------------------------------------------------------------
  2627. static BOOL EncodeSubject(
  2628. OUT BYTE **ppbEncoded,
  2629. IN OUT DWORD *pcbEncoded
  2630. )
  2631. {
  2632. BOOL fResult;
  2633. DWORD cbEncodedSubject=0;
  2634. BYTE *pbEncodedSubject=NULL;
  2635. BYTE *pbEncoded = NULL;
  2636. DWORD cbEncoded;
  2637. CERT_NAME_BLOB SubjectInfo;
  2638. //encode the wszSubjectX500Name into an encoded X509_NAME
  2639. if(!CertStrToNameW(
  2640. X509_ASN_ENCODING,
  2641. wszSubjectX500Name,
  2642. CERT_NAME_STR_REVERSE_FLAG,
  2643. NULL,
  2644. NULL,
  2645. &cbEncodedSubject,
  2646. NULL))
  2647. {
  2648. PrintLastError(IDS_CERT_STR_TO_NAME);
  2649. goto ErrorReturn;
  2650. }
  2651. pbEncodedSubject = (BYTE *) MakeCertAlloc(cbEncodedSubject);
  2652. if (pbEncodedSubject == NULL) goto ErrorReturn;
  2653. if(!CertStrToNameW(
  2654. X509_ASN_ENCODING,
  2655. wszSubjectX500Name,
  2656. CERT_NAME_STR_REVERSE_FLAG,
  2657. NULL,
  2658. pbEncodedSubject,
  2659. &cbEncodedSubject,
  2660. NULL))
  2661. {
  2662. PrintLastError(IDS_CERT_STR_TO_NAME);
  2663. goto ErrorReturn;
  2664. }
  2665. SubjectInfo.cbData=cbEncodedSubject;
  2666. SubjectInfo.pbData=pbEncodedSubject;
  2667. //add the GLUE CDRT_RDN_ATTR
  2668. if (fGlueCert)
  2669. {
  2670. if(!EncodeGlueName(&SubjectInfo,
  2671. &pbEncoded,
  2672. &cbEncoded))
  2673. goto ErrorReturn;
  2674. }
  2675. else
  2676. {
  2677. cbEncoded=cbEncodedSubject;
  2678. pbEncoded=pbEncodedSubject;
  2679. }
  2680. fResult = TRUE;
  2681. goto CommonReturn;
  2682. ErrorReturn:
  2683. if (pbEncoded) {
  2684. MakeCertFree(pbEncoded);
  2685. pbEncoded = NULL;
  2686. }
  2687. cbEncoded = 0;
  2688. fResult = FALSE;
  2689. CommonReturn:
  2690. //we need to free the memory for pbEncodedSubject for GlueCert
  2691. if(fGlueCert)
  2692. {
  2693. if(pbEncodedSubject)
  2694. {
  2695. MakeCertFree(pbEncodedSubject);
  2696. pbEncodedSubject=NULL;
  2697. }
  2698. }
  2699. *ppbEncoded = pbEncoded;
  2700. *pcbEncoded = cbEncoded;
  2701. return fResult;
  2702. }
  2703. // The test root's public key isn't encoded properly in the certificate.
  2704. // It's missing a leading zero to make it a unsigned integer.
  2705. static BYTE rgbTestRoot[] = {
  2706. #include "root.h"
  2707. };
  2708. static CERT_PUBLIC_KEY_INFO TestRootPublicKeyInfo = {
  2709. szOID_RSA_RSA, 0, NULL, sizeof(rgbTestRoot), rgbTestRoot, 0
  2710. };
  2711. static BYTE rgbTestRootInfoAsn[] = {
  2712. #include "rootasn.h"
  2713. };
  2714. //+-------------------------------------------------------------------------
  2715. // X509 Extensions: Allocate and Encode functions
  2716. //--------------------------------------------------------------------------
  2717. static BOOL CreateAuthorityKeyId(
  2718. IN HCRYPTPROV hProv,
  2719. IN PCERT_INFO pIssuerCert,
  2720. OUT BYTE **ppbEncoded,
  2721. IN OUT DWORD *pcbEncoded
  2722. )
  2723. {
  2724. BOOL fResult;
  2725. BYTE *pbEncoded = NULL;
  2726. DWORD cbEncoded;
  2727. CERT_AUTHORITY_KEY_ID_INFO KeyIdInfo;
  2728. #define MAX_HASH_LEN 20
  2729. BYTE rgbHash[MAX_HASH_LEN];
  2730. DWORD cbHash = MAX_HASH_LEN;
  2731. // Issuer's KeyId: MD5 hash of the encoded issuer's public key info
  2732. // First check if the issuer is the test root with an incorrectly
  2733. // encoded public key.
  2734. if (CertComparePublicKeyInfo(
  2735. X509_ASN_ENCODING,
  2736. &pIssuerCert->SubjectPublicKeyInfo,
  2737. &TestRootPublicKeyInfo
  2738. )) {
  2739. if (!CryptHashCertificate(
  2740. hProv,
  2741. CALG_MD5,
  2742. 0, // dwFlags
  2743. rgbTestRootInfoAsn,
  2744. sizeof(rgbTestRootInfoAsn),
  2745. rgbHash,
  2746. &cbHash)) {
  2747. PrintLastError(IDS_CRYPT_HASH_CERT);
  2748. goto ErrorReturn;
  2749. }
  2750. } else {
  2751. if (!CryptHashPublicKeyInfo(
  2752. hProv,
  2753. CALG_MD5,
  2754. 0, // dwFlags
  2755. X509_ASN_ENCODING,
  2756. &pIssuerCert->SubjectPublicKeyInfo,
  2757. rgbHash,
  2758. &cbHash)) {
  2759. PrintLastError(IDS_CRYPT_HASP_PUB);
  2760. goto ErrorReturn;
  2761. }
  2762. }
  2763. KeyIdInfo.KeyId.pbData = rgbHash;
  2764. KeyIdInfo.KeyId.cbData = cbHash;
  2765. // Issuer's Issuer
  2766. KeyIdInfo.CertIssuer = pIssuerCert->Issuer;
  2767. // Issuer's SerialNumber
  2768. KeyIdInfo.CertSerialNumber = pIssuerCert->SerialNumber;
  2769. cbEncoded = 0;
  2770. CryptEncodeObject(X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID,
  2771. &KeyIdInfo,
  2772. NULL, // pbEncoded
  2773. &cbEncoded
  2774. );
  2775. if (cbEncoded == 0) {
  2776. PrintLastError(IDS_ENCODE_AUTH_KEY);
  2777. goto ErrorReturn;
  2778. }
  2779. pbEncoded = (BYTE *) MakeCertAlloc(cbEncoded);
  2780. if (pbEncoded == NULL) goto ErrorReturn;
  2781. if (!CryptEncodeObject(X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID,
  2782. &KeyIdInfo,
  2783. pbEncoded,
  2784. &cbEncoded
  2785. )) {
  2786. PrintLastError(IDS_ENCODE_AUTH_KEY);
  2787. goto ErrorReturn;
  2788. }
  2789. fResult = TRUE;
  2790. goto CommonReturn;
  2791. ErrorReturn:
  2792. if (pbEncoded) {
  2793. MakeCertFree(pbEncoded);
  2794. pbEncoded = NULL;
  2795. }
  2796. cbEncoded = 0;
  2797. fResult = FALSE;
  2798. CommonReturn:
  2799. *ppbEncoded = pbEncoded;
  2800. *pcbEncoded = cbEncoded;
  2801. return fResult;
  2802. }
  2803. static BOOL CreateSpcSpAgency(
  2804. OUT BYTE **ppbEncoded,
  2805. IN OUT DWORD *pcbEncoded
  2806. )
  2807. {
  2808. BOOL fResult;
  2809. BYTE *pbEncoded = NULL;
  2810. DWORD cbEncoded;
  2811. SPC_LINK PolicyLink;
  2812. SPC_SP_AGENCY_INFO AgencyInfo;
  2813. memset(&AgencyInfo, 0, sizeof(AgencyInfo));
  2814. if (wszPolicyLink) {
  2815. PolicyLink.dwLinkChoice = SPC_URL_LINK_CHOICE;
  2816. PolicyLink.pwszUrl = wszPolicyLink;
  2817. AgencyInfo.pPolicyInformation = &PolicyLink;
  2818. }
  2819. cbEncoded = 0;
  2820. CryptEncodeObject(X509_ASN_ENCODING,
  2821. SPC_SP_AGENCY_INFO_OBJID,
  2822. &AgencyInfo,
  2823. NULL, // pbEncoded
  2824. &cbEncoded);
  2825. if (cbEncoded == 0) {
  2826. PrintLastError(IDS_ENCODE_SPC_AGENCY);
  2827. goto ErrorReturn;
  2828. }
  2829. pbEncoded = (BYTE *) MakeCertAlloc(cbEncoded);
  2830. if (pbEncoded == NULL) goto ErrorReturn;
  2831. if (!CryptEncodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT,
  2832. &AgencyInfo,
  2833. pbEncoded,
  2834. &cbEncoded
  2835. )) {
  2836. PrintLastError(IDS_ENCODE_SPC_AGENCY);
  2837. goto ErrorReturn;
  2838. }
  2839. fResult = TRUE;
  2840. goto CommonReturn;
  2841. ErrorReturn:
  2842. if (pbEncoded)
  2843. {
  2844. MakeCertFree(pbEncoded);
  2845. pbEncoded = NULL;
  2846. }
  2847. cbEncoded = 0;
  2848. fResult = FALSE;
  2849. CommonReturn:
  2850. *ppbEncoded = pbEncoded;
  2851. *pcbEncoded = cbEncoded;
  2852. return fResult;
  2853. }
  2854. static BOOL CreateEnhancedKeyUsage(
  2855. OUT BYTE **ppbEncoded,
  2856. IN OUT DWORD *pcbEncoded
  2857. )
  2858. {
  2859. BOOL fResult = FALSE;
  2860. LPBYTE pbEncoded =NULL;
  2861. DWORD cbEncoded =0;
  2862. DWORD cCount =0;
  2863. LPSTR psz=NULL;
  2864. LPSTR pszTok=NULL;
  2865. DWORD cTok = 0;
  2866. PCERT_ENHKEY_USAGE pUsage =NULL;
  2867. LPSTR pszCodeSigning = szOID_PKIX_KP_CODE_SIGNING;
  2868. BOOL fFound=FALSE;
  2869. if(wszEKUOids)
  2870. {
  2871. if ( WSZtoSZ(wszEKUOids, &psz) != S_OK )
  2872. goto CLEANUP;
  2873. //
  2874. // Count the number of OIDs as well as converting from comma delimited
  2875. // to NULL character delimited
  2876. //
  2877. pszTok = strtok(psz, ",");
  2878. while ( pszTok != NULL )
  2879. {
  2880. cTok++;
  2881. pszTok = strtok(NULL, ",");
  2882. }
  2883. //
  2884. // Allocate a cert enhanced key usage structure and fill it in with
  2885. // the string tokens
  2886. //
  2887. // we allocate one more string for the code signing OIDs
  2888. //
  2889. pUsage = (PCERT_ENHKEY_USAGE)new BYTE [sizeof(CERT_ENHKEY_USAGE) + ( (cTok + 1) * sizeof(LPSTR) )];
  2890. if(NULL == pUsage)
  2891. goto CLEANUP;
  2892. pszTok = psz;
  2893. pUsage->cUsageIdentifier = cTok;
  2894. pUsage->rgpszUsageIdentifier = (LPSTR *)((LPBYTE)pUsage+sizeof(CERT_ENHKEY_USAGE));
  2895. for ( cCount = 0; cCount < cTok; cCount++ )
  2896. {
  2897. pUsage->rgpszUsageIdentifier[cCount] = pszTok;
  2898. pszTok = pszTok+strlen(pszTok)+1;
  2899. }
  2900. //we add the code signing OID if use has specified commerical or individual signing
  2901. if(fCertCommercial || fCertIndividual)
  2902. {
  2903. //check to see if the code signing OID is alreayd present
  2904. for(cCount = 0; cCount < pUsage->cUsageIdentifier; cCount++)
  2905. {
  2906. if(0 == strcmp(pszCodeSigning,pUsage->rgpszUsageIdentifier[cCount]))
  2907. {
  2908. fFound=TRUE;
  2909. break;
  2910. }
  2911. }
  2912. if(FALSE == fFound)
  2913. {
  2914. (pUsage->rgpszUsageIdentifier)[pUsage->cUsageIdentifier] = pszCodeSigning;
  2915. (pUsage->cUsageIdentifier)++ ;
  2916. }
  2917. }
  2918. }
  2919. else
  2920. {
  2921. if(fCertCommercial || fCertIndividual)
  2922. {
  2923. pUsage = (PCERT_ENHKEY_USAGE)new BYTE [sizeof(CERT_ENHKEY_USAGE)];
  2924. if(NULL == pUsage)
  2925. goto CLEANUP;
  2926. pUsage->cUsageIdentifier = 1;
  2927. pUsage->rgpszUsageIdentifier = &pszCodeSigning;
  2928. }
  2929. else
  2930. {
  2931. goto CLEANUP;
  2932. }
  2933. }
  2934. //
  2935. // Encode the usage
  2936. //
  2937. if(!CryptEncodeObject(
  2938. X509_ASN_ENCODING,
  2939. szOID_ENHANCED_KEY_USAGE,
  2940. pUsage,
  2941. NULL,
  2942. &cbEncoded
  2943. ))
  2944. goto CLEANUP;
  2945. pbEncoded = new BYTE [cbEncoded];
  2946. if(NULL == pbEncoded)
  2947. goto CLEANUP;
  2948. fResult = CryptEncodeObject(
  2949. X509_ASN_ENCODING,
  2950. szOID_ENHANCED_KEY_USAGE,
  2951. pUsage,
  2952. pbEncoded,
  2953. &cbEncoded
  2954. );
  2955. //
  2956. // Cleanup
  2957. //
  2958. CLEANUP:
  2959. if(pUsage)
  2960. delete[] pUsage;
  2961. if(psz)
  2962. MakeCertFree(psz);
  2963. if ( TRUE == fResult)
  2964. {
  2965. *ppbEncoded = pbEncoded;
  2966. *pcbEncoded = cbEncoded;
  2967. }
  2968. else
  2969. {
  2970. if(pbEncoded)
  2971. delete[] pbEncoded;
  2972. }
  2973. return fResult;
  2974. }
  2975. static BOOL CreateKeyUsage(
  2976. OUT BYTE **ppbEncoded,
  2977. IN OUT DWORD *pcbEncoded
  2978. )
  2979. {
  2980. BOOL fResult;
  2981. BYTE *pbEncoded = NULL;
  2982. DWORD cbEncoded;
  2983. CERT_KEY_USAGE_RESTRICTION_INFO KeyUsageInfo;
  2984. BYTE bRestrictedKeyUsage;
  2985. DWORD cCertPolicyId;
  2986. LPSTR rgpszIndividualCertPolicyElementId[1] = {
  2987. SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID
  2988. };
  2989. LPSTR rgpszCommercialCertPolicyElementId[1] = {
  2990. SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID
  2991. };
  2992. CERT_POLICY_ID rgCertPolicyId[2];
  2993. memset(&KeyUsageInfo, 0, sizeof(KeyUsageInfo));
  2994. bRestrictedKeyUsage = CERT_DIGITAL_SIGNATURE_KEY_USAGE;
  2995. KeyUsageInfo.RestrictedKeyUsage.pbData = &bRestrictedKeyUsage;
  2996. KeyUsageInfo.RestrictedKeyUsage.cbData = 1;
  2997. KeyUsageInfo.RestrictedKeyUsage.cUnusedBits = 7;
  2998. cCertPolicyId = 0;
  2999. if (fCertIndividual) {
  3000. rgCertPolicyId[cCertPolicyId].cCertPolicyElementId = 1;
  3001. rgCertPolicyId[cCertPolicyId].rgpszCertPolicyElementId =
  3002. rgpszIndividualCertPolicyElementId;
  3003. cCertPolicyId++;
  3004. }
  3005. if (fCertCommercial) {
  3006. rgCertPolicyId[cCertPolicyId].cCertPolicyElementId = 1;
  3007. rgCertPolicyId[cCertPolicyId].rgpszCertPolicyElementId =
  3008. rgpszCommercialCertPolicyElementId;
  3009. cCertPolicyId++;
  3010. }
  3011. if (cCertPolicyId > 0) {
  3012. KeyUsageInfo.cCertPolicyId = cCertPolicyId;
  3013. KeyUsageInfo.rgCertPolicyId = rgCertPolicyId;
  3014. }
  3015. cbEncoded = 0;
  3016. CryptEncodeObject(X509_ASN_ENCODING, X509_KEY_USAGE_RESTRICTION,
  3017. &KeyUsageInfo,
  3018. NULL, // pbEncoded
  3019. &cbEncoded
  3020. );
  3021. if (cbEncoded == 0) {
  3022. PrintLastError(IDS_ENCODE_KEY_USAGE);
  3023. goto ErrorReturn;
  3024. }
  3025. pbEncoded = (BYTE *) MakeCertAlloc(cbEncoded);
  3026. if (pbEncoded == NULL) goto ErrorReturn;
  3027. if (!CryptEncodeObject(X509_ASN_ENCODING, X509_KEY_USAGE_RESTRICTION,
  3028. &KeyUsageInfo,
  3029. pbEncoded,
  3030. &cbEncoded
  3031. )) {
  3032. PrintLastError(IDS_ENCODE_KEY_USAGE);
  3033. goto ErrorReturn;
  3034. }
  3035. fResult = TRUE;
  3036. goto CommonReturn;
  3037. ErrorReturn:
  3038. if (pbEncoded) {
  3039. MakeCertFree(pbEncoded);
  3040. pbEncoded = NULL;
  3041. }
  3042. cbEncoded = 0;
  3043. fResult = FALSE;
  3044. CommonReturn:
  3045. *ppbEncoded = pbEncoded;
  3046. *pcbEncoded = cbEncoded;
  3047. return fResult;
  3048. }
  3049. static BOOL CreateBasicConstraints(
  3050. OUT BYTE **ppbEncoded,
  3051. IN OUT DWORD *pcbEncoded
  3052. )
  3053. {
  3054. BOOL fResult;
  3055. BYTE *pbEncoded = NULL;
  3056. DWORD cbEncoded;
  3057. CERT_BASIC_CONSTRAINTS2_INFO Info2;
  3058. memset(&Info2, 0, sizeof(Info2));
  3059. if (certTypes == 0)
  3060. certTypes = CERT_END_ENTITY_SUBJECT_FLAG;
  3061. if (CERT_CA_SUBJECT_FLAG & certTypes)
  3062. {
  3063. Info2.fCA = TRUE;
  3064. }
  3065. if (pathLenConstraint < 0) {
  3066. Info2.fPathLenConstraint = FALSE;
  3067. } else {
  3068. Info2.fPathLenConstraint = TRUE;
  3069. Info2.dwPathLenConstraint = pathLenConstraint;
  3070. }
  3071. cbEncoded = 0;
  3072. CryptEncodeObject(X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2,
  3073. &Info2,
  3074. NULL, // pbEncoded
  3075. &cbEncoded
  3076. );
  3077. if (cbEncoded == 0) {
  3078. PrintLastError(IDS_ENCODE_BASIC_CONSTRAINTS2);
  3079. goto ErrorReturn;
  3080. }
  3081. pbEncoded = (BYTE *) MakeCertAlloc(cbEncoded);
  3082. if (pbEncoded == NULL) goto ErrorReturn;
  3083. if (!CryptEncodeObject(X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2,
  3084. &Info2,
  3085. pbEncoded,
  3086. &cbEncoded
  3087. )) {
  3088. PrintLastError(IDS_ENCODE_BASIC_CONSTRAINTS2);
  3089. goto ErrorReturn;
  3090. }
  3091. fResult = TRUE;
  3092. goto CommonReturn;
  3093. ErrorReturn:
  3094. if (pbEncoded) {
  3095. MakeCertFree(pbEncoded);
  3096. pbEncoded = NULL;
  3097. }
  3098. cbEncoded = 0;
  3099. fResult = FALSE;
  3100. CommonReturn:
  3101. *ppbEncoded = pbEncoded;
  3102. *pcbEncoded = cbEncoded;
  3103. return fResult;
  3104. }
  3105. //+-------------------------------------------------------------------------
  3106. // Converts the bytes into WCHAR hex
  3107. //
  3108. // Needs (cb * 2 + 1) * sizeof(WCHAR) bytes of space in wsz
  3109. //--------------------------------------------------------------------------
  3110. static void BytesToWStr(ULONG cb, void* pv, LPWSTR wsz)
  3111. {
  3112. BYTE* pb = (BYTE*) pv;
  3113. for (ULONG i = 0; i<cb; i++) {
  3114. int b;
  3115. b = (*pb & 0xF0) >> 4;
  3116. *wsz++ = (b <= 9) ? b + L'0' : (b - 10) + L'A';
  3117. b = *pb & 0x0F;
  3118. *wsz++ = (b <= 9) ? b + L'0' : (b - 10) + L'A';
  3119. pb++;
  3120. }
  3121. *wsz++ = 0;
  3122. }
  3123. //-----------------------------------------------------------------------
  3124. //
  3125. // Get the hash from a cert file
  3126. //
  3127. //--------------------------------------------------------------------------
  3128. HRESULT GetCertHashFromFile(LPWSTR pwszCertFile,
  3129. BYTE **ppHash,
  3130. DWORD *pcbHash,
  3131. BOOL *pfMore)
  3132. {
  3133. HRESULT hr;
  3134. HCERTSTORE hCertStore=NULL;
  3135. PCCERT_CONTEXT pSigningCert=NULL;
  3136. PCCERT_CONTEXT pPreCert=NULL;
  3137. PCCERT_CONTEXT pDupCert=NULL;
  3138. DWORD dwCount=0;
  3139. if(!ppHash || !pcbHash || !pfMore)
  3140. return E_INVALIDARG;
  3141. //init
  3142. *pcbHash=0;
  3143. *ppHash=NULL;
  3144. *pfMore=FALSE;
  3145. //open a cert store
  3146. hCertStore=CertOpenStore(CERT_STORE_PROV_FILENAME_W,
  3147. dwCertStoreEncodingType,
  3148. NULL,
  3149. 0,
  3150. pwszCertFile);
  3151. if(hCertStore==NULL)
  3152. {
  3153. hr=SignError();
  3154. goto CLEANUP;
  3155. }
  3156. while(pDupCert=CertEnumCertificatesInStore(hCertStore,
  3157. pPreCert))
  3158. {
  3159. dwCount++;
  3160. // Fail if there is more than one cert in the store
  3161. if(dwCount > 1)
  3162. {
  3163. CertFreeCertificateContext(pDupCert);
  3164. pDupCert=NULL;
  3165. CertFreeCertificateContext(pSigningCert);
  3166. pSigningCert=NULL;
  3167. *pfMore=TRUE;
  3168. hr=E_FAIL;
  3169. goto CLEANUP;
  3170. }
  3171. pPreCert=pDupCert;
  3172. pSigningCert=CertDuplicateCertificateContext(pDupCert);
  3173. }
  3174. if(pSigningCert==NULL)
  3175. {
  3176. hr=CRYPT_E_NO_DECRYPT_CERT;
  3177. goto CLEANUP;
  3178. }
  3179. //get the hash
  3180. if(!CertGetCertificateContextProperty(pSigningCert,
  3181. CERT_SHA1_HASH_PROP_ID,
  3182. NULL,
  3183. pcbHash))
  3184. {
  3185. hr=SignError();
  3186. goto CLEANUP;
  3187. }
  3188. *ppHash=(BYTE *)ToolUtlAlloc(*pcbHash);
  3189. if(!(*ppHash))
  3190. {
  3191. hr=E_OUTOFMEMORY;
  3192. goto CLEANUP;
  3193. }
  3194. if(!CertGetCertificateContextProperty(pSigningCert,
  3195. CERT_SHA1_HASH_PROP_ID,
  3196. *ppHash,
  3197. pcbHash))
  3198. {
  3199. hr=SignError();
  3200. goto CLEANUP;
  3201. }
  3202. hr=S_OK;
  3203. CLEANUP:
  3204. if(pSigningCert)
  3205. CertFreeCertificateContext(pSigningCert);
  3206. if(hCertStore)
  3207. CertCloseStore(hCertStore, 0);
  3208. if(hr!=S_OK)
  3209. {
  3210. if(*ppHash)
  3211. {
  3212. ToolUtlFree(*ppHash);
  3213. *ppHash=NULL;
  3214. }
  3215. }
  3216. return hr;
  3217. }
  3218. //-----------------------------------------------------------------------
  3219. //
  3220. // Get the signing certificate
  3221. //
  3222. //--------------------------------------------------------------------------
  3223. PCCERT_CONTEXT GetIssuerCertAndStore(HCERTSTORE *phCertStore, BOOL *pfMore)
  3224. {
  3225. PCCERT_CONTEXT pSigningCert=NULL;
  3226. PCCERT_CONTEXT pPreCert=NULL;
  3227. PCCERT_CONTEXT pDupCert=NULL;
  3228. BYTE *pHash=NULL;
  3229. DWORD cbHash;
  3230. HCERTSTORE hCertStore=NULL;
  3231. CRYPT_HASH_BLOB HashBlob;
  3232. DWORD dwCount=0;
  3233. //init the output
  3234. if(!phCertStore || !pfMore)
  3235. return NULL;
  3236. *phCertStore=NULL;
  3237. *pfMore=FALSE;
  3238. //open a cert store
  3239. hCertStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  3240. dwCertStoreEncodingType,
  3241. NULL,
  3242. dwIssuerStoreFlag|CERT_STORE_READONLY_FLAG,
  3243. wszIssuerStore);
  3244. if(!hCertStore)
  3245. return NULL;
  3246. //get the hash of the certificate. Find the cert based on
  3247. //pwszCertFile
  3248. if(wszIssuerCertFile)
  3249. {
  3250. if(S_OK != GetCertHashFromFile(wszIssuerCertFile, &pHash, &cbHash, pfMore))
  3251. goto CLEANUP;
  3252. HashBlob.cbData=cbHash;
  3253. HashBlob.pbData=pHash;
  3254. pSigningCert=CertFindCertificateInStore(hCertStore,
  3255. X509_ASN_ENCODING,
  3256. 0,
  3257. CERT_FIND_SHA1_HASH,
  3258. &HashBlob,
  3259. NULL);
  3260. }
  3261. else
  3262. {
  3263. //find the certificate with the common name
  3264. if(wszIssuerCertName)
  3265. {
  3266. while(pDupCert=CertFindCertificateInStore(hCertStore,
  3267. X509_ASN_ENCODING,
  3268. 0,
  3269. CERT_FIND_SUBJECT_STR_W,
  3270. wszIssuerCertName,
  3271. pPreCert))
  3272. {
  3273. dwCount++;
  3274. if(dwCount > 1)
  3275. {
  3276. CertFreeCertificateContext(pDupCert);
  3277. pDupCert=NULL;
  3278. CertFreeCertificateContext(pSigningCert);
  3279. pSigningCert=NULL;
  3280. *pfMore=TRUE;
  3281. goto CLEANUP;
  3282. }
  3283. pPreCert=pDupCert;
  3284. pSigningCert=CertDuplicateCertificateContext(pDupCert);
  3285. }
  3286. }
  3287. else
  3288. {
  3289. //no searching criteria, find the only cert in the store
  3290. while(pDupCert=CertEnumCertificatesInStore(hCertStore,
  3291. pPreCert))
  3292. {
  3293. dwCount++;
  3294. if(dwCount > 1)
  3295. {
  3296. CertFreeCertificateContext(pDupCert);
  3297. pDupCert=NULL;
  3298. CertFreeCertificateContext(pSigningCert);
  3299. pSigningCert=NULL;
  3300. *pfMore=TRUE;
  3301. goto CLEANUP;
  3302. }
  3303. pPreCert=pDupCert;
  3304. pSigningCert=CertDuplicateCertificateContext(pDupCert);
  3305. }
  3306. }
  3307. }
  3308. CLEANUP:
  3309. if(pHash)
  3310. ToolUtlFree(pHash);
  3311. if(pSigningCert)
  3312. {
  3313. *phCertStore=hCertStore;
  3314. }
  3315. else
  3316. {
  3317. //free the hCertStore
  3318. CertCloseStore(hCertStore, 0);
  3319. }
  3320. return pSigningCert;
  3321. }
  3322. //-----------------------------------------------------------------------
  3323. //
  3324. // EmptySubject
  3325. //
  3326. //--------------------------------------------------------------------------
  3327. BOOL EmptySubject(CERT_NAME_BLOB *pSubject)
  3328. {
  3329. BOOL fEmpty = TRUE;
  3330. CERT_NAME_INFO *pCertNameInfo=NULL;
  3331. DWORD cbData =0;
  3332. if(!pSubject)
  3333. goto CLEANUP;
  3334. if(!CryptDecodeObject(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  3335. X509_UNICODE_NAME,
  3336. pSubject->pbData,
  3337. pSubject->cbData,
  3338. 0,
  3339. NULL,
  3340. &cbData))
  3341. goto CLEANUP;
  3342. pCertNameInfo = (CERT_NAME_INFO *)MakeCertAlloc(cbData);
  3343. if(NULL == pCertNameInfo)
  3344. goto CLEANUP;
  3345. if(!CryptDecodeObject(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  3346. X509_UNICODE_NAME,
  3347. pSubject->pbData,
  3348. pSubject->cbData,
  3349. 0,
  3350. pCertNameInfo,
  3351. &cbData))
  3352. goto CLEANUP;
  3353. if((pCertNameInfo->cRDN) > 0)
  3354. fEmpty = FALSE;
  3355. CLEANUP:
  3356. if(pCertNameInfo)
  3357. MakeCertFree(pCertNameInfo);
  3358. return fEmpty;
  3359. }
  3360. //+=========================================================================
  3361. // Support functions to generate DH keys having the 'Q'parameter
  3362. //==========================================================================
  3363. static BOOL EncodeAndAllocObject(
  3364. IN LPCSTR lpszStructType,
  3365. IN const void *pvStructInfo,
  3366. OUT BYTE **ppbEncoded,
  3367. IN OUT DWORD *pcbEncoded
  3368. )
  3369. {
  3370. BOOL fResult;
  3371. BYTE *pbEncoded = NULL;
  3372. DWORD cbEncoded = 0;
  3373. if (!CryptEncodeObject(
  3374. X509_ASN_ENCODING,
  3375. lpszStructType,
  3376. pvStructInfo,
  3377. NULL,
  3378. &cbEncoded
  3379. ))
  3380. goto ErrorReturn;
  3381. if (NULL == (pbEncoded = (BYTE *) MakeCertAlloc(cbEncoded)))
  3382. goto ErrorReturn;
  3383. if (!CryptEncodeObject(
  3384. X509_ASN_ENCODING,
  3385. lpszStructType,
  3386. pvStructInfo,
  3387. pbEncoded,
  3388. &cbEncoded
  3389. ))
  3390. goto ErrorReturn;
  3391. fResult = TRUE;
  3392. CommonReturn:
  3393. *ppbEncoded = pbEncoded;
  3394. *pcbEncoded = cbEncoded;
  3395. return fResult;
  3396. ErrorReturn:
  3397. fResult = FALSE;
  3398. MakeCertFree(pbEncoded);
  3399. pbEncoded = NULL;
  3400. goto CommonReturn;
  3401. }
  3402. static BOOL DecodeAndAllocObject(
  3403. IN LPCSTR lpszStructType,
  3404. IN const BYTE *pbEncoded,
  3405. IN DWORD cbEncoded,
  3406. OUT void **ppvStructInfo,
  3407. IN OUT DWORD *pcbStructInfo
  3408. )
  3409. {
  3410. BOOL fResult;
  3411. void *pvStructInfo = NULL;
  3412. DWORD cbStructInfo = 0;
  3413. if (!CryptDecodeObject(
  3414. X509_ASN_ENCODING,
  3415. lpszStructType,
  3416. pbEncoded,
  3417. cbEncoded,
  3418. 0, // dwFlags
  3419. NULL,
  3420. &cbStructInfo
  3421. ))
  3422. goto ErrorReturn;
  3423. if (NULL == (pvStructInfo = MakeCertAlloc(cbStructInfo)))
  3424. goto ErrorReturn;
  3425. if (!CryptDecodeObject(
  3426. X509_ASN_ENCODING,
  3427. lpszStructType,
  3428. pbEncoded,
  3429. cbEncoded,
  3430. 0, // dwFlags
  3431. pvStructInfo,
  3432. &cbStructInfo
  3433. ))
  3434. goto ErrorReturn;
  3435. fResult = TRUE;
  3436. CommonReturn:
  3437. *ppvStructInfo = pvStructInfo;
  3438. *pcbStructInfo = cbStructInfo;
  3439. return fResult;
  3440. ErrorReturn:
  3441. fResult = FALSE;
  3442. MakeCertFree(pvStructInfo);
  3443. pvStructInfo = NULL;
  3444. goto CommonReturn;
  3445. }
  3446. static BYTE rgbDhQ[21];
  3447. static CRYPT_UINT_BLOB DhQ = {0, NULL};
  3448. static BOOL GetDhParaFromCertFile(
  3449. OUT PCERT_X942_DH_PARAMETERS *ppX942DhPara
  3450. )
  3451. {
  3452. BOOL fResult;
  3453. PCCERT_CONTEXT pDhCert = NULL;
  3454. PCERT_X942_DH_PARAMETERS pX942DhPara = NULL;
  3455. BYTE *pb;
  3456. DWORD cb;
  3457. if (S_OK == RetrieveBLOBFromFile(wszDhParaCertFile, &cb, &pb)) {
  3458. pDhCert = CertCreateCertificateContext(X509_ASN_ENCODING, pb, cb);
  3459. UnmapViewOfFile(pb);
  3460. }
  3461. if (pDhCert == NULL)
  3462. goto DhParaCertFileError;
  3463. if (!DecodeAndAllocObject(
  3464. X942_DH_PARAMETERS,
  3465. pDhCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData,
  3466. pDhCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData,
  3467. (void **) &pX942DhPara,
  3468. &cb
  3469. ))
  3470. goto DhParaCertFileError;
  3471. fResult = TRUE;
  3472. CommonReturn:
  3473. CertFreeCertificateContext(pDhCert);
  3474. *ppX942DhPara = pX942DhPara;
  3475. return fResult;
  3476. DhParaCertFileError:
  3477. IDSwprintf(hModule, IDS_ERR_DH_PARA_FILE, wszDhParaCertFile);
  3478. MakeCertFree(pX942DhPara);
  3479. pX942DhPara = NULL;
  3480. fResult = FALSE;
  3481. goto CommonReturn;
  3482. }
  3483. static BOOL GetDhParaFromDssKey(
  3484. OUT PCERT_DSS_PARAMETERS *ppDssPara
  3485. )
  3486. {
  3487. BOOL fResult;
  3488. HCRYPTPROV hProv = 0;
  3489. HCRYPTKEY hKey = 0;
  3490. WCHAR *wszRegKeyName = NULL;
  3491. UUID TmpContainerUuid;
  3492. PCERT_DSS_PARAMETERS pDssPara = NULL;
  3493. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
  3494. DWORD cbPubKeyInfo;
  3495. DWORD cbDssPara;
  3496. // Create a temporary keyset to load the private key into
  3497. if (CoCreateGuid((GUID *)&TmpContainerUuid) != S_OK)
  3498. {
  3499. goto CreateKeyError;
  3500. }
  3501. if (NULL == (wszRegKeyName = (LPWSTR) MakeCertAlloc
  3502. (((sizeof(UUID) * 2 + 1) * sizeof(WCHAR)))))
  3503. goto CreateKeyError;
  3504. BytesToWStr(sizeof(UUID), &TmpContainerUuid, wszRegKeyName);
  3505. // Open a new key container
  3506. if (!CryptAcquireContextU(
  3507. &hProv,
  3508. wszRegKeyName,
  3509. wszSubjectProviderName,
  3510. dwSubjectProviderType,
  3511. CRYPT_NEWKEYSET // dwFlags
  3512. )) {
  3513. hProv = 0;
  3514. goto CreateKeyError;
  3515. }
  3516. if (0 == dwKeyBitLen)
  3517. dwKeyBitLen = 512;
  3518. // generate new DSS key in the key container
  3519. if (!CryptGenKey(
  3520. hProv,
  3521. AT_SIGNATURE,
  3522. (dwKeyBitLen << 16) | CRYPT_EXPORTABLE,
  3523. &hKey
  3524. ))
  3525. goto CreateKeyError;
  3526. else
  3527. CryptDestroyKey(hKey);
  3528. cbPubKeyInfo = 0;
  3529. CryptExportPublicKeyInfo(
  3530. hProv,
  3531. AT_SIGNATURE,
  3532. X509_ASN_ENCODING,
  3533. NULL, // pPubKeyInfo
  3534. &cbPubKeyInfo
  3535. );
  3536. if (cbPubKeyInfo == 0) {
  3537. PrintLastError(IDS_ERR_EXPORT_PUB);
  3538. goto ErrorReturn;
  3539. }
  3540. if (NULL == (pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) MakeCertAlloc(cbPubKeyInfo)))
  3541. goto ErrorReturn;
  3542. if (!CryptExportPublicKeyInfo(
  3543. hProv,
  3544. AT_SIGNATURE,
  3545. X509_ASN_ENCODING,
  3546. pPubKeyInfo,
  3547. &cbPubKeyInfo
  3548. )) {
  3549. PrintLastError(IDS_ERR_EXPORT_PUB);
  3550. goto ErrorReturn;
  3551. }
  3552. if (!DecodeAndAllocObject(
  3553. X509_DSS_PARAMETERS,
  3554. pPubKeyInfo->Algorithm.Parameters.pbData,
  3555. pPubKeyInfo->Algorithm.Parameters.cbData,
  3556. (void **) &pDssPara,
  3557. &cbDssPara
  3558. ))
  3559. goto CreateKeyError;
  3560. // Save away the DSS 'Q' parameter. It will be used in GetPublicKey()
  3561. // to update the DH parameters in the PublicKeyInfo
  3562. if (pDssPara->q.cbData <= sizeof(rgbDhQ)) {
  3563. memcpy(rgbDhQ, pDssPara->q.pbData, pDssPara->q.cbData);
  3564. DhQ.cbData = pDssPara->q.cbData;
  3565. DhQ.pbData = rgbDhQ;
  3566. }
  3567. fResult = TRUE;
  3568. CommonReturn:
  3569. if (hProv) {
  3570. // Delete the just created DSS key
  3571. CryptReleaseContext(hProv, 0);
  3572. CryptAcquireContextU(
  3573. &hProv,
  3574. wszRegKeyName,
  3575. wszSubjectProviderName,
  3576. dwSubjectProviderType,
  3577. CRYPT_DELETEKEYSET
  3578. );
  3579. }
  3580. MakeCertFree(wszRegKeyName);
  3581. MakeCertFree(pPubKeyInfo);
  3582. *ppDssPara = pDssPara;
  3583. return fResult;
  3584. CreateKeyError:
  3585. IDSwprintf(hModule,IDS_ERR_SUB_KEY_CREATE, wszSubjectKey);
  3586. ErrorReturn:
  3587. MakeCertFree(pDssPara);
  3588. pDssPara = NULL;
  3589. fResult = FALSE;
  3590. goto CommonReturn;
  3591. }
  3592. #ifndef DH3
  3593. #define DH3 (((DWORD)'D'<<8)+((DWORD)'H'<<16)+((DWORD)'3'<<24))
  3594. #endif
  3595. static BOOL CreateDh3PubKeyStruc(
  3596. IN PCERT_X942_DH_PARAMETERS pX942DhPara,
  3597. OUT PUBLICKEYSTRUC **ppPubKeyStruc,
  3598. OUT DWORD *pcbPubKeyStruc
  3599. )
  3600. {
  3601. BOOL fResult;
  3602. PUBLICKEYSTRUC *pPubKeyStruc = NULL;
  3603. DWORD cbPubKeyStruc;
  3604. BYTE *pbKeyBlob;
  3605. DHPUBKEY_VER3 *pCspPubKey;
  3606. BYTE *pbKey;
  3607. DWORD cbP;
  3608. DWORD cbQ;
  3609. DWORD cbJ;
  3610. DWORD cb;
  3611. cbP = pX942DhPara->p.cbData;
  3612. cbQ = pX942DhPara->q.cbData;
  3613. cbJ = pX942DhPara->j.cbData;
  3614. if (0 == cbQ) {
  3615. *ppPubKeyStruc = NULL;
  3616. *pcbPubKeyStruc = 0;
  3617. return TRUE;
  3618. }
  3619. // The CAPI public key representation consists of the following sequence:
  3620. // - PUBLICKEYSTRUC
  3621. // - DHPUBKEY_VER3
  3622. // - rgbP[cbP]
  3623. // - rgbQ[cbQ]
  3624. // - rgbG[cbP]
  3625. // - rgbJ[cbJ] -- optional
  3626. // - rgbY[cbP] -- will be omitted here
  3627. cbPubKeyStruc = sizeof(PUBLICKEYSTRUC) + sizeof(DHPUBKEY_VER3) +
  3628. cbP + cbQ + cbP + cbJ;
  3629. if (NULL == (pPubKeyStruc = (PUBLICKEYSTRUC *) MakeCertAlloc(
  3630. cbPubKeyStruc)))
  3631. goto ErrorReturn;
  3632. memset(pPubKeyStruc, 0, cbPubKeyStruc);
  3633. pbKeyBlob = (BYTE *) pPubKeyStruc;
  3634. pCspPubKey = (DHPUBKEY_VER3 *) (pbKeyBlob + sizeof(PUBLICKEYSTRUC));
  3635. pbKey = pbKeyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(DHPUBKEY_VER3);
  3636. pPubKeyStruc->bType = PUBLICKEYBLOB;
  3637. pPubKeyStruc->bVersion = 3;
  3638. pPubKeyStruc->aiKeyAlg = CALG_DH_SF;
  3639. pCspPubKey->magic = DH3;
  3640. pCspPubKey->bitlenP = cbP * 8;
  3641. pCspPubKey->bitlenQ = cbQ * 8;
  3642. pCspPubKey->bitlenJ = cbJ * 8;
  3643. pCspPubKey->DSSSeed.counter = 0xFFFFFFFF;
  3644. if (pX942DhPara->pValidationParams) {
  3645. PCERT_X942_DH_VALIDATION_PARAMS pValidationParams;
  3646. pValidationParams = pX942DhPara->pValidationParams;
  3647. if (0 != pValidationParams->pgenCounter &&
  3648. sizeof(pCspPubKey->DSSSeed.seed) ==
  3649. pValidationParams->seed.cbData) {
  3650. pCspPubKey->DSSSeed.counter =
  3651. pValidationParams->pgenCounter;
  3652. memcpy(pCspPubKey->DSSSeed.seed,
  3653. pValidationParams->seed.pbData,
  3654. sizeof(pCspPubKey->DSSSeed.seed));
  3655. }
  3656. }
  3657. // rgbP[cbP]
  3658. memcpy(pbKey, pX942DhPara->p.pbData, cbP);
  3659. pbKey += cbP;
  3660. // rgbQ[cbQ]
  3661. memcpy(pbKey, pX942DhPara->q.pbData, cbQ);
  3662. pbKey += cbQ;
  3663. // rgbG[cbP]
  3664. cb = pX942DhPara->g.cbData;
  3665. if (0 == cb || cb > cbP)
  3666. goto ErrorReturn;
  3667. memcpy(pbKey, pX942DhPara->g.pbData, cb);
  3668. if (cbP > cb)
  3669. memset(pbKey + cb, 0, cbP - cb);
  3670. pbKey += cbP;
  3671. // rgbJ[cbJ]
  3672. if (cbJ) {
  3673. memcpy(pbKey, pX942DhPara->j.pbData, cbJ);
  3674. pbKey += cbJ;
  3675. }
  3676. fResult = TRUE;
  3677. CommonReturn:
  3678. *ppPubKeyStruc = pPubKeyStruc;
  3679. *pcbPubKeyStruc = cbPubKeyStruc;
  3680. return fResult;
  3681. ErrorReturn:
  3682. MakeCertFree(pPubKeyStruc);
  3683. pPubKeyStruc = NULL;
  3684. cbPubKeyStruc = 0;
  3685. fResult = FALSE;
  3686. goto CommonReturn;
  3687. }
  3688. static BOOL IsDh3Csp()
  3689. {
  3690. BOOL fResult;
  3691. HCRYPTPROV hProv = 0;
  3692. HCRYPTKEY hKey = 0;
  3693. WCHAR *wszRegKeyName = NULL;
  3694. UUID TmpContainerUuid;
  3695. PCERT_X942_DH_PARAMETERS pX942DhPara = NULL;
  3696. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = NULL;
  3697. DWORD cbPubKeyInfo;
  3698. DWORD cbX942DhPara;
  3699. // Create a temporary keyset to load the private key into
  3700. if (CoCreateGuid((GUID *)&TmpContainerUuid) != S_OK)
  3701. {
  3702. goto CreateKeyError;
  3703. }
  3704. if (NULL == (wszRegKeyName = (LPWSTR) MakeCertAlloc
  3705. (((sizeof(UUID) * 2 + 1) * sizeof(WCHAR)))))
  3706. goto CreateKeyError;
  3707. BytesToWStr(sizeof(UUID), &TmpContainerUuid, wszRegKeyName);
  3708. // Open a new key container
  3709. if (!CryptAcquireContextU(
  3710. &hProv,
  3711. wszRegKeyName,
  3712. wszSubjectProviderName,
  3713. dwSubjectProviderType,
  3714. CRYPT_NEWKEYSET // dwFlags
  3715. )) {
  3716. hProv = 0;
  3717. goto CreateKeyError;
  3718. }
  3719. // generate new DH key in the key container
  3720. if (!CryptGenKey(
  3721. hProv,
  3722. AT_KEYEXCHANGE,
  3723. (512 << 16) | CRYPT_EXPORTABLE,
  3724. &hKey
  3725. ))
  3726. goto CreateKeyError;
  3727. else
  3728. CryptDestroyKey(hKey);
  3729. cbPubKeyInfo = 0;
  3730. CryptExportPublicKeyInfo(
  3731. hProv,
  3732. AT_KEYEXCHANGE,
  3733. X509_ASN_ENCODING,
  3734. NULL, // pPubKeyInfo
  3735. &cbPubKeyInfo
  3736. );
  3737. if (cbPubKeyInfo == 0) {
  3738. PrintLastError(IDS_ERR_EXPORT_PUB);
  3739. goto ErrorReturn;
  3740. }
  3741. if (NULL == (pPubKeyInfo = (PCERT_PUBLIC_KEY_INFO) MakeCertAlloc(cbPubKeyInfo)))
  3742. goto ErrorReturn;
  3743. if (!CryptExportPublicKeyInfo(
  3744. hProv,
  3745. AT_KEYEXCHANGE,
  3746. X509_ASN_ENCODING,
  3747. pPubKeyInfo,
  3748. &cbPubKeyInfo
  3749. )) {
  3750. PrintLastError(IDS_ERR_EXPORT_PUB);
  3751. goto ErrorReturn;
  3752. }
  3753. if (!DecodeAndAllocObject(
  3754. X942_DH_PARAMETERS,
  3755. pPubKeyInfo->Algorithm.Parameters.pbData,
  3756. pPubKeyInfo->Algorithm.Parameters.cbData,
  3757. (void **) &pX942DhPara,
  3758. &cbX942DhPara
  3759. ))
  3760. goto CreateKeyError;
  3761. if (pX942DhPara->q.cbData)
  3762. // Q para is only supported in Dh3 version of CSP
  3763. fResult = TRUE;
  3764. else
  3765. fResult = FALSE;
  3766. CommonReturn:
  3767. if (hProv) {
  3768. // Delete the just created DH key
  3769. CryptReleaseContext(hProv, 0);
  3770. CryptAcquireContextU(
  3771. &hProv,
  3772. wszRegKeyName,
  3773. wszSubjectProviderName,
  3774. dwSubjectProviderType,
  3775. CRYPT_DELETEKEYSET
  3776. );
  3777. }
  3778. MakeCertFree(wszRegKeyName);
  3779. MakeCertFree(pX942DhPara);
  3780. MakeCertFree(pPubKeyInfo);
  3781. return fResult;
  3782. CreateKeyError:
  3783. IDSwprintf(hModule,IDS_ERR_SUB_KEY_CREATE, wszSubjectKey);
  3784. ErrorReturn:
  3785. fResult = FALSE;
  3786. goto CommonReturn;
  3787. }
  3788. static BOOL GenDhKey(
  3789. IN HCRYPTPROV hProv,
  3790. IN DWORD dwFlags
  3791. )
  3792. {
  3793. BOOL fResult;
  3794. HCRYPTKEY hKey = 0;
  3795. PCERT_X942_DH_PARAMETERS pX942DhPara = NULL;
  3796. PCERT_DSS_PARAMETERS pDssPara = NULL;
  3797. PCRYPT_UINT_BLOB pP;
  3798. PCRYPT_UINT_BLOB pG;
  3799. DWORD cbP;
  3800. PUBLICKEYSTRUC *pDh3PubKeyStruc = NULL;
  3801. DWORD cbDh3PubKeyStruc;
  3802. BOOL fSetKeyPara;
  3803. if (wszDhParaCertFile) {
  3804. if (!GetDhParaFromCertFile(&pX942DhPara))
  3805. goto ErrorReturn;
  3806. CreateDh3PubKeyStruc(pX942DhPara, &pDh3PubKeyStruc, &cbDh3PubKeyStruc);
  3807. pP = &pX942DhPara->p;
  3808. pG = &pX942DhPara->g;
  3809. } else if (dwKeyBitLen > 1024 || IsDh3Csp()) {
  3810. // generate new keys in the key container
  3811. if (!CryptGenKey(
  3812. hProv,
  3813. AT_KEYEXCHANGE,
  3814. (dwKeyBitLen << 16) | dwFlags,
  3815. &hKey
  3816. )) {
  3817. hKey = 0;
  3818. goto CreateKeyError;
  3819. } else
  3820. goto SuccessReturn;
  3821. } else {
  3822. if (!GetDhParaFromDssKey(&pDssPara))
  3823. goto ErrorReturn;
  3824. pP = &pDssPara->p;
  3825. pG = &pDssPara->g;
  3826. }
  3827. cbP = pP->cbData;
  3828. if (!CryptGenKey(
  3829. hProv,
  3830. CALG_DH_SF,
  3831. ((cbP * 8) << 16) | CRYPT_PREGEN | dwFlags,
  3832. &hKey)) {
  3833. hKey = 0;
  3834. goto CreateKeyError;
  3835. }
  3836. fSetKeyPara = FALSE;
  3837. if (pDh3PubKeyStruc) {
  3838. CRYPT_DATA_BLOB Dh3Blob;
  3839. Dh3Blob.pbData = (PBYTE) pDh3PubKeyStruc;
  3840. Dh3Blob.cbData = cbDh3PubKeyStruc;
  3841. if (CryptSetKeyParam(
  3842. hKey,
  3843. KP_PUB_PARAMS,
  3844. (PBYTE) &Dh3Blob,
  3845. 0)) // dwFlags
  3846. fSetKeyPara = TRUE;
  3847. }
  3848. if (!fSetKeyPara) {
  3849. if (!CryptSetKeyParam(
  3850. hKey,
  3851. KP_P,
  3852. (PBYTE) pP,
  3853. 0)) // dwFlags
  3854. goto CreateKeyError;
  3855. // Note, the length of G can be less than length P. Pad with leading
  3856. // zeroes in little endian form.
  3857. if (pG->cbData < cbP) {
  3858. DWORD cbG = pG->cbData;
  3859. // We are done using P parameter. Overwrite with the G parameter and
  3860. // pad with leading zeroes in little endian form.
  3861. memcpy(pP->pbData, pG->pbData, cbG);
  3862. memset(pP->pbData + cbG, 0, cbP - cbG);
  3863. pG = pP;
  3864. }
  3865. if (!CryptSetKeyParam(
  3866. hKey,
  3867. KP_G,
  3868. (PBYTE) pG,
  3869. 0)) // dwFlags
  3870. goto CreateKeyError;
  3871. }
  3872. if (!CryptSetKeyParam(
  3873. hKey,
  3874. KP_X,
  3875. NULL, // pbData
  3876. 0)) // dwFlags
  3877. goto CreateKeyError;
  3878. SuccessReturn:
  3879. fResult = TRUE;
  3880. CommonReturn:
  3881. if (hKey)
  3882. CryptDestroyKey(hKey);
  3883. MakeCertFree(pDh3PubKeyStruc);
  3884. MakeCertFree(pX942DhPara);
  3885. MakeCertFree(pDssPara);
  3886. return fResult;
  3887. CreateKeyError:
  3888. IDSwprintf(hModule,IDS_ERR_SUB_KEY_CREATE, wszSubjectKey);
  3889. ErrorReturn:
  3890. fResult = FALSE;
  3891. goto CommonReturn;
  3892. }
  3893. static BOOL UpdateDhPublicKey(
  3894. IN OUT PCERT_PUBLIC_KEY_INFO *ppPubKeyInfo
  3895. )
  3896. {
  3897. BOOL fResult;
  3898. PCERT_PUBLIC_KEY_INFO pPubKeyInfo = *ppPubKeyInfo;
  3899. PCERT_X942_DH_PARAMETERS pX942DhPara = NULL;
  3900. DWORD cbDhPara;
  3901. PCERT_X942_DH_PARAMETERS pX942DhParaCertFile = NULL;
  3902. BYTE *pbReencodedPara = NULL;
  3903. DWORD cbReencodedPara;
  3904. BYTE *pbReencodedPubKeyInfo = NULL;
  3905. DWORD cbReencodedPubKeyInfo;
  3906. PCERT_PUBLIC_KEY_INFO pUpdatedPubKeyInfo = NULL;
  3907. DWORD cbUpdatedPubKeyInfo;
  3908. if (NULL == wszDhParaCertFile && 0 == DhQ.cbData)
  3909. return TRUE;
  3910. if (!DecodeAndAllocObject(
  3911. X942_DH_PARAMETERS,
  3912. pPubKeyInfo->Algorithm.Parameters.pbData,
  3913. pPubKeyInfo->Algorithm.Parameters.cbData,
  3914. (void **) &pX942DhPara,
  3915. &cbDhPara
  3916. )) {
  3917. PrintLastError(IDS_ERR_EXPORT_PUB);
  3918. goto ErrorReturn;
  3919. }
  3920. if (wszDhParaCertFile) {
  3921. if (!GetDhParaFromCertFile(&pX942DhParaCertFile))
  3922. goto ErrorReturn;
  3923. if (!CertCompareIntegerBlob(&pX942DhPara->p, &pX942DhParaCertFile->p))
  3924. goto DhParaCertFileError;
  3925. if (!CertCompareIntegerBlob(&pX942DhPara->g, &pX942DhParaCertFile->g))
  3926. goto DhParaCertFileError;
  3927. // Use Dh parameters from the CertFile
  3928. MakeCertFree(pX942DhPara);
  3929. pX942DhPara = pX942DhParaCertFile;
  3930. pX942DhParaCertFile = NULL;
  3931. } else if (pX942DhPara->q.cbData) {
  3932. MakeCertFree(pX942DhPara);
  3933. return TRUE;
  3934. } else
  3935. // Use Q parameter saved away when the DH key was generated
  3936. pX942DhPara->q = DhQ;
  3937. // Re-encode the DH parameters
  3938. if (!EncodeAndAllocObject(
  3939. X942_DH_PARAMETERS,
  3940. pX942DhPara,
  3941. &pbReencodedPara,
  3942. &cbReencodedPara
  3943. )) {
  3944. PrintLastError(IDS_ERR_EXPORT_PUB);
  3945. goto ErrorReturn;
  3946. }
  3947. if (0 == strcmp(szOID_RSA_DH, pPubKeyInfo->Algorithm.pszObjId))
  3948. pPubKeyInfo->Algorithm.pszObjId = szOID_ANSI_X942_DH;
  3949. // Re-encode the PublicKeyInfo using the above re-encoded DH parameters
  3950. pPubKeyInfo->Algorithm.Parameters.pbData = pbReencodedPara;
  3951. pPubKeyInfo->Algorithm.Parameters.cbData = cbReencodedPara;
  3952. if (!EncodeAndAllocObject(
  3953. X509_PUBLIC_KEY_INFO,
  3954. pPubKeyInfo,
  3955. &pbReencodedPubKeyInfo,
  3956. &cbReencodedPubKeyInfo
  3957. )) {
  3958. PrintLastError(IDS_ERR_EXPORT_PUB);
  3959. goto ErrorReturn;
  3960. }
  3961. // Decode to get the updated public key info
  3962. if (!DecodeAndAllocObject(
  3963. X509_PUBLIC_KEY_INFO,
  3964. pbReencodedPubKeyInfo,
  3965. cbReencodedPubKeyInfo,
  3966. (void **) &pUpdatedPubKeyInfo,
  3967. &cbUpdatedPubKeyInfo
  3968. )) {
  3969. PrintLastError(IDS_ERR_EXPORT_PUB);
  3970. goto ErrorReturn;
  3971. }
  3972. fResult = TRUE;
  3973. CommonReturn:
  3974. MakeCertFree(pbReencodedPubKeyInfo);
  3975. MakeCertFree(pbReencodedPara);
  3976. MakeCertFree(pX942DhPara);
  3977. MakeCertFree(pX942DhParaCertFile);
  3978. MakeCertFree(pPubKeyInfo);
  3979. *ppPubKeyInfo = pUpdatedPubKeyInfo;
  3980. return fResult;
  3981. DhParaCertFileError:
  3982. IDSwprintf(hModule, IDS_ERR_DH_PARA_FILE, wszDhParaCertFile);
  3983. ErrorReturn:
  3984. MakeCertFree(pUpdatedPubKeyInfo);
  3985. pUpdatedPubKeyInfo = NULL;
  3986. fResult = FALSE;
  3987. goto CommonReturn;
  3988. }