Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

907 lines
20 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: check7f.cpp
  7. //
  8. // Contents: Cert Server test for ASN-encoded 7f length
  9. //
  10. //---------------------------------------------------------------------------
  11. #include <pch.cpp>
  12. #pragma hdrstop
  13. #include <stdlib.h>
  14. #include <assert.h>
  15. #include "csdisp.h"
  16. typedef struct _ASNTABLE {
  17. WORD State;
  18. WORD Flags;
  19. WCHAR const *pwszElement;
  20. } ASNTABLE;
  21. #define BOOLEAN_TAG 0x01
  22. #define INTEGER_TAG 0x02
  23. #define BIT_STRING_TAG 0x03
  24. #define OCTET_STRING_TAG 0x04
  25. #define NULL_TAG 0x05
  26. #define OBJECT_ID_TAG 0x06
  27. #define SET_OF_TAG 0x11
  28. #define PRINTABLE_STRING_TAG 0x13
  29. #define TELETEX_STRING_TAG 0x14
  30. #define CHAR_STRING_TAG 0x16
  31. #define UTCTIME_TAG 0x17
  32. #define SEQUENCE_TAG 0x30
  33. #define RDN_TAG 0x31
  34. #define PRIMITIVE_TAG 0x80
  35. #define ATTRIBUTE_TAG 0xa0
  36. #define BEG_REPEAT1 0x00000100 // begin repeat section
  37. #define BEG_REPEAT2 0x00000200 // begin nested repeat section
  38. #define END_REPEAT1 0x00000400 // 'or' in back step count
  39. #define END_REPEAT2 0x00000800 // 'or' in back step count
  40. #define OPTIONAL_FIELD 0x00001000 // begin optional field
  41. #define ANY_TAG 0x00002000 // match any tag
  42. const ASNTABLE asnCert[] = {
  43. { CHECK7F_OTHER, SEQUENCE_TAG, L"Certificate" },
  44. { CHECK7F_OTHER, SEQUENCE_TAG, L".ToBeSigned" },
  45. { CHECK7F_OTHER, ATTRIBUTE_TAG | OPTIONAL_FIELD, L"..Version" },
  46. { CHECK7F_OTHER, INTEGER_TAG , L"...Version.Integer" },
  47. { CHECK7F_OTHER, INTEGER_TAG, L"..SerialNumber" },
  48. { CHECK7F_OTHER, SEQUENCE_TAG, L"..SignatureAlgorithm" },
  49. { CHECK7F_OTHER, OBJECT_ID_TAG, L"...SignatureAlgorithm.ObjectId" },
  50. { CHECK7F_OTHER, ANY_TAG | OPTIONAL_FIELD, L"...SignatureAlgorithm.Parameters" },
  51. { CHECK7F_ISSUER, SEQUENCE_TAG, L"..Issuer Name" },
  52. { CHECK7F_ISSUER_RDN,
  53. BEG_REPEAT1 | RDN_TAG | OPTIONAL_FIELD, L"...Issuer.RDN" },
  54. { CHECK7F_ISSUER_RDN_ATTRIBUTE,
  55. BEG_REPEAT2 | SEQUENCE_TAG, L"....Issuer.RDN.Attribute" },
  56. { CHECK7F_OTHER, OBJECT_ID_TAG, L".....Issuer.RDN.Attribute.ObjectId" },
  57. { CHECK7F_ISSUER_RDN_STRING, ANY_TAG, L".....Issuer.RDN.Attribute.Value" },
  58. { 0, END_REPEAT2 | 3, L"...." },
  59. { 0, END_REPEAT1 | 5, L"..." },
  60. { CHECK7F_OTHER, SEQUENCE_TAG, L"..Dates" },
  61. { CHECK7F_OTHER, UTCTIME_TAG, L"...Dates.NotBefore" },
  62. { CHECK7F_OTHER, UTCTIME_TAG, L"...Dates.NotAfter" },
  63. { CHECK7F_SUBJECT, SEQUENCE_TAG, L"..Subject Name" },
  64. { CHECK7F_SUBJECT_RDN,
  65. BEG_REPEAT1 | RDN_TAG | OPTIONAL_FIELD, L"...Subject.RDN" },
  66. { CHECK7F_SUBJECT_RDN_ATTRIBUTE,
  67. BEG_REPEAT2 | SEQUENCE_TAG, L"....Subject.RDN.Attribute" },
  68. { CHECK7F_OTHER, OBJECT_ID_TAG, L".....Subject.RDN.Attribute.ObjectId" },
  69. { CHECK7F_SUBJECT_RDN_STRING, ANY_TAG, L".....Subject.RDN.Attribute.Value" },
  70. { 0, END_REPEAT2 | 3, L"...." },
  71. { 0, END_REPEAT1 | 5, L"..." },
  72. { CHECK7F_OTHER, SEQUENCE_TAG, L"..PublicKey" },
  73. { CHECK7F_OTHER, SEQUENCE_TAG, L"...PublicKey.Algorithm" },
  74. { CHECK7F_OTHER, OBJECT_ID_TAG, L"....PublicKey.Algorithm.ObjectId" },
  75. { CHECK7F_OTHER, ANY_TAG | OPTIONAL_FIELD, L"....PublicKey.Algorithm.Parameters" },
  76. { CHECK7F_OTHER, BIT_STRING_TAG, L"...PublicKey.Key" },
  77. { CHECK7F_OTHER,
  78. PRIMITIVE_TAG | 1 | OPTIONAL_FIELD, L"..IssuerUniqueId" },
  79. { CHECK7F_OTHER,
  80. PRIMITIVE_TAG | 2 | OPTIONAL_FIELD, L"..SubjectUniqueId" },
  81. { CHECK7F_EXTENSIONS,
  82. ATTRIBUTE_TAG | 3 | OPTIONAL_FIELD, L"..Extensions" },
  83. { CHECK7F_EXTENSION_ARRAY, SEQUENCE_TAG, L"...Extensions.Array" },
  84. { CHECK7F_EXTENSION,
  85. BEG_REPEAT1 | SEQUENCE_TAG, L"....Extensions.Array.Extension" },
  86. { CHECK7F_OTHER, OBJECT_ID_TAG, L".....Extensions.Array.Extension.ObjectId" },
  87. { CHECK7F_OTHER, BOOLEAN_TAG | OPTIONAL_FIELD, L".....Extensions.Array.Extension.Critical" },
  88. { CHECK7F_EXTENSION_VALUE, OCTET_STRING_TAG, L".....Extensions.Array.Extension.Value" },
  89. //{ CHECK7F_EXTENSION_VALUE_RAW, ANY_TAG, L"......Extensions.Array.Extension.Value.Bits" },
  90. { 0, END_REPEAT1 | 4, L"...." },
  91. { CHECK7F_OTHER, SEQUENCE_TAG, L".SignatureAlogorithm" },
  92. { CHECK7F_OTHER, OBJECT_ID_TAG, L"..SignatureAlgorithm.ObjectId" },
  93. { CHECK7F_OTHER, ANY_TAG | OPTIONAL_FIELD, L"..SignatureAlgorithm.Parameters" },
  94. { CHECK7F_OTHER, BIT_STRING_TAG, L".Signature" },
  95. { 0, 0, NULL }
  96. };
  97. #define cbOLDCERTENROLLCHOKESLENGTH 0x7f
  98. // DecodeLength decodes an ASN1 encoded length field. The pbEncoded parameter
  99. // is the encoded length. pdwLen is used to return the length. The function
  100. // returns a -1 if it fails and otherwise returns the number of total bytes in
  101. // the encoded length.
  102. long
  103. DecodeLength(
  104. BOOL fVerbose,
  105. DWORD *pdwLen,
  106. DWORD iLevel,
  107. BYTE const *pbBase,
  108. BYTE const *pbEncoded,
  109. DWORD cbEncoded,
  110. WCHAR const *pwsz)
  111. {
  112. long index = 0;
  113. BYTE count;
  114. assert(NULL != pdwLen);
  115. assert(NULL != pbEncoded);
  116. if (1 > cbEncoded)
  117. {
  118. DBGPRINT((DBG_SS_CERTLIB, "cbEncoded overflow %d\n", cbEncoded));
  119. return(-1);
  120. }
  121. // determine the length of the length field
  122. count = pbEncoded[0];
  123. if (0x80 < count)
  124. {
  125. // If there is more than one byte in the length field, then the lower
  126. // seven bits tells us the number of bytes.
  127. count &= 0x7f;
  128. // This function only allows the length field to be 2 bytes. If the
  129. // field is longer, then the function fails.
  130. if (2 < count)
  131. {
  132. DBGPRINT((DBG_SS_CERTLIB, "Length field reported to be over 2 bytes\n"));
  133. return(-1);
  134. }
  135. if (count > cbEncoded)
  136. {
  137. DBGPRINT((DBG_SS_CERTLIB, "cbEncoded overflow %d\n", cbEncoded));
  138. return(-1);
  139. }
  140. *pdwLen = 0;
  141. // go through the bytes of the length field
  142. for (index = 1; index <= count; index++)
  143. {
  144. *pdwLen = (*pdwLen << 8) + pbEncoded[index];
  145. }
  146. }
  147. else // the length field is just one byte long
  148. {
  149. *pdwLen = pbEncoded[0];
  150. index = 1;
  151. }
  152. // return how many bytes there were in the length field.
  153. #if DBG_CERTSRV
  154. if (fVerbose)
  155. {
  156. CONSOLEPRINT7((
  157. DBG_SS_CERTLIB,
  158. "asn %u:@%x: %02x, len %x, cbEncoded %x, end @%x, %ws\n",
  159. iLevel,
  160. &pbEncoded[-1] - pbBase,
  161. pbEncoded[-1],
  162. *pdwLen,
  163. cbEncoded + 1,
  164. &pbEncoded[-1] - pbBase + cbEncoded + 1,
  165. pwsz));
  166. }
  167. #endif // DBG_CERTSRV
  168. return(index);
  169. }
  170. WCHAR const *
  171. GetLevel(
  172. OPTIONAL IN WCHAR const *pwszField,
  173. OUT DWORD *piLevel)
  174. {
  175. DWORD iLevel = 0;
  176. iLevel = 0;
  177. if (NULL != pwszField)
  178. {
  179. while ('.' == *pwszField)
  180. {
  181. iLevel++;
  182. pwszField++;
  183. }
  184. }
  185. *piLevel = iLevel;
  186. return(pwszField);
  187. }
  188. BOOL
  189. RestoreLevel(
  190. IN DWORD *acbLevel,
  191. IN DWORD iLevelNext,
  192. IN DWORD *piLevel,
  193. IN BOOL fVerbose)
  194. {
  195. BOOL fOk = FALSE;
  196. DWORD iLevel;
  197. DWORD i = *piLevel;
  198. #if DBG_CERTSRV
  199. if (1 < fVerbose)
  200. {
  201. CONSOLEPRINT2((
  202. DBG_SS_CERTLIBI,
  203. "RestoreLevel(%x, %x)\n",
  204. iLevelNext,
  205. *piLevel));
  206. }
  207. #endif
  208. iLevel = *piLevel;
  209. while (0 < iLevel && 0 == acbLevel[iLevel] && iLevelNext < iLevel)
  210. {
  211. iLevel--;
  212. if (1 < fVerbose)
  213. {
  214. CONSOLEPRINT2((
  215. DBG_SS_CERTLIBI,
  216. "Restoring length(%u) ==> %x\n",
  217. iLevel,
  218. acbLevel[iLevel]));
  219. }
  220. }
  221. if (iLevelNext < iLevel)
  222. {
  223. CONSOLEPRINT2((
  224. MAXDWORD,
  225. "BAD RESTORED LENGTH[%u]: 0 < %x\n",
  226. iLevel,
  227. acbLevel[iLevel]));
  228. goto error;
  229. }
  230. *piLevel = iLevel;
  231. fOk = TRUE;
  232. error:
  233. if (1 < fVerbose)
  234. {
  235. CONSOLEPRINT4((
  236. DBG_SS_CERTLIBI,
  237. "RestoreLevel(%x, %x --> %x) --> %x\n",
  238. iLevelNext,
  239. i,
  240. *piLevel,
  241. fOk));
  242. }
  243. return(fOk);
  244. }
  245. VOID
  246. ReturnString(
  247. IN WCHAR const *pwszReturn,
  248. OPTIONAL IN OUT DWORD *pcwcBuf,
  249. OPTIONAL OUT WCHAR *pwcBuf)
  250. {
  251. DWORD cwcNeeded = wcslen(pwszReturn) + 1;
  252. DWORD cwcBuf;
  253. if (NULL != pcwcBuf)
  254. {
  255. cwcBuf = *pcwcBuf;
  256. if (NULL != pwcBuf && 0 < cwcBuf)
  257. {
  258. CopyMemory(pwcBuf, pwszReturn, sizeof(WCHAR) * min(cwcBuf, cwcNeeded));
  259. pwcBuf[cwcBuf - 1] = L'\0';
  260. }
  261. *pcwcBuf = cwcNeeded;
  262. }
  263. }
  264. #define MATCHTAG(b, flags) ((ANY_TAG & (flags)) || (b) == (BYTE) (flags))
  265. HRESULT
  266. myCheck7f(
  267. IN const BYTE *pbCert,
  268. IN DWORD cbCert,
  269. IN BOOL fVerbose,
  270. OUT DWORD *pState,
  271. OPTIONAL OUT DWORD *pIndex1,
  272. OPTIONAL OUT DWORD *pIndex2,
  273. OPTIONAL IN OUT DWORD *pcwcField,
  274. OPTIONAL OUT WCHAR *pwszField,
  275. OPTIONAL IN OUT DWORD *pcwcObjectId,
  276. OPTIONAL OUT WCHAR *pwszObjectId,
  277. OPTIONAL OUT WCHAR const **ppwszObjectIdDescription)
  278. {
  279. ASNTABLE const *pasn;
  280. HRESULT hr = S_OK;
  281. BOOL fSaveCert = TRUE;
  282. BYTE const *pb = pbCert;
  283. long index;
  284. DWORD length;
  285. DWORD acbLevel[20];
  286. DWORD iLevel;
  287. DWORD iLevelNext;
  288. WCHAR const *pwszfieldname;
  289. DWORD cbdiff;
  290. DWORD aiElement[20];
  291. DWORD aiElement7f[2];
  292. DWORD iElementLevel;
  293. DWORD State;
  294. BOOL fSetField = FALSE;
  295. BOOL fSetObjectId = FALSE;
  296. CERT_INFO *pCertInfo = NULL;
  297. DWORD cbCertInfo;
  298. CERT_NAME_INFO *pNameInfo = NULL;
  299. DWORD cbNameInfo;
  300. WCHAR *pwszObjId = NULL;
  301. State = CHECK7F_NONE;
  302. if (NULL != ppwszObjectIdDescription)
  303. {
  304. *ppwszObjectIdDescription = NULL;
  305. }
  306. #if DBG_CERTSRV
  307. if (!fVerbose && DbgIsSSActive(DBG_SS_CERTLIBI))
  308. {
  309. fVerbose = TRUE;
  310. }
  311. #endif // DBG_CERTSRV
  312. if (fVerbose)
  313. {
  314. CONSOLEPRINT1((MAXDWORD, "myCheck7f: %x bytes\n", cbCert));
  315. }
  316. pasn = asnCert;
  317. iLevel = 0;
  318. ZeroMemory(aiElement7f, sizeof(aiElement7f));
  319. acbLevel[iLevel] = cbCert;
  320. iElementLevel = 0;
  321. while (0 != iLevel || (0 != acbLevel[iLevel] && NULL != pasn->pwszElement))
  322. {
  323. DWORD i;
  324. if (1 < fVerbose)
  325. {
  326. if (2 < fVerbose)
  327. {
  328. CONSOLEPRINT3((
  329. DBG_SS_CERTLIBI,
  330. "ASN:0: *pb=%x %u: %ws\n",
  331. *pb,
  332. pasn - asnCert,
  333. pasn->pwszElement));
  334. }
  335. CONSOLEPRINT0((MAXDWORD, "LENGTHS:0:"));
  336. for (i = 0; i <= iLevel; i++)
  337. {
  338. CONSOLEPRINT1((MAXDWORD, " %3x", acbLevel[i]));
  339. }
  340. CONSOLEPRINT0((MAXDWORD, "\n"));
  341. }
  342. while (OPTIONAL_FIELD & pasn->Flags)
  343. {
  344. DWORD f;
  345. if (0 < acbLevel[iLevel] && MATCHTAG(*pb, pasn->Flags))
  346. {
  347. #if DBG_CERTSRV
  348. if (fVerbose)
  349. {
  350. CONSOLEPRINT2((
  351. DBG_SS_CERTLIB,
  352. "Optional field MATCH cb=%x %ws\n",
  353. acbLevel[iLevel],
  354. pasn->pwszElement));
  355. }
  356. #endif // DBG_CERTSRV
  357. break;
  358. }
  359. #if DBG_CERTSRV
  360. if (fVerbose)
  361. {
  362. CONSOLEPRINT2((
  363. DBG_SS_CERTLIB,
  364. "Optional field NO match cb=%x %ws\n",
  365. acbLevel[iLevel],
  366. pasn->pwszElement));
  367. }
  368. #endif // DBG_CERTSRV
  369. f = 0;
  370. switch ((BEG_REPEAT1 | BEG_REPEAT2) & pasn->Flags)
  371. {
  372. case BEG_REPEAT1:
  373. f = END_REPEAT1;
  374. break;
  375. case BEG_REPEAT2:
  376. f = END_REPEAT2;
  377. break;
  378. }
  379. if (f)
  380. {
  381. while (!(f & pasn->Flags))
  382. {
  383. #if DBG_CERTSRV
  384. if (fVerbose)
  385. {
  386. CONSOLEPRINT2((
  387. DBG_SS_CERTLIB,
  388. "Skipping[%x] %ws\n",
  389. f,
  390. pasn->pwszElement));
  391. }
  392. #endif // DBG_CERTSRV
  393. pasn++;
  394. }
  395. }
  396. else
  397. {
  398. DWORD iLevelCurrent;
  399. GetLevel(pasn->pwszElement, &iLevelCurrent);
  400. while (TRUE)
  401. {
  402. GetLevel(pasn[1].pwszElement, &iLevelNext);
  403. if (iLevelNext <= iLevelCurrent)
  404. {
  405. break;
  406. }
  407. #if DBG_CERTSRV
  408. if (fVerbose)
  409. {
  410. CONSOLEPRINT1((
  411. DBG_SS_CERTLIB,
  412. "Skipping nested optional field %ws\n",
  413. pasn->pwszElement));
  414. }
  415. #endif // DBG_CERTSRV
  416. pasn++;
  417. }
  418. }
  419. #if DBG_CERTSRV
  420. if (fVerbose)
  421. {
  422. CONSOLEPRINT1((
  423. DBG_SS_CERTLIB,
  424. "Skipping optional field %ws\n",
  425. pasn->pwszElement));
  426. }
  427. #endif // DBG_CERTSRV
  428. pasn++;
  429. if (0 == acbLevel[iLevel])
  430. {
  431. GetLevel(pasn->pwszElement, &iLevelNext);
  432. if (iLevelNext < iLevel)
  433. {
  434. iLevel = iLevelNext;
  435. }
  436. }
  437. }
  438. while ((END_REPEAT1 | END_REPEAT2) & pasn->Flags)
  439. {
  440. // Make sure only one END_REPEAT bit is on.
  441. assert(
  442. (END_REPEAT1 | END_REPEAT2) !=
  443. ((END_REPEAT1 | END_REPEAT2) & pasn->Flags));
  444. pwszfieldname = GetLevel(pasn->pwszElement, &iLevelNext);
  445. if (!RestoreLevel(acbLevel, iLevelNext, &iLevel, fVerbose))
  446. {
  447. goto error;
  448. }
  449. i = (BYTE) pasn->Flags;
  450. assert((DWORD) (pasn - asnCert) > i);
  451. if (0 != acbLevel[iLevel])
  452. {
  453. if (!MATCHTAG(*pb, (pasn - i)->Flags))
  454. {
  455. CONSOLEPRINT5((
  456. MAXDWORD,
  457. "Check7f: Unexpected tag at %x: at level %u: (%x/%x) %ws\n",
  458. cbCert - acbLevel[0],
  459. iLevel,
  460. *pb,
  461. pasn->Flags,
  462. pasn->pwszElement));
  463. goto error;
  464. }
  465. // Some data remain at this level, and the type tag matches
  466. // the expected repeat tag, loop back to the start of the
  467. // section to be repeated.
  468. pasn -= i;
  469. // Make sure only one BEG_REPEAT bit is on.
  470. assert(
  471. (BEG_REPEAT1 | BEG_REPEAT2) !=
  472. ((BEG_REPEAT1 | BEG_REPEAT2) & pasn->Flags));
  473. // Make sure the BEG_REPEAT bit in the begin record matches
  474. // the END_REPEAT bit in the end record.
  475. assert(
  476. ((BEG_REPEAT1 & pasn->Flags) &&
  477. (END_REPEAT1 & pasn[i].Flags)) ||
  478. ((BEG_REPEAT2 & pasn->Flags) &&
  479. (END_REPEAT2 & pasn[i].Flags)));
  480. }
  481. else
  482. {
  483. pasn++;
  484. iElementLevel--;
  485. }
  486. }
  487. if (2 < fVerbose)
  488. {
  489. CONSOLEPRINT3((
  490. DBG_SS_CERTLIBI,
  491. "ASN:1: *pb=%x %u: %ws\n",
  492. *pb,
  493. pasn - asnCert,
  494. pasn->pwszElement));
  495. }
  496. if ((BEG_REPEAT1 | BEG_REPEAT2) & pasn->Flags)
  497. {
  498. if ((BEG_REPEAT1 & pasn->Flags) && 0 == iElementLevel ||
  499. (BEG_REPEAT2 & pasn->Flags) && 1 == iElementLevel)
  500. {
  501. iElementLevel++;
  502. aiElement[iElementLevel] = 0;
  503. }
  504. aiElement[iElementLevel]++;
  505. }
  506. pwszfieldname = GetLevel(pasn->pwszElement, &iLevelNext);
  507. if (!RestoreLevel(acbLevel, iLevelNext, &iLevel, fVerbose))
  508. {
  509. goto error;
  510. }
  511. if (1 < fVerbose)
  512. {
  513. CONSOLEPRINT0((MAXDWORD, "LENGTHS:1:"));
  514. for (i = 0; i <= iLevel; i++)
  515. {
  516. CONSOLEPRINT1((MAXDWORD, " %3x", acbLevel[i]));
  517. }
  518. CONSOLEPRINT0((MAXDWORD, "\n"));
  519. }
  520. if (0 == iLevel && 0 == acbLevel[0])
  521. {
  522. break; // all done!
  523. }
  524. if (!MATCHTAG(*pb, pasn->Flags))
  525. {
  526. CONSOLEPRINT5((
  527. MAXDWORD,
  528. "Check7f: Unexpected tag at %x: at level %u: (%x/%x) %ws\n",
  529. cbCert - acbLevel[0],
  530. iLevel,
  531. *pb,
  532. pasn->Flags,
  533. pasn->pwszElement));
  534. goto error;
  535. }
  536. GetLevel(pasn[1].pwszElement, &iLevelNext);
  537. index = DecodeLength(
  538. fVerbose,
  539. &length,
  540. iLevel,
  541. pbCert,
  542. &pb[1],
  543. acbLevel[iLevel] - 1,
  544. pasn->pwszElement);
  545. if (fVerbose)
  546. {
  547. DWORD ccol;
  548. char achdbg[128];
  549. char *pchdbg;
  550. //char achbuf[10];
  551. pchdbg = achdbg;
  552. pchdbg += sprintf(pchdbg, "%04x:", pb - pbCert);
  553. for (i = 0; i <= iLevel; i++)
  554. {
  555. pchdbg += sprintf(pchdbg, " %3x", acbLevel[i]);
  556. }
  557. pchdbg += sprintf(pchdbg, " (%x)", length);
  558. ccol = SAFE_SUBTRACT_POINTERS(pchdbg, achdbg);
  559. if (ccol > 34)
  560. {
  561. ccol = 34;
  562. }
  563. pchdbg += sprintf(pchdbg, " %*hs -- ", 34 - ccol, "");
  564. assert(2 >= iElementLevel);
  565. if (1 == iElementLevel)
  566. {
  567. pchdbg += sprintf(pchdbg, "[%u]:", aiElement[1] - 1);
  568. }
  569. else if (2 == iElementLevel)
  570. {
  571. pchdbg += sprintf(
  572. pchdbg,
  573. "[%u,%u]:",
  574. aiElement[1] - 1,
  575. aiElement[2] - 1);
  576. }
  577. CONSOLEPRINT2((DBG_SS_CERTLIBI, "%hs%ws\n", achdbg, pwszfieldname));
  578. }
  579. if (length == cbOLDCERTENROLLCHOKESLENGTH)
  580. {
  581. CONSOLEPRINT2((
  582. MAXDWORD,
  583. "Check7f: Length of %ws is %u bytes\n",
  584. pwszfieldname,
  585. length));
  586. if (CHECK7F_NONE == State)
  587. {
  588. ReturnString(pwszfieldname, pcwcField, pwszField);
  589. if (1 <= iElementLevel)
  590. {
  591. aiElement7f[0] = aiElement[1];
  592. }
  593. if (2 <= iElementLevel)
  594. {
  595. aiElement7f[1] = aiElement[2];
  596. }
  597. State = pasn->State;
  598. fSetField = TRUE;
  599. }
  600. }
  601. if (1 < fVerbose)
  602. {
  603. CONSOLEPRINT6((
  604. DBG_SS_CERTLIBI,
  605. "index=%x len=%x level=%x->%x acb[%x]=%x\n",
  606. index,
  607. length,
  608. iLevel,
  609. iLevelNext,
  610. iLevel,
  611. acbLevel[iLevel]));
  612. }
  613. if (0 > index || index + length > acbLevel[iLevel])
  614. {
  615. CONSOLEPRINT2((
  616. MAXDWORD,
  617. "Check7f: BAD LENGTH: i=%x l=%x\n",
  618. index,
  619. length));
  620. goto error;
  621. }
  622. cbdiff = index + 1;
  623. if (iLevelNext > iLevel)
  624. {
  625. assert(iLevel + 1 == iLevelNext);
  626. }
  627. else
  628. {
  629. cbdiff += length;
  630. }
  631. for (i = 0; i <= iLevel; i++)
  632. {
  633. if (acbLevel[i] < cbdiff)
  634. {
  635. CONSOLEPRINT3((
  636. MAXDWORD,
  637. "Check7f: BAD NESTED LENGTH[%u]: %x < %x\n",
  638. i,
  639. acbLevel[i],
  640. cbdiff));
  641. goto error;
  642. }
  643. acbLevel[i] -= cbdiff;
  644. }
  645. if (iLevelNext > iLevel)
  646. {
  647. iLevel++;
  648. if (1 < fVerbose)
  649. {
  650. CONSOLEPRINT2((
  651. DBG_SS_CERTLIBI,
  652. "Saving length(%u) <== %x\n",
  653. iLevel,
  654. length));
  655. }
  656. acbLevel[iLevel] = length;
  657. }
  658. pb += cbdiff;
  659. pasn++;
  660. }
  661. *pIndex1 = 0;
  662. if (0 != iLevel || 0 != acbLevel[iLevel] || NULL != pasn->pwszElement)
  663. {
  664. CONSOLEPRINT3((
  665. MAXDWORD,
  666. "Check7f: Mismatch: %x bytes left at: %x: %ws\n",
  667. acbLevel[iLevel],
  668. cbCert - acbLevel[0],
  669. pasn->pwszElement));
  670. }
  671. else if (!fSetField)
  672. {
  673. fSaveCert = FALSE;
  674. }
  675. if (fSetField && NULL != pcwcObjectId)
  676. {
  677. char const *pszObjId;
  678. CERT_NAME_BLOB const *pNameBlob;
  679. // Decode certificate
  680. cbCertInfo = 0;
  681. if (!myDecodeObject(
  682. X509_ASN_ENCODING,
  683. X509_CERT_TO_BE_SIGNED,
  684. pbCert,
  685. cbCert,
  686. CERTLIB_USE_LOCALALLOC,
  687. (VOID **) &pCertInfo,
  688. &cbCertInfo))
  689. {
  690. hr = GetLastError();
  691. goto error;
  692. }
  693. pszObjId = NULL;
  694. pNameBlob = NULL;
  695. switch (State)
  696. {
  697. case CHECK7F_ISSUER_RDN:
  698. case CHECK7F_ISSUER_RDN_ATTRIBUTE:
  699. case CHECK7F_ISSUER_RDN_STRING:
  700. pNameBlob = &pCertInfo->Issuer;
  701. break;
  702. case CHECK7F_SUBJECT_RDN:
  703. case CHECK7F_SUBJECT_RDN_ATTRIBUTE:
  704. case CHECK7F_SUBJECT_RDN_STRING:
  705. pNameBlob = &pCertInfo->Subject;
  706. break;
  707. case CHECK7F_EXTENSION:
  708. case CHECK7F_EXTENSION_VALUE:
  709. case CHECK7F_EXTENSION_VALUE_RAW:
  710. if (0 != aiElement7f[0] &&
  711. aiElement7f[0] <= pCertInfo->cExtension)
  712. {
  713. pszObjId =
  714. pCertInfo->rgExtension[aiElement7f[0] - 1].pszObjId;
  715. }
  716. break;
  717. default:
  718. break;
  719. }
  720. if (NULL != pNameBlob)
  721. {
  722. if (!myDecodeName(
  723. X509_ASN_ENCODING,
  724. X509_UNICODE_NAME,
  725. pNameBlob->pbData,
  726. pNameBlob->cbData,
  727. CERTLIB_USE_LOCALALLOC,
  728. &pNameInfo,
  729. &cbNameInfo))
  730. {
  731. hr = GetLastError();
  732. goto error;
  733. }
  734. if (0 != aiElement7f[0] && aiElement7f[0] <= pNameInfo->cRDN)
  735. {
  736. CERT_RDN *pRDN;
  737. pRDN = &pNameInfo->rgRDN[aiElement7f[0] - 1];
  738. if (0 != aiElement7f[1] && aiElement7f[1] <= pRDN->cRDNAttr)
  739. {
  740. pszObjId = pRDN->rgRDNAttr[aiElement7f[1] - 1].pszObjId;
  741. }
  742. }
  743. }
  744. if (NULL != pszObjId)
  745. {
  746. if (!ConvertSzToWsz(&pwszObjId, pszObjId, -1))
  747. {
  748. hr = E_OUTOFMEMORY;
  749. goto error;
  750. }
  751. ReturnString(pwszObjId, pcwcObjectId, pwszObjectId);
  752. fSetObjectId = TRUE;
  753. if (NULL != ppwszObjectIdDescription)
  754. {
  755. WCHAR const *pwszDesc;
  756. pwszDesc = myGetOIDNameA(pszObjId);
  757. if (NULL != pwszDesc && L'\0' != *pwszDesc)
  758. {
  759. *ppwszObjectIdDescription = pwszDesc;
  760. }
  761. }
  762. }
  763. }
  764. error:
  765. if (fSaveCert)
  766. {
  767. EncodeToFileW(
  768. fSetField? L"c:\\7flen.crt" : L"c:\\7fasn.crt",
  769. pbCert,
  770. cbCert,
  771. DECF_FORCEOVERWRITE | CRYPT_STRING_BINARY);
  772. }
  773. if (NULL != pCertInfo)
  774. {
  775. LocalFree(pCertInfo);
  776. }
  777. if (NULL != pNameInfo)
  778. {
  779. LocalFree(pNameInfo);
  780. }
  781. if (NULL != pwszObjId)
  782. {
  783. LocalFree(pwszObjId);
  784. }
  785. *pState = State;
  786. if (NULL != pIndex1)
  787. {
  788. *pIndex1 = aiElement7f[0];
  789. }
  790. if (NULL != pIndex2)
  791. {
  792. *pIndex2 = aiElement7f[1];
  793. }
  794. if (!fSetField && NULL != pcwcField)
  795. {
  796. if (NULL != pwszField && 0 < *pcwcField)
  797. {
  798. pwszField[0] = L'\0';
  799. }
  800. *pcwcField = 0;
  801. }
  802. if (!fSetObjectId && NULL != pcwcObjectId)
  803. {
  804. if (NULL != pwszObjectId && 0 < *pcwcObjectId)
  805. {
  806. pwszObjectId[0] = L'\0';
  807. }
  808. *pcwcObjectId = 0;
  809. }
  810. if (fVerbose)
  811. {
  812. CONSOLEPRINT1((MAXDWORD, "myCheck7f: --> %x\n", hr));
  813. }
  814. return(hr);
  815. }