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.

2664 lines
80 KiB

  1. //-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1997
  6. //
  7. // File: tdecode.cpp
  8. //
  9. // Contents: API testing of CryptEncodeObject/CryptDecodeObject.
  10. //
  11. // History: 22-January-97 xiaohs created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "tdecode.h"
  15. //--------------------------------------------------------------------------
  16. // Globals
  17. //--------------------------------------------------------------------------
  18. //the count of errors in the program
  19. DWORD g_dwErrCnt=0;
  20. HCRYPTPROV g_hProv=NULL;
  21. //--------------------------------------------------------------------------
  22. // The utility function to display the parameters for the input.
  23. //--------------------------------------------------------------------------
  24. static void Usage(void)
  25. {
  26. printf("\n");
  27. printf("Usage: tdecode [options] <FileTypes><Filename>\n");
  28. printf("\n");
  29. printf("FileTypes are(case sensitive):\n");
  30. printf(" C -This is a certificate file\n");
  31. printf(" R -This is a certificate request blob file\n");
  32. printf(" S -This is a signed message file\n");
  33. printf("\n");
  34. printf("Options are(case sensitive):\n");
  35. printf(" -i - A complete test on cbEncoded in CryptDecodeObject\n");
  36. printf(" Default does not do the check\n");
  37. printf(" -o - A complete test on *pcbStructInfo on CryptDecodeObject\n");
  38. printf(" Default does not do the check\n");
  39. printf(" -b - A complete test on *pcbStructInfo and cbEncoded\n");
  40. printf(" Default does not do the check\n");
  41. printf("\n");
  42. return;
  43. }
  44. //--------------------------------------------------------------------------
  45. // The utility function to display a message that the test is not exeucted
  46. //--------------------------------------------------------------------------
  47. static void NotExecuted(void)
  48. {
  49. printf("*****************************************************\n");
  50. printf(" Summary information for TDecode Test \n");
  51. printf("*****************************************************\n"); \
  52. printf("\n");
  53. printf("The test is not executed!\n");
  54. return;
  55. }
  56. //--------------------------------------------------------------------------
  57. // The main program that Decode/Encode Certifitcate, Certificate Request,
  58. // and CRL.
  59. //--------------------------------------------------------------------------
  60. void _cdecl main(int argc, char * argv[])
  61. {
  62. BOOL fStructLengthCheck=FALSE;
  63. BOOL fBLOBLengthCheck=FALSE;
  64. DWORD dwFileType=0;
  65. LPSTR pszFilename=NULL;
  66. BYTE pbByte[100]=
  67. {0x00, 0xa1, 0x23, 0x45, 0x56, 0x78, 0x9a, 0xbc,0xdf,0xee,
  68. 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0XFF, 0xA6, 0x8f,0xe4, 0x0f,
  69. 0x00, 0xa1, 0x23, 0x45, 0x56, 0x78, 0x9a, 0xbc,0xdf,0xee,
  70. 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0XFF, 0xA6, 0x8f,0xe4, 0x0f,
  71. 0x00, 0xa1, 0x23, 0x45, 0x56, 0x78, 0x9a, 0xbc,0xdf,0xee,
  72. 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0XFF, 0xA6, 0x8f,0xe4, 0x0f,
  73. 0x00, 0xa1, 0x23, 0x45, 0x56, 0x78, 0x9a, 0xbc,0xdf,0xee,
  74. 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0XFF, 0xA6, 0x8f,0xe4, 0x0f,
  75. 0x00, 0xa1, 0x23, 0x45, 0x56, 0x78, 0x9a, 0xbc,0xdf,0xee,
  76. 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0XFF, 0xA6, 0x8f,0xe4, 0x0f};
  77. //parsing through the command line input parameters
  78. while (--argc>0)
  79. {
  80. if (**++argv == '-')
  81. {
  82. switch(argv[0][1])
  83. {
  84. case 'i':
  85. fBLOBLengthCheck=TRUE;
  86. break;
  87. case 'o':
  88. fStructLengthCheck=TRUE;
  89. break;
  90. case 'b':
  91. fBLOBLengthCheck=TRUE;
  92. fStructLengthCheck=TRUE;
  93. break;
  94. default:
  95. Usage();
  96. NotExecuted();
  97. return;
  98. }
  99. }
  100. else
  101. {
  102. //parsing through the file name
  103. switch(**argv)
  104. {
  105. case 'C':
  106. dwFileType=CERT_CRL_FILE;
  107. break;
  108. case 'R':
  109. dwFileType=CERT_REQUEST_FILE;
  110. break;
  111. case 'S':
  112. dwFileType=SIGNED_MSG_FILE;
  113. break;
  114. default:
  115. Usage();
  116. NotExecuted();
  117. return;
  118. }
  119. //make sure there is a file name specified
  120. if(argv[0][1]=='\0')
  121. {
  122. Usage();
  123. NotExecuted();
  124. return;
  125. }
  126. //get the file name
  127. pszFilename = &(argv[0][1]);
  128. }
  129. }
  130. //if the file name is NULL, something is wrong in the input parameter
  131. if(!pszFilename)
  132. {
  133. Usage();
  134. NotExecuted();
  135. return;
  136. }
  137. //acquireContext
  138. TESTC(CryptAcquireContext(&g_hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT),TRUE)
  139. //test PKCS_UTC_TIME
  140. TESTC(VerifyPKCS_UTC_TIME(fStructLengthCheck, fBLOBLengthCheck),TRUE)
  141. //test PKCS_TIME_REQUEST
  142. TESTC(VerifyPKCS_TIME_REQUEST(fStructLengthCheck, fBLOBLengthCheck),TRUE)
  143. //decode the corresponding file types.
  144. switch(dwFileType)
  145. {
  146. case CERT_CRL_FILE:
  147. TESTC(DecodeCertFile(pszFilename,fStructLengthCheck,
  148. fBLOBLengthCheck),TRUE)
  149. break;
  150. case CERT_REQUEST_FILE:
  151. TESTC(DecodeCertReqFile(pszFilename,fStructLengthCheck,
  152. fBLOBLengthCheck),TRUE)
  153. break;
  154. case SIGNED_MSG_FILE:
  155. TESTC(DecodeSignedMsgFile(pszFilename,fStructLengthCheck,
  156. fBLOBLengthCheck),TRUE)
  157. break;
  158. default:
  159. break;
  160. }
  161. TCLEANUP:
  162. //release the CSP
  163. if(g_hProv)
  164. TCHECK(CryptReleaseContext(g_hProv,0),TRUE);
  165. //print out the test result
  166. DisplayTestResult(g_dwErrCnt);
  167. }
  168. //--------------------------------------------------------------------------
  169. // Local Functions
  170. //--------------------------------------------------------------------------
  171. ///////////////////////////////////////////////////////////////////////////
  172. //Error Manipulations
  173. //--------------------------------------------------------------------------
  174. // DisplayTestResult
  175. //--------------------------------------------------------------------------
  176. void DisplayTestResult(DWORD dwErrCnt)
  177. {
  178. printf("*****************************************************\n");
  179. printf(" Summary information for TDecode Test \n");
  180. printf("*****************************************************\n");
  181. printf("\n");
  182. if(!dwErrCnt)
  183. printf("This test succeeded!\n");
  184. else
  185. printf("This test failed with total %d errors!\n",dwErrCnt);
  186. return;
  187. }
  188. //--------------------------------------------------------------------------
  189. // Validate the return code is the same as expected. If they are not the
  190. // same, increment the error count and print out the file name and the line
  191. // number.
  192. //--------------------------------------------------------------------------
  193. BOOL Validate(DWORD dwErr, BOOL fSame, char *szFile, DWORD dwLine)
  194. {
  195. if(fSame)
  196. return TRUE;
  197. printf("*****************************************************\n");
  198. printf("Error: %d 0x%x occurred at file %s line %d\n\n",
  199. dwErr, dwErr, szFile, dwLine);
  200. g_dwErrCnt++;
  201. return FALSE;
  202. }
  203. //--------------------------------------------------------------------------
  204. // Output the two BLOBs. One is the original one, the other is the
  205. // BLOB encoded by pvStructInfo.
  206. //--------------------------------------------------------------------------
  207. void OutputError(LPCSTR lpszStructType, DWORD cbSecondEncoded, DWORD cbEncoded,
  208. BYTE *pbSecondEncoded, BYTE *pbEncoded)
  209. {
  210. DWORD cbMin=0;
  211. printf("------------------------------------------------------\n");
  212. printf("An inconsistency in BLOBs has been found!\n");
  213. //print out the lpszStructType
  214. if(((DWORD_PTR)lpszStructType)>>8 == 0)
  215. printf("The lpszStructType is %d.\n",(DWORD)(DWORD_PTR)lpszStructType);
  216. else
  217. printf("The lpszStructType is %s.\n",lpszStructType);
  218. printf("\n");
  219. //print out the size of BLOBs
  220. printf("The original cbEncoded is %d.\n",cbEncoded);
  221. printf("The new cbEncoded is %d.\n",cbSecondEncoded);
  222. printf("\n");
  223. //see if the min of cbEncoded and cbSecondEncoded is the same
  224. if(cbSecondEncoded>cbEncoded)
  225. cbMin=cbEncoded;
  226. else
  227. cbMin=cbSecondEncoded;
  228. if(memcmp(pbSecondEncoded,pbEncoded,cbMin)==0)
  229. printf("The two blobs are the same up to %dth byte.\n",cbMin);
  230. //print out all the bytes in the BLOBs
  231. printf("The original BLOB is:\n");
  232. PrintBytes(" ", pbEncoded, cbEncoded);
  233. printf("\n");
  234. printf("The new BLOB is:\n");
  235. PrintBytes(" ",pbSecondEncoded, cbSecondEncoded);
  236. return;
  237. }
  238. //--------------------------------------------------------------------------
  239. // Print out the Byte in 16 bytes per row and their corresponding HEX.
  240. //--------------------------------------------------------------------------
  241. void PrintBytes(LPCSTR pszHdr, BYTE *pb, DWORD cbSize)
  242. {
  243. ULONG cb, i;
  244. while (cbSize > 0)
  245. {
  246. printf("%s", pszHdr);
  247. cb = min(CROW, cbSize);
  248. cbSize -= cb;
  249. for (i = 0; i<cb; i++)
  250. printf(" %02X", pb[i]);
  251. for (i = cb; i<CROW; i++)
  252. printf(" ");
  253. printf(" '");
  254. for (i = 0; i<cb; i++)
  255. if (pb[i] >= 0x20 && pb[i] <= 0x7f)
  256. printf("%c", pb[i]);
  257. else
  258. printf(".");
  259. pb += cb;
  260. printf("'\n");
  261. }
  262. }
  263. ///////////////////////////////////////////////////////////////////////////
  264. //General Testing routings
  265. //--------------------------------------------------------------------------
  266. // Validate CryptEncodeObject/CryptDecodeObject handle the NULL or invalid
  267. // parameters correctly.
  268. //--------------------------------------------------------------------------
  269. BOOL ParameterTest(LPCSTR lpszStructType, DWORD cbEncoded, BYTE *pbEncoded)
  270. {
  271. BOOL fSucceeded=FALSE;
  272. DWORD cbStructInfo=0;
  273. void *pvStructInfo=NULL;
  274. DWORD cbCorrectSize=0;
  275. DWORD cbLengthOnly=0;
  276. DWORD cbSecondEncoded=0;
  277. BYTE *pbSecondEncoded=NULL;
  278. DWORD dwReturn=0;
  279. DWORD dwEncodingType=CRYPT_ENCODE_TYPE;
  280. //init
  281. assert(cbEncoded);
  282. assert(pbEncoded);
  283. assert(lpszStructType);
  284. //We have different decoding type for PKCS7_SIGNER_INFO
  285. if((DWORD_PTR)(lpszStructType)==(DWORD_PTR)(PKCS7_SIGNER_INFO))
  286. dwEncodingType=MSG_ENCODING_TYPE;
  287. cbSecondEncoded=cbEncoded;
  288. pbSecondEncoded=(BYTE *)SAFE_ALLOC(cbEncoded);
  289. CHECK_POINTER(pbSecondEncoded)
  290. //Decode the BLOB correctly
  291. cbStructInfo=1000;
  292. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,
  293. cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,NULL,&cbStructInfo),TRUE)
  294. cbLengthOnly=cbStructInfo;
  295. //allocate the memory
  296. pvStructInfo=SAFE_ALLOC(cbStructInfo);
  297. CHECK_POINTER(pvStructInfo);
  298. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,
  299. cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),TRUE)
  300. cbCorrectSize=cbStructInfo;
  301. //Test incorrect ENCODING type
  302. //pass X509_NDR_ENCODING
  303. TESTC(CryptDecodeObject(X509_NDR_ENCODING,lpszStructType,pbEncoded,
  304. cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),FALSE)
  305. // Since we do not know the correct return code, make sure at least
  306. //S_OK is not returned.
  307. TCHECK(GetLastError()!=S_OK, TRUE);
  308. TESTC(CryptEncodeObject(X509_NDR_ENCODING, lpszStructType,pvStructInfo,
  309. pbSecondEncoded,&cbSecondEncoded),FALSE)
  310. TCHECK(GetLastError()!=S_OK, TRUE);
  311. //pass X509_NDR_ENCODING|X509_ASN_ENCODING
  312. TESTC(CryptDecodeObject(X509_NDR_ENCODING|X509_ASN_ENCODING,lpszStructType,pbEncoded,
  313. cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),FALSE)
  314. TCHECK(GetLastError()!=S_OK, TRUE);
  315. TESTC(CryptEncodeObject(X509_NDR_ENCODING|X509_ASN_ENCODING, lpszStructType,pvStructInfo,
  316. pbSecondEncoded,&cbSecondEncoded),FALSE)
  317. TCHECK(GetLastError()!=S_OK, TRUE);
  318. //Test invalid/unsupported lpszStructType
  319. //passing NULL for lpszStructType
  320. TESTC(CryptDecodeObject(dwEncodingType,CRYPT_ENCODE_DECODE_NONE,pbEncoded,
  321. cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),FALSE)
  322. TCHECK(GetLastError()!=S_OK, TRUE);
  323. TESTC(CryptEncodeObject(dwEncodingType, CRYPT_ENCODE_DECODE_NONE,pvStructInfo,
  324. pbSecondEncoded,&cbSecondEncoded),FALSE)
  325. TCHECK(GetLastError()!=S_OK, TRUE);
  326. //passing invalid lpszStructType
  327. TESTC(CryptDecodeObject(dwEncodingType,INVALID_LPSZSTRUCTTYPE,pbEncoded,
  328. cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),FALSE)
  329. TCHECK(GetLastError()!=S_OK, TRUE);
  330. TESTC(CryptEncodeObject(dwEncodingType, INVALID_LPSZSTRUCTTYPE,pvStructInfo,
  331. pbSecondEncoded,&cbSecondEncoded),FALSE)
  332. TCHECK(GetLastError()!=S_OK, TRUE);
  333. // CryptEncodeObject: pbEncoded is not NULL while cbEncoded is 0.
  334. cbSecondEncoded=0;
  335. TESTC(CryptEncodeObject(dwEncodingType, lpszStructType,pvStructInfo,
  336. pbSecondEncoded,&cbSecondEncoded),FALSE)
  337. TCHECK(GetLastError(),ERROR_MORE_DATA);
  338. //CryptDecodeObject: pvStructInfo is not NULL while pcbStructInfo is 0
  339. cbStructInfo=0;
  340. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,
  341. cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),FALSE)
  342. TCHECK(cbStructInfo,cbCorrectSize);
  343. TCHECK(GetLastError(),ERROR_MORE_DATA);
  344. //CryptDecodeObject: Pass invalid blobs
  345. cbSecondEncoded=(DWORD)(cbEncoded/2);
  346. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,
  347. cbEncoded-cbSecondEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),FALSE)
  348. dwReturn=GetLastError();
  349. // Ignore ASN1_ERR_EOD
  350. if (dwReturn != 0x80093102) {
  351. TCHECKALL(dwReturn,CRYPT_E_BAD_ENCODE, CRYPT_E_OSS_ERROR+DATA_ERROR);
  352. }
  353. //CryptDecodeObject: Pass cbEncoded=0
  354. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,
  355. 0,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),FALSE)
  356. dwReturn=GetLastError();
  357. if (dwReturn != 0x80093102) {
  358. TCHECKALL(dwReturn,CRYPT_E_BAD_ENCODE, CRYPT_E_OSS_ERROR+MORE_INPUT);
  359. }
  360. //CryptDecodeObject: lpszStructType mismatches pbEncoded
  361. TESTC(MismatchTest(lpszStructType, cbEncoded, pbEncoded,cbLengthOnly),TRUE)
  362. fSucceeded=TRUE;
  363. TCLEANUP:
  364. //release memory
  365. SAFE_FREE(pbSecondEncoded)
  366. SAFE_FREE(pvStructInfo)
  367. return fSucceeded;
  368. }
  369. //--------------------------------------------------------------------------
  370. // The routine to test CryptDecodeObject() handles the mismatch between
  371. // lpszStructType and pbEncoded
  372. //
  373. // PreCondition: This routine assumes that lpszStructType's high-order
  374. // word is 0 and the low order word specifies the integer
  375. // identifier for the type of the given structure.
  376. //
  377. // cbCorrectStructInfo is the correct size for pvStructInfo in CryptDecodeObject
  378. //--------------------------------------------------------------------------
  379. BOOL MismatchTest(LPCSTR lpszStructType, DWORD cbEncoded, BYTE *pbEncoded,
  380. DWORD cbCorrectStructInfo)
  381. {
  382. BOOL fSucceeded=FALSE;
  383. DWORD dwrgSize=0;
  384. DWORD dwError=0;
  385. ULONG iIndex=0;
  386. void *pvStructInfo=NULL;
  387. DWORD cbStructInfo=cbCorrectStructInfo;
  388. DWORD dwEncodingType=CRYPT_ENCODE_TYPE;
  389. LPCSTR rglpszStructType[]={X509_CERT_TO_BE_SIGNED,
  390. X509_CERT_CRL_TO_BE_SIGNED,
  391. X509_CERT_REQUEST_TO_BE_SIGNED,
  392. X509_EXTENSIONS,
  393. X509_NAME_VALUE,
  394. X509_NAME,
  395. X509_PUBLIC_KEY_INFO,
  396. X509_AUTHORITY_KEY_ID,
  397. X509_KEY_ATTRIBUTES,
  398. X509_KEY_USAGE_RESTRICTION,
  399. X509_ALTERNATE_NAME,
  400. X509_BASIC_CONSTRAINTS,
  401. X509_KEY_USAGE,
  402. X509_BASIC_CONSTRAINTS2,
  403. X509_CERT_POLICIES,
  404. PKCS_UTC_TIME,
  405. PKCS_TIME_REQUEST,
  406. RSA_CSP_PUBLICKEYBLOB,
  407. PKCS7_SIGNER_INFO};
  408. //init
  409. dwrgSize=sizeof(rglpszStructType)/sizeof(rglpszStructType[0]);
  410. //We have different decoding type for PKCS7_SIGNER_INFO
  411. if((DWORD_PTR)(lpszStructType)==(DWORD_PTR)(PKCS7_SIGNER_INFO))
  412. dwEncodingType=MSG_ENCODING_TYPE;
  413. pvStructInfo=SAFE_ALLOC(cbCorrectStructInfo);
  414. CHECK_POINTER(pvStructInfo);
  415. //start to decode the BLOB. Should fail when lpszStructType mismatches pbEncoded
  416. for(iIndex=0; iIndex<dwrgSize; iIndex++)
  417. {
  418. cbStructInfo=cbCorrectStructInfo;
  419. //skip the test if lpszStructType==X509_NAME_VALUE since the X509_NAME_VALUE
  420. //allows any encoded type. It has the dwValueType CERT_RDN_ENCODED_BLOB.
  421. if((DWORD_PTR)(rglpszStructType[iIndex])==(DWORD_PTR)X509_NAME_VALUE)
  422. continue;
  423. //if lpszStructType is the correct type, TRUE should be returned.
  424. if((DWORD_PTR)lpszStructType==(DWORD_PTR)(rglpszStructType[iIndex]))
  425. {
  426. TESTC(CryptDecodeObject(dwEncodingType, rglpszStructType[iIndex],
  427. pbEncoded,cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),TRUE)
  428. }
  429. else
  430. {
  431. //error should occur
  432. TESTC(CryptDecodeObject(dwEncodingType, rglpszStructType[iIndex],
  433. pbEncoded,cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),FALSE)
  434. //test the return code
  435. dwError=GetLastError();
  436. //we are not sure that should be expected here. The following error has
  437. //occurred:
  438. //E_INVALIDARG, CRYPT_E_OSS_ERROR+PDU_MISMATCH, +DATA_ERROR, or
  439. //+MORE_INPUT
  440. //make sure at lease S_OK is not returned
  441. TCHECK(dwError!=S_OK, TRUE);
  442. }
  443. }
  444. fSucceeded=TRUE;
  445. TCLEANUP:
  446. //release the memory
  447. SAFE_FREE(pvStructInfo)
  448. return fSucceeded;
  449. }
  450. ///////////////////////////////////////////////////////////////////////////////
  451. //General Decode/Encode Testing routines
  452. //--------------------------------------------------------------------------
  453. // Get a BLOB based on an input file.
  454. //
  455. //--------------------------------------------------------------------------
  456. BOOL RetrieveBLOBfromFile(LPSTR pszFileName,DWORD *pcbEncoded,BYTE **ppbEncoded)
  457. {
  458. BOOL fSucceeded=FALSE;
  459. DWORD cCount=0;
  460. HANDLE hFile=NULL;
  461. assert(pszFileName);
  462. assert(pcbEncoded);
  463. assert(ppbEncoded);
  464. if((hFile = CreateFile(pszFileName,
  465. GENERIC_READ,
  466. 0, NULL, OPEN_EXISTING, 0, NULL))==INVALID_HANDLE_VALUE)
  467. PROCESS_ERR_GOTO("Can not open the file!\n");
  468. //Get the size of the file
  469. cCount=GetFileSize(hFile, NULL);
  470. //make sure the file is not empty
  471. TESTC(cCount!=0, TRUE)
  472. //allocate memory
  473. *ppbEncoded=(BYTE *)SAFE_ALLOC(cCount);
  474. *pcbEncoded=cCount;
  475. //fill the buffer
  476. TESTC(ReadFile( hFile,*ppbEncoded, *pcbEncoded,&cCount,NULL),TRUE)
  477. //make sure that we have the right number of bytes
  478. TESTC(cCount,*pcbEncoded)
  479. fSucceeded=TRUE;
  480. TCLEANUP:
  481. if(hFile)
  482. CloseHandle(hFile);
  483. return fSucceeded;
  484. }
  485. //--------------------------------------------------------------------------
  486. // A general routine to encode the singer info struct and
  487. // add Attributes to the structur if there was none
  488. //
  489. //--------------------------------------------------------------------------
  490. BOOL EncodeSignerInfoWAttr(PCMSG_SIGNER_INFO pSignerInfo,DWORD *pbSignerEncoded,
  491. BYTE **ppbSignerEncoded)
  492. {
  493. BOOL fSucceeded=FALSE;
  494. //add attribute to the CMSG_SINGER_INFO struct if necessary
  495. //make up the attributes
  496. BYTE rgAttribValue1[]={0x02, 0x02, 0x11, 0x11};
  497. BYTE rgAttribValue2[]={0x02, 0x02, 0x11, 0x11};
  498. //make 3 CRYPT_ATTRIBUTE
  499. CRYPT_ATTRIBUTE rgCryptAttribute[3];
  500. CRYPT_ATTR_BLOB rgAttribBlob[3];
  501. rgAttribBlob[0].cbData=sizeof(rgAttribValue2);
  502. rgAttribBlob[0].pbData=rgAttribValue2;
  503. rgAttribBlob[1].cbData=sizeof(rgAttribValue2);
  504. rgAttribBlob[1].pbData=rgAttribValue2;
  505. rgAttribBlob[2].cbData=sizeof(rgAttribValue1);
  506. rgAttribBlob[2].pbData=rgAttribValue1;
  507. rgCryptAttribute[0].pszObjId="1.2.3.4";
  508. rgCryptAttribute[0].cValue=0;
  509. rgCryptAttribute[0].rgValue=NULL;
  510. rgCryptAttribute[1].pszObjId="1.2.3.4";
  511. rgCryptAttribute[1].cValue=1;
  512. rgCryptAttribute[1].rgValue=rgAttribBlob;
  513. rgCryptAttribute[2].pszObjId="1.2.3.4";
  514. rgCryptAttribute[2].cValue=3;
  515. rgCryptAttribute[2].rgValue=rgAttribBlob;
  516. //if pSingerInfo does not include any attributes, add attributes
  517. //to the struct
  518. if(pSignerInfo->AuthAttrs.cAttr==0)
  519. {
  520. pSignerInfo->AuthAttrs.cAttr=1;
  521. pSignerInfo->AuthAttrs.rgAttr=rgCryptAttribute;
  522. }
  523. if(pSignerInfo->UnauthAttrs.cAttr==0)
  524. {
  525. pSignerInfo->AuthAttrs.cAttr=3;
  526. pSignerInfo->AuthAttrs.rgAttr=rgCryptAttribute;
  527. }
  528. //encode the struct
  529. TESTC(CryptEncodeObject(MSG_ENCODING_TYPE,PKCS7_SIGNER_INFO,
  530. pSignerInfo,NULL,pbSignerEncoded),TRUE)
  531. //allocate memory
  532. *ppbSignerEncoded=(BYTE *)SAFE_ALLOC(*pbSignerEncoded);
  533. CHECK_POINTER(*ppbSignerEncoded);
  534. //encode
  535. TESTC(CryptEncodeObject(MSG_ENCODING_TYPE,PKCS7_SIGNER_INFO,
  536. pSignerInfo,*ppbSignerEncoded,pbSignerEncoded),TRUE)
  537. fSucceeded=TRUE;
  538. TCLEANUP:
  539. return fSucceeded;
  540. }
  541. //--------------------------------------------------------------------------
  542. // A general routine compare two time stamp request
  543. //
  544. //--------------------------------------------------------------------------
  545. BOOL CompareTimeStampRequest(CRYPT_TIME_STAMP_REQUEST_INFO *pReqNew,
  546. CRYPT_TIME_STAMP_REQUEST_INFO *pReqOld)
  547. {
  548. BOOL fSucceeded=FALSE;
  549. DWORD iIndex=0;
  550. DWORD iValue=0;
  551. TESTC(_stricmp(pReqNew->pszTimeStampAlgorithm,
  552. pReqOld->pszTimeStampAlgorithm),0)
  553. TESTC(_stricmp(pReqNew->pszContentType, pReqOld->pszContentType),0)
  554. TESTC(pReqNew->Content.cbData, pReqOld->Content.cbData)
  555. TESTC(memcmp(pReqNew->Content.pbData,pReqOld->Content.pbData,
  556. pReqNew->Content.cbData),0)
  557. TESTC(pReqNew->cAttribute, pReqOld->cAttribute)
  558. for(iIndex=0; iIndex<pReqNew->cAttribute;iIndex++)
  559. {
  560. TESTC(_stricmp(pReqNew->rgAttribute[iIndex].pszObjId,
  561. pReqOld->rgAttribute[iIndex].pszObjId),0)
  562. TESTC(pReqNew->rgAttribute[iIndex].cValue,
  563. pReqOld->rgAttribute[iIndex].cValue)
  564. for(iValue=0;iValue<pReqNew->rgAttribute[iIndex].cValue;iValue++)
  565. {
  566. TESTC(pReqNew->rgAttribute[iIndex].rgValue[iValue].cbData,
  567. pReqOld->rgAttribute[iIndex].rgValue[iValue].cbData)
  568. TESTC(memcmp(pReqNew->rgAttribute[iIndex].rgValue[iValue].pbData,
  569. pReqOld->rgAttribute[iIndex].rgValue[iValue].pbData,
  570. pReqOld->rgAttribute[iIndex].rgValue[iValue].cbData),0)
  571. }
  572. }
  573. fSucceeded=TRUE;
  574. TCLEANUP:
  575. return fSucceeded;
  576. }
  577. //--------------------------------------------------------------------------
  578. // A general routine to verify the algorithm parameters is NULL.
  579. //
  580. // cbData==2 and pbData=0x05 0x00
  581. //--------------------------------------------------------------------------
  582. BOOL VerifyAlgorithParam(PCRYPT_ALGORITHM_IDENTIFIER pAlgorithm)
  583. {
  584. BOOL fSucceeded=FALSE;
  585. TESTC((pAlgorithm->Parameters).cbData, 2);
  586. TESTC((BYTE)((pAlgorithm->Parameters).pbData[0])==(BYTE)5,TRUE);
  587. TESTC((BYTE)((pAlgorithm->Parameters).pbData[1])==(BYTE)0,TRUE);
  588. fSucceeded=TRUE;
  589. TCLEANUP:
  590. return fSucceeded;
  591. }
  592. //--------------------------------------------------------------------------
  593. // A general routine to verify the PKCS_UTC_TIME
  594. //
  595. //--------------------------------------------------------------------------
  596. BOOL VerifyPKCS_UTC_TIME(BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  597. {
  598. BOOL fSucceeded=FALSE;
  599. DWORD cbEncoded=0;
  600. BYTE *pbEncoded=NULL;
  601. DWORD dwError;
  602. FILETIME FileTime;
  603. //setup the struct
  604. FileTime.dwLowDateTime=0;
  605. FileTime.dwHighDateTime=31457160;
  606. //encode the struct into a BLOB
  607. TESTC(CryptEncodeObject(CRYPT_ENCODE_TYPE,PKCS_UTC_TIME,
  608. &FileTime,NULL,&cbEncoded),TRUE)
  609. pbEncoded=(BYTE *)SAFE_ALLOC(cbEncoded);
  610. CHECK_POINTER(pbEncoded)
  611. TESTC(CryptEncodeObject(CRYPT_ENCODE_TYPE,PKCS_UTC_TIME,
  612. &FileTime,pbEncoded,&cbEncoded),TRUE)
  613. //decode the struct with COPY and NOCOPY options
  614. TESTC(DecodeGenericBLOB(PKCS_UTC_TIME,cbEncoded, pbEncoded, CRYPT_DECODE_COPY_FLAG,
  615. TRUE,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  616. TESTC(DecodeGenericBLOB(PKCS_UTC_TIME,cbEncoded, pbEncoded, CRYPT_DECODE_NOCOPY_FLAG,
  617. TRUE,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  618. fSucceeded=TRUE;
  619. TCLEANUP:
  620. //print out the errors
  621. if(!fSucceeded)
  622. {
  623. dwError=GetLastError();
  624. printf("********The last error is %d\n",dwError);
  625. //print out the pbEncoded
  626. printf("The cbEncoded is %d, and pbEncoded is:\n",cbEncoded);
  627. PrintBytes(" ",pbEncoded,cbEncoded);
  628. printf("\n");
  629. }
  630. SAFE_FREE(pbEncoded);
  631. return fSucceeded;
  632. }
  633. //--------------------------------------------------------------------------
  634. // A general routine to verify the PKCS_TIME_REQUEST
  635. //
  636. //--------------------------------------------------------------------------
  637. BOOL VerifyPKCS_TIME_REQUEST(BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  638. {
  639. BOOL fSucceeded=TRUE;
  640. CRYPT_TIME_STAMP_REQUEST_INFO TimeStampRequest;
  641. void *pvStructInfo=NULL;
  642. DWORD cbStructInfo=0;
  643. DWORD cbEncoded=0;
  644. BYTE *pbEncoded=NULL;
  645. //make a hard-coded timestamp request
  646. BYTE rgTestData[] = {
  647. 0x1b, 0xf6, 0x92, 0xee, 0x6c, 0x44, 0xc5, 0xed, 0x51};
  648. BYTE rgAttribValue1[]={
  649. 0x02, 0x02, 0x11, 0x11};
  650. BYTE rgAttribValue2[]={
  651. 0x02, 0x02, 0x11, 0x11};
  652. //make 3 CRYPT_ATTRIBUTE
  653. CRYPT_ATTRIBUTE rgCryptAttribute[3];
  654. CRYPT_ATTR_BLOB rgAttribBlob[3];
  655. rgAttribBlob[0].cbData=sizeof(rgAttribValue2);
  656. rgAttribBlob[0].pbData=rgAttribValue2;
  657. rgAttribBlob[1].cbData=sizeof(rgAttribValue2);
  658. rgAttribBlob[1].pbData=rgAttribValue2;
  659. rgAttribBlob[2].cbData=sizeof(rgAttribValue1);
  660. rgAttribBlob[2].pbData=rgAttribValue1;
  661. rgCryptAttribute[0].pszObjId="1.2.3.4";
  662. rgCryptAttribute[0].cValue=0;
  663. rgCryptAttribute[0].rgValue=NULL;
  664. rgCryptAttribute[1].pszObjId="1.2.3.4";
  665. rgCryptAttribute[1].cValue=1;
  666. rgCryptAttribute[1].rgValue=rgAttribBlob;
  667. rgCryptAttribute[2].pszObjId="1.2.3.4";
  668. rgCryptAttribute[2].cValue=3;
  669. rgCryptAttribute[2].rgValue=rgAttribBlob;
  670. // initialize the timestamp structure
  671. TimeStampRequest.pszTimeStampAlgorithm = szOID_RSA_signingTime;
  672. TimeStampRequest.pszContentType = szOID_RSA_data;
  673. TimeStampRequest.Content.cbData = sizeof(rgTestData);
  674. TimeStampRequest.Content.pbData = rgTestData;
  675. TimeStampRequest.cAttribute = 3;
  676. TimeStampRequest.rgAttribute = rgCryptAttribute;
  677. //encode the struct into a BLOB
  678. TESTC(CryptEncodeObject(CRYPT_ENCODE_TYPE,PKCS_TIME_REQUEST,
  679. &TimeStampRequest,NULL,&cbEncoded),TRUE)
  680. pbEncoded=(BYTE *)SAFE_ALLOC(cbEncoded);
  681. CHECK_POINTER(pbEncoded)
  682. TESTC(CryptEncodeObject(CRYPT_ENCODE_TYPE,PKCS_TIME_REQUEST,
  683. &TimeStampRequest,pbEncoded,&cbEncoded),TRUE)
  684. //decode the struct with COPY and NOCOPY options
  685. TESTC(DecodePKCS_TIME_REQUEST(cbEncoded, pbEncoded, CRYPT_DECODE_COPY_FLAG,
  686. TRUE,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  687. TESTC(DecodePKCS_TIME_REQUEST(cbEncoded, pbEncoded, CRYPT_DECODE_NOCOPY_FLAG,
  688. TRUE,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  689. //decode the struct and compare it with the original
  690. TESTC(CryptDecodeObject(CRYPT_ENCODE_TYPE,PKCS_TIME_REQUEST,
  691. pbEncoded, cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,NULL,&cbStructInfo),TRUE)
  692. pvStructInfo=SAFE_ALLOC(cbStructInfo);
  693. CHECK_POINTER(pvStructInfo);
  694. TESTC(CryptDecodeObject(CRYPT_ENCODE_TYPE,PKCS_TIME_REQUEST,
  695. pbEncoded, cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,pvStructInfo,&cbStructInfo),TRUE)
  696. //compare two timstamp request
  697. TESTC(CompareTimeStampRequest(&TimeStampRequest,
  698. (CRYPT_TIME_STAMP_REQUEST_INFO *)pvStructInfo),TRUE)
  699. fSucceeded=TRUE;
  700. TCLEANUP:
  701. SAFE_FREE(pbEncoded);
  702. SAFE_FREE(pvStructInfo);
  703. return fSucceeded;
  704. }
  705. //--------------------------------------------------------------------------
  706. // A general routine to verify the CERT_PUBLIB_KEY_INFO.
  707. //
  708. // Encode and decode the structure. Call CryptImportPublicKeyInfo and
  709. // CryptImportKey.
  710. //--------------------------------------------------------------------------
  711. BOOL VerifyPublicKeyInfo(PCERT_PUBLIC_KEY_INFO pPublicKeyInfo,
  712. DWORD dwDecodeFlags, BOOL fEncode,
  713. BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  714. {
  715. BOOL fSucceeded=FALSE;
  716. HCRYPTKEY hKey=NULL;
  717. DWORD cbEncoded=0;
  718. BYTE *pbEncoded=NULL;
  719. //call CryptImportPublicKeyInfo
  720. TESTC(CryptImportPublicKeyInfo(g_hProv,CRYPT_ENCODE_TYPE,
  721. pPublicKeyInfo,&hKey),TRUE)
  722. //verify the algorithm
  723. TESTC(VerifyAlgorithParam(&(pPublicKeyInfo->Algorithm)),TRUE)
  724. //encode CERT_PUBLIC_KEY_INFO
  725. TESTC(EncodeStruct(X509_PUBLIC_KEY_INFO, pPublicKeyInfo,&cbEncoded,
  726. &pbEncoded),TRUE)
  727. //decode/encode the publicKeyInfo
  728. TESTC(DecodeGenericBLOB(X509_PUBLIC_KEY_INFO, cbEncoded, pbEncoded, dwDecodeFlags,
  729. fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  730. //decode/encode the RSA_CSP_PUBLICKEYBLOB
  731. TESTC(DecodeRSA_CSP_PUBLICKEYBLOB(pPublicKeyInfo->PublicKey.cbData,
  732. pPublicKeyInfo->PublicKey.pbData,dwDecodeFlags,fEncode,fStructLengthCheck,
  733. fBLOBLengthCheck),TRUE)
  734. fSucceeded=TRUE;
  735. TCLEANUP:
  736. if(hKey)
  737. TCHECK(CryptDestroyKey(hKey),TRUE);
  738. SAFE_FREE(pbEncoded)
  739. return fSucceeded;
  740. }
  741. //--------------------------------------------------------------------------
  742. // A general routine to verify the extentions in a cert.
  743. //
  744. //--------------------------------------------------------------------------
  745. BOOL VerifyCertExtensions(DWORD cExtension, PCERT_EXTENSION rgExtension,
  746. DWORD dwDecodeFlags, BOOL fEncode,
  747. BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  748. {
  749. BOOL fSucceeded=FALSE;
  750. DWORD cbEncoded=0;
  751. BYTE *pbEncoded=NULL;
  752. CERT_EXTENSIONS CertExtensions;
  753. DWORD cbTestEncoded=0;
  754. BYTE *pbTestEncoded=NULL;
  755. DWORD cbStructInfo=sizeof(CERT_EXTENSIONS);
  756. CERT_EXTENSIONS CertTestExtensions;
  757. //init
  758. CertExtensions.cExtension=0;
  759. CertExtensions.rgExtension=NULL;
  760. //Check the NULL case
  761. //length only calculation
  762. TESTC(CryptEncodeObject(CRYPT_ENCODE_TYPE,X509_EXTENSIONS, &CertExtensions,NULL,
  763. &cbTestEncoded),TRUE)
  764. //allocate memory
  765. pbTestEncoded=(BYTE *)SAFE_ALLOC(cbTestEncoded);
  766. CHECK_POINTER(pbTestEncoded);
  767. //EncodeObject
  768. TESTC(CryptEncodeObject(CRYPT_ENCODE_TYPE,X509_EXTENSIONS, &CertExtensions,
  769. pbTestEncoded, &cbTestEncoded),TRUE)
  770. //DecodeObject
  771. TESTC(CryptDecodeObject(CRYPT_ENCODE_TYPE,X509_EXTENSIONS,
  772. pbTestEncoded,cbTestEncoded,dwDecodeFlags,&CertTestExtensions,&cbStructInfo),TRUE)
  773. //Verify CertTestExtensions
  774. TESTC(CertTestExtensions.cExtension, CertExtensions.cExtension)
  775. //init again
  776. CertExtensions.cExtension=cExtension;
  777. CertExtensions.rgExtension=rgExtension;
  778. //encode CERT_EXTENSIONS
  779. TESTC(EncodeStruct(X509_EXTENSIONS, &CertExtensions,&cbEncoded,
  780. &pbEncoded),TRUE)
  781. //decode/encode X509_EXTENSIONS
  782. TESTC(DecodeX509_EXTENSIONS(cbEncoded,
  783. pbEncoded,dwDecodeFlags,fEncode,fStructLengthCheck,
  784. fBLOBLengthCheck),TRUE)
  785. fSucceeded=TRUE;
  786. TCLEANUP:
  787. SAFE_FREE(pbEncoded)
  788. SAFE_FREE(pbTestEncoded)
  789. return fSucceeded;
  790. }
  791. //--------------------------------------------------------------------------
  792. // Return the corresponding lpStructInfo based on the objectID passed in
  793. //--------------------------------------------------------------------------
  794. LPCSTR MapObjID2StructType(LPSTR szObjectID)
  795. {
  796. if(szObjectID==NULL)
  797. return NULL;
  798. if(strcmp(szObjectID,szOID_AUTHORITY_KEY_IDENTIFIER)==0)
  799. return X509_AUTHORITY_KEY_ID;
  800. if(strcmp(szObjectID,szOID_KEY_ATTRIBUTES)==0)
  801. return X509_KEY_ATTRIBUTES;
  802. if(strcmp(szObjectID,szOID_KEY_USAGE_RESTRICTION)==0)
  803. return X509_KEY_USAGE_RESTRICTION;
  804. if(strcmp(szObjectID,szOID_SUBJECT_ALT_NAME)==0)
  805. return X509_ALTERNATE_NAME;
  806. if(strcmp(szObjectID,szOID_ISSUER_ALT_NAME)==0)
  807. return X509_ALTERNATE_NAME;
  808. if(strcmp(szObjectID,szOID_BASIC_CONSTRAINTS)==0)
  809. return X509_BASIC_CONSTRAINTS;
  810. if(strcmp(szObjectID,szOID_KEY_USAGE)==0)
  811. return X509_KEY_USAGE;
  812. if(strcmp(szObjectID,szOID_BASIC_CONSTRAINTS2)==0)
  813. return X509_BASIC_CONSTRAINTS2;
  814. if(strcmp(szObjectID,szOID_CERT_POLICIES)==0)
  815. return X509_CERT_POLICIES;
  816. return NULL;
  817. }
  818. ///////////////////////////////////////////////////////////////////////////
  819. //Certificate Manipulation Functions
  820. //--------------------------------------------------------------------------
  821. // Decode a storefile what has CRL and certificates
  822. //--------------------------------------------------------------------------
  823. BOOL DecodeCertFile(LPSTR pszFileName,BOOL fStructLengthCheck,
  824. BOOL fBLOBLengthCheck)
  825. {
  826. BOOL fSucceeded=FALSE;
  827. HCERTSTORE hCertStore=NULL;
  828. DWORD cbCertEncoded=0;
  829. BYTE *pbCertEncoded=NULL;
  830. PCCERT_CONTEXT pCertContext=NULL;
  831. PCCERT_CONTEXT pPrevCertContext=NULL;
  832. PCCRL_CONTEXT pCrlContext=NULL;
  833. PCCRL_CONTEXT pPrevCrlContext=NULL;
  834. DWORD dwFlags=0;
  835. DWORD cCount=0;
  836. //open cert store
  837. if(!(hCertStore=CertOpenStore(CERT_STORE_PROV_FILENAME_A, CRYPT_ENCODE_TYPE,
  838. g_hProv,CERT_STORE_NO_CRYPT_RELEASE_FLAG,pszFileName)))
  839. PROCESS_ERR_GOTO("Failed to open a store!\n")
  840. //get a cert from the store one at a time
  841. while((pCertContext=CertEnumCertificatesInStore(hCertStore,pPrevCertContext)))
  842. {
  843. cCount++;
  844. printf("//-----------------------------------------\n");
  845. printf("Decoding the %dth Certificate\n",cCount);
  846. //retrieve the encoded X_509 BLOBs
  847. cbCertEncoded=pCertContext->cbCertEncoded;
  848. pbCertEncoded=pCertContext->pbCertEncoded;
  849. //verify the hCertStore is connect
  850. TESTC(hCertStore==pCertContext->hCertStore, TRUE)
  851. //NULL/invalid parameter testing only once
  852. if(cCount==1)
  853. TESTC(ParameterTest(X509_CERT_TO_BE_SIGNED, cbCertEncoded, pbCertEncoded),TRUE)
  854. //decode/encode the certificate blob with NOCOPY option
  855. TESTC(DecodeX509_CERT(CERT_INFO_STRUCT,cbCertEncoded,pbCertEncoded, CRYPT_DECODE_NOCOPY_FLAG,
  856. TRUE,fStructLengthCheck,fBLOBLengthCheck,pCertContext->pCertInfo),TRUE)
  857. //decode/encode the certificate blob with COPY option
  858. TESTC(DecodeX509_CERT(CERT_INFO_STRUCT,cbCertEncoded,pbCertEncoded, CRYPT_DECODE_COPY_FLAG,
  859. TRUE,fStructLengthCheck,fBLOBLengthCheck,pCertContext->pCertInfo),TRUE)
  860. pPrevCertContext=pCertContext;
  861. }
  862. cCount=0;
  863. //get a CRL from the store one at a time
  864. while((pCrlContext=CertGetCRLFromStore(hCertStore,NULL,pPrevCrlContext,&dwFlags)))
  865. {
  866. cCount++;
  867. printf("//-----------------------------------------\n");
  868. printf("Decoding the %dth CRL\n",cCount);
  869. //retrieve the encoded X_509 BLOBs
  870. cbCertEncoded=pCrlContext->cbCrlEncoded;
  871. pbCertEncoded=pCrlContext->pbCrlEncoded;
  872. //verify the hCertStore is connect
  873. TESTC(hCertStore==pCrlContext->hCertStore, TRUE)
  874. //NULL/invalid parameter testing only once
  875. if(cCount==1)
  876. TESTC(ParameterTest(X509_CERT_CRL_TO_BE_SIGNED, cbCertEncoded, pbCertEncoded),TRUE)
  877. //decode/encode the certificate blob with NOCOPY option
  878. TESTC(DecodeX509_CERT(CRL_INFO_STRUCT,cbCertEncoded,pbCertEncoded, CRYPT_DECODE_NOCOPY_FLAG,
  879. TRUE,fStructLengthCheck,fBLOBLengthCheck,pCrlContext->pCrlInfo),TRUE)
  880. //decode/encode the certificate blob with COPY option
  881. TESTC(DecodeX509_CERT(CRL_INFO_STRUCT,cbCertEncoded,pbCertEncoded, CRYPT_DECODE_COPY_FLAG,
  882. TRUE,fStructLengthCheck,fBLOBLengthCheck,pCrlContext->pCrlInfo),TRUE)
  883. pPrevCrlContext=pCrlContext;
  884. }
  885. fSucceeded=TRUE;
  886. TCLEANUP:
  887. //release the cert context
  888. if(pCertContext)
  889. CertFreeCertificateContext(pCertContext);
  890. //we do not need to free pPreCertContext since it is always freed by
  891. //CertEnumCertificatesInStore.
  892. //release the CRL contest
  893. if(pCrlContext)
  894. CertFreeCRLContext(pCrlContext);
  895. //release the cert store
  896. if(hCertStore)
  897. TCHECK(CertCloseStore(hCertStore,CERT_CLOSE_STORE_FORCE_FLAG),TRUE);
  898. return fSucceeded;
  899. }
  900. //--------------------------------------------------------------------------
  901. // Decode a BLOB file that is an encoded certificate request
  902. //--------------------------------------------------------------------------
  903. BOOL DecodeCertReqFile(LPSTR pszFileName,BOOL fStructLengthCheck,
  904. BOOL fBLOBLengthCheck)
  905. {
  906. BOOL fSucceeded=FALSE;
  907. DWORD cbEncoded=0;
  908. BYTE *pbEncoded=NULL;
  909. //Get the cbEncoded and pEncoded BLOB from the file
  910. TESTC(RetrieveBLOBfromFile(pszFileName,&cbEncoded,&pbEncoded),TRUE)
  911. //do a parameter testing
  912. TESTC(ParameterTest(X509_CERT_REQUEST_TO_BE_SIGNED, cbEncoded, pbEncoded),TRUE)
  913. //decode the BLOB as X509_CERT with COPY option
  914. TESTC(DecodeX509_CERT(CERT_REQUEST_INFO_STRUCT,cbEncoded,pbEncoded, CRYPT_DECODE_COPY_FLAG,
  915. TRUE,fStructLengthCheck,fBLOBLengthCheck,NULL),TRUE)
  916. //decode the BLOB as X509_CERT wiht NOCOPY option
  917. TESTC(DecodeX509_CERT(CERT_REQUEST_INFO_STRUCT,cbEncoded,pbEncoded, CRYPT_DECODE_NOCOPY_FLAG,
  918. TRUE,fStructLengthCheck,fBLOBLengthCheck,NULL),TRUE)
  919. fSucceeded=TRUE;
  920. TCLEANUP:
  921. SAFE_FREE(pbEncoded)
  922. return fSucceeded;
  923. }
  924. //--------------------------------------------------------------------------
  925. // Decode a BLOB file that is an signed message
  926. //--------------------------------------------------------------------------
  927. BOOL DecodeSignedMsgFile(LPSTR pszFileName,BOOL fStructLengthCheck,
  928. BOOL fBLOBLengthCheck)
  929. {
  930. BOOL fSucceeded=FALSE;
  931. DWORD cbEncoded=0;
  932. BYTE *pbEncoded=NULL;
  933. DWORD cbSignerEncoded=0;
  934. BYTE *pbSignerEncoded=NULL;
  935. HCRYPTMSG hCryptMsg=NULL;
  936. PCMSG_SIGNER_INFO pSignerInfo=NULL;
  937. DWORD cbSize=0;
  938. DWORD iIndex=0;
  939. DWORD cSignerCount=0;
  940. //Get the cbEncoded and pEncoded BLOB from the file
  941. TESTC(RetrieveBLOBfromFile(pszFileName,&cbEncoded,&pbEncoded),TRUE)
  942. //Get the SIGNER_INFO BLOB from the file BLOB
  943. hCryptMsg=CryptMsgOpenToDecode(MSG_ENCODING_TYPE,0,0,g_hProv,NULL,NULL);
  944. if(!hCryptMsg)
  945. goto TCLEANUP;
  946. TESTC(CryptMsgUpdate(hCryptMsg,pbEncoded,cbEncoded,TRUE),TRUE)
  947. //Get the count of signer in the message
  948. cbSize=sizeof(cSignerCount);
  949. TESTC(CryptMsgGetParam(hCryptMsg,CMSG_SIGNER_COUNT_PARAM,
  950. 0,&cSignerCount,&cbSize),TRUE)
  951. //go through the list of all signers
  952. for(iIndex=0;iIndex<cSignerCount;iIndex++)
  953. {
  954. //get the CMSG_SINGER_INFO struct
  955. TESTC(CryptMsgGetParam(hCryptMsg,CMSG_SIGNER_INFO_PARAM,
  956. iIndex,NULL,&cbSize),TRUE)
  957. //allocation memory
  958. pSignerInfo=(PCMSG_SIGNER_INFO)SAFE_ALLOC(cbSize);
  959. CHECK_POINTER(pSignerInfo);
  960. TESTC(CryptMsgGetParam(hCryptMsg,CMSG_SIGNER_INFO_PARAM,
  961. iIndex,pSignerInfo,&cbSize),TRUE)
  962. //encode the struct info a BLOB. Add Attributes if possible
  963. TESTC(EncodeSignerInfoWAttr(pSignerInfo,&cbSignerEncoded,
  964. &pbSignerEncoded),TRUE)
  965. //do a parameter testing for the 1st round
  966. if(iIndex==0)
  967. {
  968. TESTC(ParameterTest(PKCS7_SIGNER_INFO, cbSignerEncoded, pbSignerEncoded),TRUE)
  969. }
  970. //decode the BLOB as PKCS7_SIGNER_INFO with COPY option
  971. TESTC(DecodePKCS7_SIGNER_INFO(cbSignerEncoded,pbSignerEncoded, CRYPT_DECODE_COPY_FLAG,
  972. TRUE,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  973. //decode the BLOB as PKCS7_SIGNER_INFO wiht NOCOPY option
  974. TESTC(DecodePKCS7_SIGNER_INFO(cbSignerEncoded,pbSignerEncoded, CRYPT_DECODE_NOCOPY_FLAG,
  975. TRUE,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  976. //release the memory
  977. SAFE_FREE(pSignerInfo);
  978. SAFE_FREE(pbSignerEncoded);
  979. }
  980. fSucceeded=TRUE;
  981. TCLEANUP:
  982. //close the msg handle
  983. CryptMsgClose(hCryptMsg);
  984. SAFE_FREE(pbEncoded)
  985. SAFE_FREE(pbSignerEncoded)
  986. SAFE_FREE(pSignerInfo)
  987. return fSucceeded;
  988. }
  989. //--------------------------------------------------------------------------
  990. // A general routine to encode a struct based on lpszStructType
  991. //--------------------------------------------------------------------------
  992. BOOL EncodeStruct(LPCSTR lpszStructType, void *pStructInfo,DWORD *pcbEncoded,
  993. BYTE **ppbEncoded)
  994. {
  995. BOOL fSucceeded=FALSE;
  996. DWORD cbEncoded=NULL;
  997. BYTE *pbTestEncoded=NULL;
  998. DWORD cbTestEncoded=0;
  999. DWORD dwEncodingType=CRYPT_ENCODE_TYPE;
  1000. //init
  1001. *pcbEncoded=0;
  1002. *ppbEncoded=NULL;
  1003. assert(lpszStructType);
  1004. assert(pStructInfo);
  1005. //We have different decoding type for PKCS7_SIGNER_INFO
  1006. if((DWORD_PTR)(lpszStructType)==(DWORD_PTR)(PKCS7_SIGNER_INFO))
  1007. dwEncodingType=MSG_ENCODING_TYPE;
  1008. //length only calculation
  1009. TESTC(CryptEncodeObject(dwEncodingType,lpszStructType, pStructInfo,NULL,
  1010. &cbEncoded),TRUE)
  1011. //the struct has to be more than 0 byte
  1012. assert(cbEncoded);
  1013. //allocate the correct amount of memory
  1014. *ppbEncoded=(BYTE *)SAFE_ALLOC(cbEncoded);
  1015. CHECK_POINTER(*ppbEncoded);
  1016. //Encode the strcut with *pcbEncoded == the correct length
  1017. *pcbEncoded=cbEncoded;
  1018. //Encode the struct
  1019. TESTC(CryptEncodeObject(dwEncodingType,lpszStructType,pStructInfo,*ppbEncoded,
  1020. pcbEncoded),TRUE)
  1021. //the length returned has to be less or equal to cbEncoded
  1022. TESTC(cbEncoded>=(*pcbEncoded),TRUE)
  1023. //allocate memory to LENGTH_DELTA byte more than necessary to pbTestEncoded
  1024. pbTestEncoded=(BYTE *)SAFE_ALLOC(cbEncoded+LENGTH_MORE);
  1025. CHECK_POINTER(pbTestEncoded)
  1026. //Encode the struct with *pcbEncoded > the correct length
  1027. cbTestEncoded=cbEncoded+LENGTH_MORE;
  1028. TESTC(CryptEncodeObject(dwEncodingType,lpszStructType,pStructInfo,pbTestEncoded,
  1029. &cbTestEncoded),TRUE)
  1030. //*pcbEncoded should be the same as cbEncoded
  1031. TESTC(cbTestEncoded, *pcbEncoded)
  1032. //Verify the pbTestEncoded contain the same bytes as pcbEncoded, starting
  1033. //at the 1st byte of the BLOB
  1034. TESTC(memcmp(pbTestEncoded, *ppbEncoded,*pcbEncoded),0)
  1035. //Encode the struct with *pcbEncoded < the correct length
  1036. cbTestEncoded=(*pcbEncoded)-LENGTH_LESS;
  1037. TESTC(CryptEncodeObject(dwEncodingType,lpszStructType,pStructInfo,pbTestEncoded,
  1038. &cbTestEncoded),FALSE)
  1039. //*pcbEncoded should be the same as cbEncoded
  1040. TESTC(cbTestEncoded, *pcbEncoded)
  1041. //GetLastError should be ERROR_MORE_DATA
  1042. TESTC(GetLastError(),ERROR_MORE_DATA)
  1043. fSucceeded=TRUE;
  1044. TCLEANUP:
  1045. SAFE_FREE(pbTestEncoded)
  1046. return fSucceeded;
  1047. }
  1048. //--------------------------------------------------------------------------
  1049. // EncodeAndVerify
  1050. //
  1051. // Encode the pStructInfo and verify the encoded BLOB is the same
  1052. // as expected.
  1053. //--------------------------------------------------------------------------
  1054. BOOL EncodeAndVerify(LPCSTR lpszStructType, void *pvStructInfo, DWORD cbEncoded,
  1055. BYTE *pbEncoded)
  1056. {
  1057. DWORD cbSecondEncoded=0;
  1058. BYTE *pbSecondEncoded=0;
  1059. BOOL fSucceeded=FALSE;
  1060. assert(lpszStructType);
  1061. assert(pvStructInfo);
  1062. assert(cbEncoded);
  1063. assert(pbEncoded);
  1064. //encode the struct back to a BLOB
  1065. TESTC(EncodeStruct(lpszStructType,pvStructInfo,&cbSecondEncoded,&pbSecondEncoded),
  1066. TRUE)
  1067. //make sure the returned encoded BLOB is the same as the original BLOB
  1068. //the two encoded BLOB has to of the same length
  1069. if(!TCHECK(cbSecondEncoded, cbEncoded))
  1070. {
  1071. PROCESS_ERR(szEncodedSizeInconsistent)
  1072. OutputError(lpszStructType,cbSecondEncoded, cbEncoded,pbSecondEncoded,pbEncoded);
  1073. }
  1074. if (0 != memcmp(pbSecondEncoded,pbEncoded,cbEncoded)) {
  1075. if (X509_KEY_USAGE == lpszStructType) {
  1076. // Force the unused bits to be the same
  1077. if (3 <= cbSecondEncoded && 3 <= cbEncoded) {
  1078. BYTE bUnusedBits = pbSecondEncoded[2];
  1079. pbSecondEncoded[2] = pbEncoded[2];
  1080. if (0 == memcmp(pbSecondEncoded,pbEncoded,cbEncoded))
  1081. printf("Warning, difference in reencoded KeyUsage UnusedBit Count\n");
  1082. else
  1083. pbSecondEncoded[2] = bUnusedBits;
  1084. }
  1085. }
  1086. }
  1087. //the two encoded BLOB has to be of the same content
  1088. if(!TCHECK(memcmp(pbSecondEncoded,pbEncoded,cbEncoded),0))
  1089. {
  1090. PROCESS_ERR(szEncodedContentInconsistent)
  1091. OutputError(lpszStructType,cbSecondEncoded, cbEncoded,pbSecondEncoded,pbEncoded);
  1092. }
  1093. fSucceeded=TRUE;
  1094. TCLEANUP:
  1095. SAFE_FREE(pbSecondEncoded)
  1096. return fSucceeded;
  1097. }
  1098. //--------------------------------------------------------------------------
  1099. // A general routine to decode a BLOB based on lpszStructType
  1100. //
  1101. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1102. // for *pcbStructInfo from 0 .. CorrectLength-1
  1103. //
  1104. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1105. // for cbEncoded from 0 .. CorrentLength-1
  1106. //
  1107. //--------------------------------------------------------------------------
  1108. BOOL DecodeBLOB(LPCSTR lpszStructType,DWORD cbEncoded, BYTE *pbEncoded,
  1109. DWORD dwDecodeFlags, DWORD *pcbStructInfo, void **ppvStructInfo,
  1110. BOOL fStructLengthCheck,BOOL fBLOBLengthCheck)
  1111. {
  1112. BOOL fSucceeded=FALSE;
  1113. DWORD cbStructInfo=0;
  1114. LONG iIndex=0;
  1115. LONG cbUpperLimit=0;
  1116. DWORD cbTestStructInfo=0;
  1117. void *pvTestStructInfo=NULL;
  1118. DWORD dwEncodingType=CRYPT_ENCODE_TYPE;
  1119. //init
  1120. *pcbStructInfo=0;
  1121. *ppvStructInfo=NULL;
  1122. assert(lpszStructType);
  1123. assert(pbEncoded);
  1124. assert(cbEncoded);
  1125. //Decode
  1126. if((DWORD_PTR)(lpszStructType)==(DWORD_PTR)(PKCS7_SIGNER_INFO))
  1127. dwEncodingType=MSG_ENCODING_TYPE;
  1128. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,cbEncoded,
  1129. dwDecodeFlags,NULL,&cbStructInfo),TRUE)
  1130. //the struct has to be more than 0 byte
  1131. assert(cbStructInfo);
  1132. *ppvStructInfo=(BYTE *)SAFE_ALLOC(cbStructInfo);
  1133. CHECK_POINTER(*ppvStructInfo);
  1134. //Decode the BLOB with *pcbStructInfo==correct length
  1135. *pcbStructInfo=cbStructInfo;
  1136. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,cbEncoded,
  1137. dwDecodeFlags,*ppvStructInfo,pcbStructInfo),TRUE)
  1138. //make sure the correct length is less than cbStructInfo
  1139. TESTC(cbStructInfo>=(*pcbStructInfo),TRUE);
  1140. //Decode the BLOB with *pcbStructInfo>correct length
  1141. //allocate memory to be LENGTH_DELTA more byte than the correct length
  1142. pvTestStructInfo=SAFE_ALLOC(cbStructInfo+LENGTH_MORE);
  1143. CHECK_POINTER(pvTestStructInfo);
  1144. cbTestStructInfo=cbStructInfo+LENGTH_MORE;
  1145. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,cbEncoded,
  1146. dwDecodeFlags,pvTestStructInfo,&cbTestStructInfo),TRUE)
  1147. //make sure the length is the same
  1148. TESTC(cbTestStructInfo, (*pcbStructInfo));
  1149. //Decode the BLOB with *pcbStructInfo < correct length
  1150. cbTestStructInfo=(*pcbStructInfo)-LENGTH_LESS;
  1151. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,cbEncoded,
  1152. dwDecodeFlags,pvTestStructInfo,&cbTestStructInfo),FALSE)
  1153. TESTC(GetLastError(), ERROR_MORE_DATA)
  1154. //make sure the length is the same
  1155. TESTC(cbTestStructInfo, (*pcbStructInfo));
  1156. //if fStructLengthCheck is TRUE, we need to do a more rigorous test of *pcbStructInfo
  1157. if(fStructLengthCheck)
  1158. {
  1159. cbUpperLimit=(*pcbStructInfo)-1;
  1160. for(iIndex=cbUpperLimit; iIndex>=0; iIndex--)
  1161. {
  1162. cbTestStructInfo=iIndex;
  1163. //decode the BLOB with *pcbStructInfo<correct bytes
  1164. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,cbEncoded,
  1165. dwDecodeFlags,pvTestStructInfo,&cbTestStructInfo),FALSE)
  1166. TESTC(GetLastError(), ERROR_MORE_DATA)
  1167. //make sure the length is the same
  1168. TESTC(cbTestStructInfo, *pcbStructInfo);
  1169. }
  1170. }
  1171. //if fBLOBLengthCheck is TRUE, we need to do a more rigorous test of cbEncoded
  1172. if(fBLOBLengthCheck)
  1173. {
  1174. cbUpperLimit=cbEncoded-1;
  1175. for(iIndex=cbUpperLimit; iIndex>=0; iIndex--)
  1176. {
  1177. cbTestStructInfo=cbStructInfo;
  1178. //decode the BLOB with cbEncoded < correct byte
  1179. TESTC(CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded,iIndex,
  1180. dwDecodeFlags,pvTestStructInfo,&cbTestStructInfo),FALSE)
  1181. //we are not sure that should be expected here. The following error has
  1182. //occurred:
  1183. //E_INVALIDARG, CRYPT_E_OSS_ERROR+PDU_MISMATCH, +DATA_ERROR, or
  1184. //+MORE_INPUT
  1185. //make sure at lease S_OK is not returned
  1186. TCHECK(GetLastError()!=S_OK, TRUE);
  1187. }
  1188. }
  1189. fSucceeded=TRUE;
  1190. TCLEANUP:
  1191. //reallocate memory
  1192. SAFE_FREE(pvTestStructInfo);
  1193. return fSucceeded;
  1194. }
  1195. //--------------------------------------------------------------------------
  1196. // Decode X509_CERT BLOBs
  1197. //
  1198. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1199. // for *pcbStructInfo from 0 .. CorrectLength-1
  1200. //
  1201. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1202. // for cbEncoded from 0 .. CorrentLength-1
  1203. //--------------------------------------------------------------------------
  1204. BOOL DecodeX509_CERT(DWORD dwCertType,DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,BOOL fEncode,
  1205. BOOL fStructLengthCheck, BOOL fBLOBLengthCheck,
  1206. void *pInfoStruct)
  1207. {
  1208. BOOL fSucceeded=FALSE;
  1209. DWORD cbStructInfo=0;
  1210. void *pStructInfo=NULL;
  1211. LPCSTR lpszStructType=NULL;
  1212. //init
  1213. lpszStructType=X509_CERT;
  1214. //Decode the encoded BLOB
  1215. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1216. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1217. //verify the algorithm
  1218. TESTC(VerifyAlgorithParam(&(((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->SignatureAlgorithm)),TRUE)
  1219. //Further Decode the X509_CERT_TO_BE_SIGNED
  1220. //Notice we should use the original cbData and pbData passed in for Decode
  1221. //but use ToBeSigned in CERT_SIGNED_CONTENT_INFO for encode purpose
  1222. switch(dwCertType)
  1223. {
  1224. case CERT_INFO_STRUCT:
  1225. TESTC(DecodeX509_CERT_TO_BE_SIGNED(cbEncoded,
  1226. pbEncoded,dwDecodeFlags,fEncode,
  1227. fStructLengthCheck, fBLOBLengthCheck,
  1228. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).cbData,
  1229. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).pbData
  1230. ),TRUE)
  1231. //verify the pCertInfo should be encoded correctly
  1232. TCHECK(EncodeAndVerify(X509_CERT_TO_BE_SIGNED, pInfoStruct,
  1233. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).cbData,
  1234. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).pbData),TRUE);
  1235. break;
  1236. case CRL_INFO_STRUCT:
  1237. TESTC(DecodeX509_CERT_CRL_TO_BE_SIGNED(cbEncoded,
  1238. pbEncoded,dwDecodeFlags,fEncode,
  1239. fStructLengthCheck, fBLOBLengthCheck,
  1240. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).cbData,
  1241. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).pbData
  1242. ),TRUE)
  1243. //verify the pCrlInfo should be encoded correctly
  1244. TCHECK(EncodeAndVerify(X509_CERT_CRL_TO_BE_SIGNED, pInfoStruct,
  1245. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).cbData,
  1246. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).pbData),TRUE);
  1247. break;
  1248. case CERT_REQUEST_INFO_STRUCT:
  1249. TESTC(DecodeX509_CERT_REQUEST_TO_BE_SIGNED(cbEncoded,
  1250. pbEncoded,dwDecodeFlags,fEncode,
  1251. fStructLengthCheck, fBLOBLengthCheck,
  1252. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).cbData,
  1253. (((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).pbData
  1254. ),TRUE)
  1255. break;
  1256. }
  1257. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1258. //by checking the size of the encoded blob and do a memcmp.
  1259. if(fEncode)
  1260. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbEncoded, pbEncoded),TRUE);
  1261. fSucceeded=TRUE;
  1262. TCLEANUP:
  1263. SAFE_FREE(pStructInfo)
  1264. return fSucceeded;
  1265. }
  1266. //--------------------------------------------------------------------------
  1267. // Decode X509_CERT_TO_BE_SIGNED BLOBs
  1268. //
  1269. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1270. // for *pcbStructInfo from 0 .. CorrectLength-1
  1271. //
  1272. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1273. // for cbEncoded from 0 .. CorrentLength-1
  1274. //--------------------------------------------------------------------------
  1275. BOOL DecodeX509_CERT_TO_BE_SIGNED(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1276. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck,
  1277. BOOL cbExpectedEncoded, BYTE *pbExpectedEncoded)
  1278. {
  1279. BOOL fSucceeded=FALSE;
  1280. DWORD cbStructInfo=0;
  1281. void *pStructInfo=NULL;
  1282. LPCSTR lpszStructType=NULL;
  1283. //init
  1284. lpszStructType=X509_CERT_TO_BE_SIGNED;
  1285. //Decode the encoded BLOB
  1286. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1287. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1288. //Verify the signaure algorithm
  1289. TESTC(VerifyAlgorithParam(&(((PCERT_INFO)pStructInfo)->SignatureAlgorithm)),TRUE)
  1290. //Verify the public Key information
  1291. TESTC(VerifyPublicKeyInfo(&(((PCERT_INFO)pStructInfo)->SubjectPublicKeyInfo),
  1292. dwDecodeFlags, fEncode,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1293. //Decode Issuer in CERT_INFO struct
  1294. TESTC(DecodeX509_NAME((((PCERT_INFO)pStructInfo)->Issuer).cbData,
  1295. (((PCERT_INFO)pStructInfo)->Issuer).pbData,dwDecodeFlags,fEncode,
  1296. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1297. //Decode Issuer to X509_UNICODE_NAME
  1298. TESTC(DecodeX509_UNICODE_NAME((((PCERT_INFO)pStructInfo)->Issuer).cbData,
  1299. (((PCERT_INFO)pStructInfo)->Issuer).pbData,dwDecodeFlags,fEncode,
  1300. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1301. //Decode Subject in CERT_INFO struct
  1302. TESTC(DecodeX509_NAME((((PCERT_INFO)pStructInfo)->Subject).cbData,
  1303. (((PCERT_INFO)pStructInfo)->Subject).pbData,dwDecodeFlags,fEncode,
  1304. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1305. //Decode Subject to X509_UNICODE_NAME
  1306. TESTC(DecodeX509_UNICODE_NAME((((PCERT_INFO)pStructInfo)->Subject).cbData,
  1307. (((PCERT_INFO)pStructInfo)->Subject).pbData,dwDecodeFlags,fEncode,
  1308. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1309. //Verify the extensions
  1310. TESTC(VerifyCertExtensions(((PCERT_INFO)pStructInfo)->cExtension,
  1311. ((PCERT_INFO)pStructInfo)->rgExtension,dwDecodeFlags,fEncode,
  1312. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1313. //decode the extensions one by one
  1314. TESTC(DecodeCertExtensions(((PCERT_INFO)pStructInfo)->cExtension,
  1315. ((PCERT_INFO)pStructInfo)->rgExtension,dwDecodeFlags,fEncode,
  1316. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1317. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1318. //by checking the size of the encoded blob and do a memcmp.
  1319. if(fEncode)
  1320. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbExpectedEncoded,
  1321. pbExpectedEncoded),TRUE);
  1322. fSucceeded=TRUE;
  1323. TCLEANUP:
  1324. SAFE_FREE(pStructInfo)
  1325. return fSucceeded;
  1326. }
  1327. //--------------------------------------------------------------------------
  1328. // Decode X509_CERT_CRL_TO_BE_SIGNED BLOBs
  1329. //
  1330. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1331. // for *pcbStructInfo from 0 .. CorrectLength-1
  1332. //
  1333. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1334. // for cbEncoded from 0 .. CorrentLength-1
  1335. //--------------------------------------------------------------------------
  1336. BOOL DecodeX509_CERT_CRL_TO_BE_SIGNED(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1337. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck,
  1338. BOOL cbExpectedEncoded, BYTE *pbExpectedEncoded)
  1339. {
  1340. BOOL fSucceeded=FALSE;
  1341. DWORD cbStructInfo=0;
  1342. void *pStructInfo=NULL;
  1343. DWORD iIndex=0;
  1344. PCRL_ENTRY pCrlEntry=NULL;
  1345. LPCSTR lpszStructType=NULL;
  1346. //init
  1347. lpszStructType=X509_CERT_CRL_TO_BE_SIGNED;
  1348. //Decode the encoded BLOB
  1349. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1350. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1351. //Verify the signaure algorithm
  1352. TESTC(VerifyAlgorithParam(&(((PCRL_INFO)pStructInfo)->SignatureAlgorithm)),TRUE)
  1353. //Decode Issuer in CRL_INFO struct
  1354. TESTC(DecodeX509_NAME((((PCRL_INFO)pStructInfo)->Issuer).cbData,
  1355. (((PCRL_INFO)pStructInfo)->Issuer).pbData,dwDecodeFlags,fEncode,
  1356. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1357. //Decode Issuer to the X509_UNICODE_NAME
  1358. TESTC(DecodeX509_UNICODE_NAME((((PCRL_INFO)pStructInfo)->Issuer).cbData,
  1359. (((PCRL_INFO)pStructInfo)->Issuer).pbData,dwDecodeFlags,fEncode,
  1360. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1361. //Verify the CRL_ENTRY
  1362. for(iIndex=0; iIndex<((PCRL_INFO)pStructInfo)->cCRLEntry; iIndex++)
  1363. {
  1364. pCrlEntry=&(((PCRL_INFO)pStructInfo)->rgCRLEntry[iIndex]);
  1365. TESTC(DecodeCRLEntry(pCrlEntry,dwDecodeFlags,fEncode,
  1366. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1367. }
  1368. //Verify the extensions
  1369. TESTC(VerifyCertExtensions(((PCRL_INFO)pStructInfo)->cExtension,
  1370. ((PCRL_INFO)pStructInfo)->rgExtension,dwDecodeFlags,fEncode,
  1371. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1372. //decode the extensions one by one
  1373. TESTC(DecodeCertExtensions(((PCRL_INFO)pStructInfo)->cExtension,
  1374. ((PCRL_INFO)pStructInfo)->rgExtension,dwDecodeFlags,fEncode,
  1375. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1376. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1377. //by checking the size of the encoded blob and do a memcmp.
  1378. if(fEncode)
  1379. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbExpectedEncoded,
  1380. pbExpectedEncoded),TRUE);
  1381. fSucceeded=TRUE;
  1382. TCLEANUP:
  1383. SAFE_FREE(pStructInfo)
  1384. return fSucceeded;
  1385. }
  1386. //--------------------------------------------------------------------------
  1387. // Decode 509_CERT_REQUEST_TO_BE_SIGNED BLOBS
  1388. //
  1389. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1390. // for *pcbStructInfo from 0 .. CorrectLength-1
  1391. //
  1392. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1393. // for cbEncoded from 0 .. CorrentLength-1
  1394. //--------------------------------------------------------------------------
  1395. BOOL DecodeX509_CERT_REQUEST_TO_BE_SIGNED(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1396. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck,
  1397. BOOL cbExpectedEncoded, BYTE *pbExpectedEncoded)
  1398. {
  1399. BOOL fSucceeded=FALSE;
  1400. DWORD cbStructInfo=0;
  1401. void *pStructInfo=NULL;
  1402. DWORD cCount=0;
  1403. DWORD iIndex=0;
  1404. PCRYPT_ATTRIBUTE pCryptAttribute=NULL;
  1405. LPCSTR lpszStructType=NULL;
  1406. //init
  1407. lpszStructType=X509_CERT_REQUEST_TO_BE_SIGNED;
  1408. //Decode the encoded BLOB
  1409. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1410. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1411. //Verify the public Key information
  1412. // TESTC(VerifyPublicKeyInfo(&(((PCERT_REQUEST_INFO)pStructInfo)->SubjectPublicKeyInfo),
  1413. // dwDecodeFlags, fEncode,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1414. //Decode Subject in CERT_REQUEST_INFO struct
  1415. TESTC(DecodeX509_NAME((((PCERT_REQUEST_INFO)pStructInfo)->Subject).cbData,
  1416. (((PCERT_REQUEST_INFO)pStructInfo)->Subject).pbData,dwDecodeFlags,fEncode,
  1417. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1418. //Decode Subject in CERT_REQUEST_INFO struct for X509_UNICODE_NAME
  1419. TESTC(DecodeX509_UNICODE_NAME((((PCERT_REQUEST_INFO)pStructInfo)->Subject).cbData,
  1420. (((PCERT_REQUEST_INFO)pStructInfo)->Subject).pbData,dwDecodeFlags,fEncode,
  1421. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1422. //Decode the rgAttribute in CERT_REQUEST_INFO
  1423. cCount=((PCERT_REQUEST_INFO)pStructInfo)->cAttribute;
  1424. for(iIndex=0; iIndex<cCount; iIndex++)
  1425. {
  1426. pCryptAttribute=&(((PCERT_REQUEST_INFO)pStructInfo)->rgAttribute[iIndex]);
  1427. TESTC(DecodeCryptAttribute(pCryptAttribute,dwDecodeFlags,fEncode,
  1428. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1429. }
  1430. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1431. //by checking the size of the encoded blob and do a memcmp.
  1432. if(fEncode)
  1433. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbExpectedEncoded,
  1434. pbExpectedEncoded),TRUE);
  1435. fSucceeded=TRUE;
  1436. TCLEANUP:
  1437. SAFE_FREE(pStructInfo)
  1438. return fSucceeded;
  1439. }
  1440. //--------------------------------------------------------------------------
  1441. // Decode RSA_CSP_PUBLICKEYBLOB
  1442. //
  1443. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1444. // for *pcbStructInfo from 0 .. CorrectLength-1
  1445. //
  1446. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1447. // for cbEncoded from 0 .. CorrentLength-1
  1448. //--------------------------------------------------------------------------
  1449. BOOL DecodeRSA_CSP_PUBLICKEYBLOB(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1450. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1451. {
  1452. BOOL fSucceeded=FALSE;
  1453. DWORD cbStructInfo=0;
  1454. void *pStructInfo=NULL;
  1455. LPCSTR lpszStructType=NULL;
  1456. HCRYPTKEY hKey=NULL;
  1457. //init
  1458. lpszStructType=RSA_CSP_PUBLICKEYBLOB;
  1459. //Decode the encoded BLOB
  1460. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1461. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1462. //Make sure the pStructInfo can be used by CryptImportKey
  1463. TESTC(CryptImportKey(g_hProv,(BYTE *)pStructInfo,cbStructInfo,
  1464. 0,0,&hKey),TRUE)
  1465. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1466. //by checking the size of the encoded blob and do a memcmp.
  1467. if(fEncode)
  1468. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbEncoded,
  1469. pbEncoded),TRUE);
  1470. fSucceeded=TRUE;
  1471. TCLEANUP:
  1472. if(hKey)
  1473. TCHECK(CryptDestroyKey(hKey),TRUE);
  1474. SAFE_FREE(pStructInfo)
  1475. return fSucceeded;
  1476. }
  1477. //--------------------------------------------------------------------------
  1478. // Decode PKCS_TIME_REQUEST
  1479. //
  1480. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1481. // for *pcbStructInfo from 0 .. CorrectLength-1
  1482. //
  1483. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1484. // for cbEncoded from 0 .. CorrentLength-1
  1485. //--------------------------------------------------------------------------
  1486. BOOL DecodePKCS_TIME_REQUEST(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1487. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1488. {
  1489. BOOL fSucceeded=FALSE;
  1490. DWORD cbStructInfo=0;
  1491. void *pStructInfo=NULL;
  1492. LPCSTR lpszStructType=NULL;
  1493. //init
  1494. lpszStructType=PKCS_TIME_REQUEST;
  1495. //Decode the encoded BLOB
  1496. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1497. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1498. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1499. //by checking the size of the encoded blob and do a memcmp.
  1500. if(fEncode)
  1501. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbEncoded,
  1502. pbEncoded),TRUE);
  1503. fSucceeded=TRUE;
  1504. TCLEANUP:
  1505. SAFE_FREE(pStructInfo)
  1506. return fSucceeded;
  1507. }
  1508. //--------------------------------------------------------------------------
  1509. // Decode a genanric BLOB, encode is back to make sure that the same
  1510. // BLOB is returned.
  1511. //
  1512. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1513. // for *pcbStructInfo from 0 .. CorrectLength-1
  1514. //
  1515. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1516. // for cbEncoded from 0 .. CorrentLength-1
  1517. //--------------------------------------------------------------------------
  1518. BOOL DecodeGenericBLOB(LPCSTR lpszStructType, DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1519. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1520. {
  1521. BOOL fSucceeded=FALSE;
  1522. DWORD cbStructInfo=0;
  1523. void *pStructInfo=NULL;
  1524. //Decode the encoded BLOB
  1525. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1526. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1527. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1528. //by checking the size of the encoded blob and do a memcmp.
  1529. if(fEncode)
  1530. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbEncoded,
  1531. pbEncoded),TRUE);
  1532. fSucceeded=TRUE;
  1533. TCLEANUP:
  1534. SAFE_FREE(pStructInfo)
  1535. return fSucceeded;
  1536. }
  1537. //--------------------------------------------------------------------------
  1538. // Decode X509_NAME BLOBs
  1539. //
  1540. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1541. // for *pcbStructInfo from 0 .. CorrectLength-1
  1542. //
  1543. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1544. // for cbEncoded from 0 .. CorrentLength-1
  1545. //--------------------------------------------------------------------------
  1546. BOOL DecodeX509_NAME(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1547. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1548. {
  1549. BOOL fSucceeded=FALSE;
  1550. DWORD cbStructInfo=0;
  1551. void *pStructInfo=NULL;
  1552. LPCSTR lpszStructType=NULL;
  1553. DWORD cRDN=0;
  1554. DWORD cRDNAttr=0;
  1555. DWORD cRDNCount=0;
  1556. DWORD cRDNAttrCount=0;
  1557. //init
  1558. lpszStructType=X509_NAME;
  1559. //Decode the encoded BLOB
  1560. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1561. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1562. //We need to further decode CERT_RDN_ATTR if dwValueType is CERT_RDN_ENCODED_BLOB
  1563. cRDNCount=((PCERT_NAME_INFO)pStructInfo)->cRDN;
  1564. for(cRDN=0;cRDN<cRDNCount;cRDN++)
  1565. {
  1566. cRDNAttrCount=(((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).cRDNAttr;
  1567. for(cRDNAttr=0; cRDNAttr<cRDNAttrCount; cRDNAttr++)
  1568. {
  1569. //no need to do a length checking since the routine is written and
  1570. //installed by third party
  1571. if( (((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).rgRDNAttr[cRDNAttr].dwValueType==
  1572. CERT_RDN_ENCODED_BLOB)
  1573. TESTC(DecodeBasedOnObjID(
  1574. (((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).rgRDNAttr[cRDNAttr].pszObjId,
  1575. (((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).rgRDNAttr[cRDNAttr].Value.cbData,
  1576. (((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).rgRDNAttr[cRDNAttr].Value.pbData,
  1577. dwDecodeFlags, fEncode,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1578. }
  1579. }
  1580. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1581. //by checking the size of the encoded blob and do a memcmp.
  1582. if(fEncode)
  1583. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbEncoded, pbEncoded),TRUE);
  1584. fSucceeded=TRUE;
  1585. TCLEANUP:
  1586. SAFE_FREE(pStructInfo)
  1587. return fSucceeded;
  1588. }
  1589. //--------------------------------------------------------------------------
  1590. // Decode PKCS7_SIGNER_INFO
  1591. //
  1592. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1593. // for *pcbStructInfo from 0 .. CorrectLength-1
  1594. //
  1595. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1596. // for cbEncoded from 0 .. CorrentLength-1
  1597. //--------------------------------------------------------------------------
  1598. BOOL DecodePKCS7_SIGNER_INFO(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1599. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1600. {
  1601. BOOL fSucceeded=FALSE;
  1602. DWORD cbStructInfo=0;
  1603. void *pStructInfo=NULL;
  1604. LPCSTR lpszStructType=NULL;
  1605. //init
  1606. lpszStructType=PKCS7_SIGNER_INFO;
  1607. //Decode the encoded BLOB
  1608. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1609. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1610. //further decode the issuser name
  1611. TESTC(DecodeX509_NAME((((PCMSG_SIGNER_INFO)pStructInfo)->Issuer).cbData,
  1612. (((PCMSG_SIGNER_INFO)pStructInfo)->Issuer).pbData,dwDecodeFlags,fEncode,
  1613. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1614. //further decode the attributes
  1615. TESTC(VerifyAttributes(((PCMSG_SIGNER_INFO)pStructInfo)->AuthAttrs.cAttr,
  1616. ((PCMSG_SIGNER_INFO)pStructInfo)->AuthAttrs.rgAttr,
  1617. dwDecodeFlags,fEncode,
  1618. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1619. TESTC(VerifyAttributes(((PCMSG_SIGNER_INFO)pStructInfo)->UnauthAttrs.cAttr,
  1620. ((PCMSG_SIGNER_INFO)pStructInfo)->UnauthAttrs.rgAttr,
  1621. dwDecodeFlags,fEncode,
  1622. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1623. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1624. //by checking the size of the encoded blob and do a memcmp.
  1625. if(fEncode)
  1626. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbEncoded,
  1627. pbEncoded),TRUE);
  1628. fSucceeded=TRUE;
  1629. TCLEANUP:
  1630. SAFE_FREE(pStructInfo)
  1631. return fSucceeded;
  1632. }
  1633. //--------------------------------------------------------------------------
  1634. // Decode an array of attributes
  1635. //
  1636. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1637. // for *pcbStructInfo from 0 .. CorrectLength-1
  1638. //
  1639. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1640. // for cbEncoded from 0 .. CorrentLength-1
  1641. //--------------------------------------------------------------------------
  1642. BOOL VerifyAttributes(DWORD cAttr, PCRYPT_ATTRIBUTE rgAttr,
  1643. DWORD dwDecodeFlags, BOOL fEncode, BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1644. {
  1645. BOOL fSucceeded=FALSE;
  1646. ULONG iIndex=0;
  1647. for(iIndex=0;iIndex<cAttr;iIndex++)
  1648. {
  1649. TESTC(DecodeCryptAttribute(&(rgAttr[iIndex]),dwDecodeFlags,fEncode,
  1650. fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1651. }
  1652. fSucceeded=TRUE;
  1653. TCLEANUP:
  1654. return fSucceeded;
  1655. }
  1656. //--------------------------------------------------------------------------
  1657. // Decode X509_UNICODE_NAME BLOBs
  1658. //
  1659. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1660. // for *pcbStructInfo from 0 .. CorrectLength-1
  1661. //
  1662. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1663. // for cbEncoded from 0 .. CorrentLength-1
  1664. //--------------------------------------------------------------------------
  1665. BOOL DecodeX509_UNICODE_NAME(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1666. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1667. {
  1668. BOOL fSucceeded=FALSE;
  1669. DWORD cbStructInfo=0;
  1670. void *pStructInfo=NULL;
  1671. LPCSTR lpszStructType=NULL;
  1672. DWORD cRDN=0;
  1673. DWORD cRDNAttr=0;
  1674. DWORD cRDNCount=0;
  1675. DWORD cRDNAttrCount=0;
  1676. //init
  1677. lpszStructType=X509_UNICODE_NAME;
  1678. //Decode the encoded BLOB
  1679. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1680. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1681. //We need to further decode CERT_RDN_ATTR if dwValueType is CERT_RDN_ENCODED_BLOB
  1682. cRDNCount=((PCERT_NAME_INFO)pStructInfo)->cRDN;
  1683. for(cRDN=0;cRDN<cRDNCount;cRDN++)
  1684. {
  1685. cRDNAttrCount=(((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).cRDNAttr;
  1686. for(cRDNAttr=0; cRDNAttr<cRDNAttrCount; cRDNAttr++)
  1687. {
  1688. //no need to do a length checking since the routine is written and
  1689. //installed by third party
  1690. if( (((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).rgRDNAttr[cRDNAttr].dwValueType==
  1691. CERT_RDN_ENCODED_BLOB)
  1692. TESTC(DecodeBasedOnObjID(
  1693. (((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).rgRDNAttr[cRDNAttr].pszObjId,
  1694. (((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).rgRDNAttr[cRDNAttr].Value.cbData,
  1695. (((PCERT_NAME_INFO)pStructInfo)->rgRDN[cRDN]).rgRDNAttr[cRDNAttr].Value.pbData,
  1696. dwDecodeFlags, fEncode,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1697. }
  1698. }
  1699. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1700. //by checking the size of the encoded blob and do a memcmp.
  1701. if(fEncode)
  1702. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbEncoded, pbEncoded),TRUE);
  1703. fSucceeded=TRUE;
  1704. TCLEANUP:
  1705. SAFE_FREE(pStructInfo)
  1706. return fSucceeded;
  1707. }
  1708. //--------------------------------------------------------------------------
  1709. // Decode X509_EXTENSIONS BLOB
  1710. //
  1711. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1712. // for *pcbStructInfo from 0 .. CorrectLength-1
  1713. //
  1714. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1715. // for cbEncoded from 0 .. CorrentLength-1
  1716. //--------------------------------------------------------------------------
  1717. BOOL DecodeX509_EXTENSIONS(DWORD cbEncoded, BYTE *pbEncoded, DWORD dwDecodeFlags,
  1718. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1719. {
  1720. BOOL fSucceeded=FALSE;
  1721. DWORD cbStructInfo=0;
  1722. void *pStructInfo=NULL;
  1723. LPCSTR lpszStructType=NULL;
  1724. //init
  1725. lpszStructType=X509_EXTENSIONS;
  1726. //Decode the encoded BLOB
  1727. TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,dwDecodeFlags,&cbStructInfo,
  1728. &pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1729. //Decode further the pStructInfo which points to an array of CERT_EXTENSION
  1730. TESTC(DecodeCertExtensions(((PCERT_EXTENSIONS)pStructInfo)->cExtension,
  1731. ((PCERT_EXTENSIONS)pStructInfo)->rgExtension,dwDecodeFlags, fEncode,
  1732. fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1733. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1734. //by checking the size of the encoded blob and do a memcmp.
  1735. if(fEncode)
  1736. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbEncoded,
  1737. pbEncoded),TRUE);
  1738. fSucceeded=TRUE;
  1739. TCLEANUP:
  1740. SAFE_FREE(pStructInfo)
  1741. return fSucceeded;
  1742. }
  1743. //--------------------------------------------------------------------------
  1744. // Decode an array of X509 cert extensions
  1745. //
  1746. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1747. // for *pcbStructInfo from 0 .. CorrectLength-1
  1748. //
  1749. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1750. // for cbEncoded from 0 .. CorrentLength-1
  1751. //--------------------------------------------------------------------------
  1752. BOOL DecodeCertExtensions(DWORD cExtension, PCERT_EXTENSION rgExtension, DWORD dwDecodeFlags,
  1753. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1754. {
  1755. DWORD iIndex=0;
  1756. BOOL fSucceeded=FALSE;
  1757. for(iIndex=0; iIndex<cExtension; iIndex++)
  1758. {
  1759. TESTC(DecodeBasedOnObjID((rgExtension[iIndex]).pszObjId,
  1760. (rgExtension[iIndex]).Value.cbData, (rgExtension[iIndex]).Value.pbData,
  1761. dwDecodeFlags, fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1762. }
  1763. fSucceeded=TRUE;
  1764. TCLEANUP:
  1765. return fSucceeded;
  1766. }
  1767. //--------------------------------------------------------------------------
  1768. // Decode CRYPT_ATTRIBUTE struct and encode
  1769. //
  1770. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1771. // for *pcbStructInfo from 0 .. CorrectLength-1
  1772. //
  1773. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1774. // for cbEncoded from 0 .. CorrentLength-1
  1775. //--------------------------------------------------------------------------
  1776. BOOL DecodeCryptAttribute(PCRYPT_ATTRIBUTE pCryptAttribute,DWORD dwDecodeFlags,
  1777. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1778. {
  1779. BOOL fSucceeded=FALSE;
  1780. DWORD iIndex=0;
  1781. for(iIndex=0; iIndex<pCryptAttribute->cValue;iIndex++)
  1782. {
  1783. TESTC(DecodeBasedOnObjID(pCryptAttribute->pszObjId,
  1784. (pCryptAttribute->rgValue)[iIndex].cbData,
  1785. (pCryptAttribute->rgValue)[iIndex].pbData,
  1786. dwDecodeFlags, fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1787. }
  1788. fSucceeded=TRUE;
  1789. TCLEANUP:
  1790. return fSucceeded;
  1791. }
  1792. //--------------------------------------------------------------------------
  1793. // Decode CRL_ENTRY struct and encode
  1794. //
  1795. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1796. // for *pcbStructInfo from 0 .. CorrectLength-1
  1797. //
  1798. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1799. // for cbEncoded from 0 .. CorrentLength-1
  1800. //--------------------------------------------------------------------------
  1801. BOOL DecodeCRLEntry(PCRL_ENTRY pCrlEntry, DWORD dwDecodeFlags,
  1802. BOOL fEncode,BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1803. {
  1804. BOOL fSucceeded=FALSE;
  1805. //Verify the extensions
  1806. TESTC(VerifyCertExtensions(pCrlEntry->cExtension,
  1807. pCrlEntry->rgExtension,dwDecodeFlags,fEncode,
  1808. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1809. //decode the extensions one by one
  1810. TESTC(DecodeCertExtensions(pCrlEntry->cExtension,
  1811. pCrlEntry->rgExtension,dwDecodeFlags,fEncode,
  1812. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1813. fSucceeded=TRUE;
  1814. TCLEANUP:
  1815. return fSucceeded;
  1816. }
  1817. //--------------------------------------------------------------------------
  1818. // Decode one X509 cert extension
  1819. //
  1820. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1821. // for *pcbStructInfo from 0 .. CorrectLength-1
  1822. //
  1823. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1824. // for cbEncoded from 0 .. CorrentLength-1
  1825. //--------------------------------------------------------------------------
  1826. BOOL DecodeBasedOnObjID(LPSTR szObjId, DWORD cbData, BYTE *pbData,
  1827. DWORD dwDecodeFlags, BOOL fEncode,
  1828. BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1829. {
  1830. BOOL fSucceeded=FALSE;
  1831. DWORD cbStructInfo=0;
  1832. void *pStructInfo=NULL;
  1833. DWORD iIndex=0;
  1834. DWORD cCount=0;
  1835. DWORD iIndexInner=0;
  1836. DWORD cCountInner=0;
  1837. CERT_NAME_BLOB *pBlob=NULL;
  1838. PCERT_ALT_NAME_ENTRY pCertAltNameEntry=NULL;
  1839. PCERT_POLICY_INFO pCertPolicyInfo=NULL;
  1840. PCERT_POLICY_QUALIFIER_INFO pCertPolicyQualifierInfo=NULL;
  1841. LPCSTR lpszStructType=NULL;
  1842. //init
  1843. lpszStructType=MapObjID2StructType(szObjId);
  1844. //return TRUE if we can not recognize the object ID. We can no longer
  1845. //go any further.
  1846. if(!lpszStructType)
  1847. return TRUE;
  1848. //Decode the encoded BLOB
  1849. TESTC(DecodeBLOB(lpszStructType,cbData, pbData,
  1850. dwDecodeFlags,&cbStructInfo,&pStructInfo,fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1851. //further decode the extension if we know what the struct look like
  1852. switch((DWORD_PTR)lpszStructType)
  1853. {
  1854. //we need to further decode CertIssuer in CERT_AUTHORITY_KEY_ID_INFO
  1855. case (DWORD_PTR)(X509_AUTHORITY_KEY_ID):
  1856. pBlob=&(((PCERT_AUTHORITY_KEY_ID_INFO)pStructInfo)->CertIssuer);
  1857. TESTC(DecodeX509_NAME(pBlob->cbData, pBlob->pbData,
  1858. dwDecodeFlags, fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1859. //further decode the BLOB to X509_UNICODE_NAME
  1860. TESTC(DecodeX509_UNICODE_NAME(pBlob->cbData, pBlob->pbData,
  1861. dwDecodeFlags, fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1862. break;
  1863. //we need to further decode the CERT_ALT_NAME_ENTRY array
  1864. case (DWORD_PTR)(X509_ALTERNATE_NAME):
  1865. /* cCount=((PCERT_ALT_NAME_INFO)pStructInfo)->cAltEntry;
  1866. for(iIndex=0; iIndex<cCount; iIndex++)
  1867. {
  1868. pCertAltNameEntry=&(((PCERT_ALT_NAME_INFO)pStructInfo)->rgAltEntry[iIndex]);
  1869. TESTC(DecodeCertAltNameEntry(pCertAltNameEntry,dwDecodeFlags, fEncode,
  1870. fStructLengthCheck, fBLOBLengthCheck),TRUE)
  1871. }
  1872. */
  1873. break;
  1874. //we need to further decode CERT_BASIC_CONSTRAINTS_INFO
  1875. case (DWORD_PTR)(X509_BASIC_CONSTRAINTS):
  1876. cCount=((PCERT_BASIC_CONSTRAINTS_INFO)pStructInfo)->cSubtreesConstraint;
  1877. //decode the array of CERT_NAME_BLOB in rgSubtreesConstraint
  1878. //of CERT_BASIC_CONSTRAINTS_INFO
  1879. for(iIndex=0; iIndex<cCount; iIndex++)
  1880. {
  1881. pBlob=&((((PCERT_BASIC_CONSTRAINTS_INFO)pStructInfo)->rgSubtreesConstraint)[iIndex]);
  1882. TESTC(DecodeX509_NAME(pBlob->cbData, pBlob->pbData,
  1883. dwDecodeFlags, fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1884. //further decode as X509_UNICODE_NAME
  1885. TESTC(DecodeX509_UNICODE_NAME(pBlob->cbData, pBlob->pbData,
  1886. dwDecodeFlags, fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1887. }
  1888. break;
  1889. case (DWORD_PTR)(X509_CERT_POLICIES ):
  1890. cCount=((PCERT_POLICIES_INFO)pStructInfo)->cPolicyInfo;
  1891. for(iIndex=0; iIndex<cCount;iIndex++)
  1892. {
  1893. pCertPolicyInfo=&(((PCERT_POLICIES_INFO)pStructInfo)->rgPolicyInfo[iIndex]);
  1894. cCountInner=pCertPolicyInfo->cPolicyQualifier;
  1895. for(iIndexInner=0; iIndexInner<cCountInner; iIndexInner++)
  1896. {
  1897. pCertPolicyQualifierInfo=&((pCertPolicyInfo->rgPolicyQualifier)[iIndexInner]);
  1898. //Although DecodeBasedOnObjID is called here, we have
  1899. //no risk of an infinite loop.
  1900. //This is a recursive call, which should
  1901. //end when there is no further decodable code, that is,
  1902. //the pszObjID should not be szOID_CERT_POLICIES
  1903. TESTC(DecodeBasedOnObjID(pCertPolicyQualifierInfo->pszPolicyQualifierId,
  1904. pCertPolicyQualifierInfo->Qualifier.cbData,
  1905. pCertPolicyQualifierInfo->Qualifier.pbData,
  1906. dwDecodeFlags, fEncode,fStructLengthCheck,
  1907. fBLOBLengthCheck),TRUE)
  1908. }
  1909. }
  1910. break;
  1911. default:
  1912. break;
  1913. }
  1914. //if requested, encode the BLOB back to what it was. Make sure no data is lost
  1915. //by checking the size of the encoded blob and do a memcmp.
  1916. if(fEncode)
  1917. TCHECK(EncodeAndVerify(lpszStructType, pStructInfo,cbData,
  1918. pbData),TRUE);
  1919. fSucceeded=TRUE;
  1920. TCLEANUP:
  1921. SAFE_FREE(pStructInfo)
  1922. return fSucceeded;
  1923. }
  1924. //--------------------------------------------------------------------------
  1925. // Decode one X509 cert extension
  1926. //
  1927. // fStructLengthCheck: Flag to indicate whether a length checking is necessary
  1928. // for *pcbStructInfo from 0 .. CorrectLength-1
  1929. //
  1930. // fBLOBLengthCheck: Flag to indicate whether a length checking is necessary
  1931. // for cbEncoded from 0 .. CorrentLength-1
  1932. //--------------------------------------------------------------------------
  1933. BOOL DecodeCertAltNameEntry(PCERT_ALT_NAME_ENTRY pCertAltNameEntry,
  1934. DWORD dwDecodeFlags, BOOL fEncode,
  1935. BOOL fStructLengthCheck, BOOL fBLOBLengthCheck)
  1936. {
  1937. BOOL fSucceeded=FALSE;
  1938. PCRYPT_ATTRIBUTE_TYPE_VALUE pAttributeTypeValue=NULL;
  1939. assert(pCertAltNameEntry);
  1940. switch(pCertAltNameEntry->dwAltNameChoice)
  1941. {
  1942. case CERT_ALT_NAME_DIRECTORY_NAME:
  1943. //further decode the NAME_BLOB in DirectoryName
  1944. TESTC(DecodeX509_NAME(pCertAltNameEntry->DirectoryName.cbData,
  1945. pCertAltNameEntry->DirectoryName.pbData,
  1946. dwDecodeFlags,fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1947. //decode it as UNICODE
  1948. TESTC(DecodeX509_UNICODE_NAME(pCertAltNameEntry->DirectoryName.cbData,
  1949. pCertAltNameEntry->DirectoryName.pbData,
  1950. dwDecodeFlags,fEncode,fStructLengthCheck,fBLOBLengthCheck),TRUE)
  1951. break;
  1952. default:
  1953. break;
  1954. }
  1955. fSucceeded=TRUE;
  1956. TCLEANUP:
  1957. return fSucceeded;
  1958. }