CryptTs.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. /** @file
  2. RFC3161 Timestamp Countersignature Verification over OpenSSL.
  3. The timestamp is generated by a TimeStamping Authority (TSA) and asserts that a
  4. publisher's signature existed before the specified time. The timestamp extends
  5. the lifetime of the signature when a signing certificate expires or is later
  6. revoked.
  7. Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
  8. SPDX-License-Identifier: BSD-2-Clause-Patent
  9. **/
  10. #include "InternalCryptLib.h"
  11. #include <openssl/asn1.h>
  12. #include <openssl/asn1t.h>
  13. #include <openssl/x509.h>
  14. #include <openssl/x509v3.h>
  15. #include <openssl/pkcs7.h>
  16. //
  17. // OID ASN.1 Value for SPC_RFC3161_OBJID ("1.3.6.1.4.1.311.3.3.1")
  18. //
  19. UINT8 mSpcRFC3161OidValue[] = {
  20. 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x03, 0x03, 0x01
  21. };
  22. ///
  23. /// The messageImprint field SHOULD contain the hash of the datum to be
  24. /// time-stamped. The hash is represented as an OCTET STRING. Its
  25. /// length MUST match the length of the hash value for that algorithm
  26. /// (e.g., 20 bytes for SHA-1 or 16 bytes for MD5).
  27. ///
  28. /// MessageImprint ::= SEQUENCE {
  29. /// hashAlgorithm AlgorithmIdentifier,
  30. /// hashedMessage OCTET STRING }
  31. ///
  32. typedef struct {
  33. X509_ALGOR *HashAlgorithm;
  34. ASN1_OCTET_STRING *HashedMessage;
  35. } TS_MESSAGE_IMPRINT;
  36. //
  37. // ASN.1 Functions for TS_MESSAGE_IMPRINT
  38. //
  39. DECLARE_ASN1_FUNCTIONS (TS_MESSAGE_IMPRINT)
  40. ASN1_SEQUENCE (TS_MESSAGE_IMPRINT) = {
  41. ASN1_SIMPLE (TS_MESSAGE_IMPRINT, HashAlgorithm, X509_ALGOR),
  42. ASN1_SIMPLE (TS_MESSAGE_IMPRINT, HashedMessage, ASN1_OCTET_STRING)
  43. } ASN1_SEQUENCE_END (TS_MESSAGE_IMPRINT)
  44. IMPLEMENT_ASN1_FUNCTIONS (TS_MESSAGE_IMPRINT)
  45. ///
  46. /// Accuracy represents the time deviation around the UTC time contained
  47. /// in GeneralizedTime of time-stamp token.
  48. ///
  49. /// Accuracy ::= SEQUENCE {
  50. /// seconds INTEGER OPTIONAL,
  51. /// millis [0] INTEGER (1..999) OPTIONAL,
  52. /// micros [1] INTEGER (1..999) OPTIONAL }
  53. ///
  54. typedef struct {
  55. ASN1_INTEGER *Seconds;
  56. ASN1_INTEGER *Millis;
  57. ASN1_INTEGER *Micros;
  58. } TS_ACCURACY;
  59. //
  60. // ASN.1 Functions for TS_ACCURACY
  61. //
  62. DECLARE_ASN1_FUNCTIONS (TS_ACCURACY)
  63. ASN1_SEQUENCE (TS_ACCURACY) = {
  64. ASN1_OPT (TS_ACCURACY, Seconds, ASN1_INTEGER),
  65. ASN1_IMP_OPT (TS_ACCURACY, Millis, ASN1_INTEGER, 0),
  66. ASN1_IMP_OPT (TS_ACCURACY, Micros, ASN1_INTEGER, 1)
  67. } ASN1_SEQUENCE_END (TS_ACCURACY)
  68. IMPLEMENT_ASN1_FUNCTIONS (TS_ACCURACY)
  69. ///
  70. /// The timestamp token info resulting from a successful timestamp request,
  71. /// as defined in RFC 3161.
  72. ///
  73. /// TSTInfo ::= SEQUENCE {
  74. /// version INTEGER { v1(1) },
  75. /// policy TSAPolicyId,
  76. /// messageImprint MessageImprint,
  77. /// -- MUST have the same value as the similar field in
  78. /// -- TimeStampReq
  79. /// serialNumber INTEGER,
  80. /// -- Time-Stamping users MUST be ready to accommodate integers
  81. /// -- up to 160 bits.
  82. /// genTime GeneralizedTime,
  83. /// accuracy Accuracy OPTIONAL,
  84. /// ordering BOOLEAN DEFAULT FALSE,
  85. /// nonce INTEGER OPTIONAL,
  86. /// -- MUST be present if the similar field was present
  87. /// -- in TimeStampReq. In that case it MUST have the same value.
  88. /// tsa [0] GeneralName OPTIONAL,
  89. /// extensions [1] IMPLICIT Extensions OPTIONAL }
  90. ///
  91. typedef struct {
  92. ASN1_INTEGER *Version;
  93. ASN1_OBJECT *Policy;
  94. TS_MESSAGE_IMPRINT *MessageImprint;
  95. ASN1_INTEGER *SerialNumber;
  96. ASN1_GENERALIZEDTIME *GenTime;
  97. TS_ACCURACY *Accuracy;
  98. ASN1_BOOLEAN Ordering;
  99. ASN1_INTEGER *Nonce;
  100. GENERAL_NAME *Tsa;
  101. STACK_OF(X509_EXTENSION) *Extensions;
  102. } TS_TST_INFO;
  103. //
  104. // ASN.1 Functions for TS_TST_INFO
  105. //
  106. DECLARE_ASN1_FUNCTIONS (TS_TST_INFO)
  107. ASN1_SEQUENCE (TS_TST_INFO) = {
  108. ASN1_SIMPLE (TS_TST_INFO, Version, ASN1_INTEGER),
  109. ASN1_SIMPLE (TS_TST_INFO, Policy, ASN1_OBJECT),
  110. ASN1_SIMPLE (TS_TST_INFO, MessageImprint, TS_MESSAGE_IMPRINT),
  111. ASN1_SIMPLE (TS_TST_INFO, SerialNumber, ASN1_INTEGER),
  112. ASN1_SIMPLE (TS_TST_INFO, GenTime, ASN1_GENERALIZEDTIME),
  113. ASN1_OPT (TS_TST_INFO, Accuracy, TS_ACCURACY),
  114. ASN1_OPT (TS_TST_INFO, Ordering, ASN1_FBOOLEAN),
  115. ASN1_OPT (TS_TST_INFO, Nonce, ASN1_INTEGER),
  116. ASN1_EXP_OPT(TS_TST_INFO, Tsa, GENERAL_NAME, 0),
  117. ASN1_IMP_SEQUENCE_OF_OPT (TS_TST_INFO, Extensions, X509_EXTENSION, 1)
  118. } ASN1_SEQUENCE_END (TS_TST_INFO)
  119. IMPLEMENT_ASN1_FUNCTIONS (TS_TST_INFO)
  120. /**
  121. Convert ASN.1 GeneralizedTime to EFI Time.
  122. @param[in] Asn1Time Pointer to the ASN.1 GeneralizedTime to be converted.
  123. @param[out] SigningTime Return the corresponding EFI Time.
  124. @retval TRUE The time conversion succeeds.
  125. @retval FALSE Invalid parameters.
  126. **/
  127. BOOLEAN
  128. EFIAPI
  129. ConvertAsn1TimeToEfiTime (
  130. IN ASN1_TIME *Asn1Time,
  131. OUT EFI_TIME *EfiTime
  132. )
  133. {
  134. CONST CHAR8 *Str;
  135. UINTN Index;
  136. if ((Asn1Time == NULL) || (EfiTime == NULL)) {
  137. return FALSE;
  138. }
  139. Str = (CONST CHAR8*)Asn1Time->data;
  140. SetMem (EfiTime, 0, sizeof (EFI_TIME));
  141. Index = 0;
  142. if (Asn1Time->type == V_ASN1_UTCTIME) { /* two digit year */
  143. EfiTime->Year = (Str[Index++] - '0') * 10;
  144. EfiTime->Year += (Str[Index++] - '0');
  145. if (EfiTime->Year < 70) {
  146. EfiTime->Year += 100;
  147. }
  148. } else if (Asn1Time->type == V_ASN1_GENERALIZEDTIME) { /* four digit year */
  149. EfiTime->Year = (Str[Index++] - '0') * 1000;
  150. EfiTime->Year += (Str[Index++] - '0') * 100;
  151. EfiTime->Year += (Str[Index++] - '0') * 10;
  152. EfiTime->Year += (Str[Index++] - '0');
  153. if ((EfiTime->Year < 1900) || (EfiTime->Year > 9999)) {
  154. return FALSE;
  155. }
  156. }
  157. EfiTime->Month = (Str[Index++] - '0') * 10;
  158. EfiTime->Month += (Str[Index++] - '0');
  159. if ((EfiTime->Month < 1) || (EfiTime->Month > 12)) {
  160. return FALSE;
  161. }
  162. EfiTime->Day = (Str[Index++] - '0') * 10;
  163. EfiTime->Day += (Str[Index++] - '0');
  164. if ((EfiTime->Day < 1) || (EfiTime->Day > 31)) {
  165. return FALSE;
  166. }
  167. EfiTime->Hour = (Str[Index++] - '0') * 10;
  168. EfiTime->Hour += (Str[Index++] - '0');
  169. if (EfiTime->Hour > 23) {
  170. return FALSE;
  171. }
  172. EfiTime->Minute = (Str[Index++] - '0') * 10;
  173. EfiTime->Minute += (Str[Index++] - '0');
  174. if (EfiTime->Minute > 59) {
  175. return FALSE;
  176. }
  177. EfiTime->Second = (Str[Index++] - '0') * 10;
  178. EfiTime->Second += (Str[Index++] - '0');
  179. if (EfiTime->Second > 59) {
  180. return FALSE;
  181. }
  182. /* Note: we did not adjust the time based on time zone information */
  183. return TRUE;
  184. }
  185. /**
  186. Check the validity of TimeStamp Token Information.
  187. @param[in] TstInfo Pointer to the TS_TST_INFO structure.
  188. @param[in] TimestampedData Pointer to the data to be time-stamped.
  189. @param[in] DataSize Size of timestamped data in bytes.
  190. @retval TRUE The TimeStamp Token Information is valid.
  191. @retval FALSE Invalid TimeStamp Token Information.
  192. **/
  193. BOOLEAN
  194. EFIAPI
  195. CheckTSTInfo (
  196. IN CONST TS_TST_INFO *TstInfo,
  197. IN CONST UINT8 *TimestampedData,
  198. IN UINTN DataSize
  199. )
  200. {
  201. BOOLEAN Status;
  202. TS_MESSAGE_IMPRINT *Imprint;
  203. X509_ALGOR *HashAlgo;
  204. CONST EVP_MD *Md;
  205. EVP_MD_CTX *MdCtx;
  206. UINTN MdSize;
  207. UINT8 *HashedMsg;
  208. //
  209. // Initialization
  210. //
  211. Status = FALSE;
  212. HashAlgo = NULL;
  213. HashedMsg = NULL;
  214. MdCtx = NULL;
  215. //
  216. // -- Check version number of Timestamp:
  217. // The version field (currently v1) describes the version of the time-stamp token.
  218. // Conforming time-stamping servers MUST be able to provide version 1 time-stamp tokens.
  219. //
  220. if ((ASN1_INTEGER_get (TstInfo->Version)) != 1) {
  221. return FALSE;
  222. }
  223. //
  224. // -- Check Policies
  225. // The policy field MUST indicate the TSA's policy under which the response was produced.
  226. //
  227. if (TstInfo->Policy == NULL) {
  228. /// NOTE: Need to check if the requested and returned policies.
  229. /// We have no information about the Requested TSA Policy.
  230. return FALSE;
  231. }
  232. //
  233. // -- Compute & Check Message Imprint
  234. //
  235. Imprint = TstInfo->MessageImprint;
  236. HashAlgo = X509_ALGOR_dup (Imprint->HashAlgorithm);
  237. Md = EVP_get_digestbyobj (HashAlgo->algorithm);
  238. if (Md == NULL) {
  239. goto _Exit;
  240. }
  241. MdSize = EVP_MD_size (Md);
  242. HashedMsg = AllocateZeroPool (MdSize);
  243. if (HashedMsg == NULL) {
  244. goto _Exit;
  245. }
  246. MdCtx = EVP_MD_CTX_new ();
  247. if (MdCtx == NULL) {
  248. goto _Exit;
  249. }
  250. if ((EVP_DigestInit_ex (MdCtx, Md, NULL) != 1) ||
  251. (EVP_DigestUpdate (MdCtx, TimestampedData, DataSize) != 1) ||
  252. (EVP_DigestFinal (MdCtx, HashedMsg, NULL) != 1)) {
  253. goto _Exit;
  254. }
  255. if ((MdSize == (UINTN)ASN1_STRING_length (Imprint->HashedMessage)) &&
  256. (CompareMem (HashedMsg, ASN1_STRING_get0_data (Imprint->HashedMessage), MdSize) != 0)) {
  257. goto _Exit;
  258. }
  259. //
  260. // -- Check Nonces
  261. //
  262. if (TstInfo->Nonce != NULL) {
  263. //
  264. // Nonces is optional, No error if no nonce is returned;
  265. //
  266. }
  267. //
  268. // -- Check if the TSA name and signer certificate is matched.
  269. //
  270. if (TstInfo->Tsa != NULL) {
  271. //
  272. // Ignored the optional Tsa field checking.
  273. //
  274. }
  275. Status = TRUE;
  276. _Exit:
  277. X509_ALGOR_free (HashAlgo);
  278. EVP_MD_CTX_free (MdCtx);
  279. if (HashedMsg != NULL) {
  280. FreePool (HashedMsg);
  281. }
  282. return Status;
  283. }
  284. /**
  285. Verifies the validity of a TimeStamp Token as described in RFC 3161 ("Internet
  286. X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)").
  287. If TSToken is NULL, then return FALSE.
  288. If TimestampedData is NULL, then return FALSE.
  289. @param[in] TSToken Pointer to the RFC3161 TimeStamp Token, which is generated
  290. by a TSA and located in the software publisher's SignerInfo
  291. structure.
  292. @param[in] TokenSize Size of the TimeStamp Token in bytes.
  293. @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER.
  294. @param[in] CertSize Size of the trusted TSA certificate in bytes.
  295. @param[in] TimestampedData Pointer to the data to be time-stamped.
  296. @param[in] DataSize Size of timestamped data in bytes.
  297. @param[out] SigningTime Return the time of timestamp generation time if the timestamp
  298. signature is valid.
  299. @retval TRUE The specified timestamp token is valid.
  300. @retval FALSE Invalid timestamp token.
  301. **/
  302. BOOLEAN
  303. EFIAPI
  304. TimestampTokenVerify (
  305. IN CONST UINT8 *TSToken,
  306. IN UINTN TokenSize,
  307. IN CONST UINT8 *TsaCert,
  308. IN UINTN CertSize,
  309. IN CONST UINT8 *TimestampedData,
  310. IN UINTN DataSize,
  311. OUT EFI_TIME *SigningTime
  312. )
  313. {
  314. BOOLEAN Status;
  315. CONST UINT8 *TokenTemp;
  316. PKCS7 *Pkcs7;
  317. X509 *Cert;
  318. CONST UINT8 *CertTemp;
  319. X509_STORE *CertStore;
  320. BIO *OutBio;
  321. UINT8 *TstData;
  322. UINTN TstSize;
  323. CONST UINT8 *TstTemp;
  324. TS_TST_INFO *TstInfo;
  325. Status = FALSE;
  326. //
  327. // Check input parameters
  328. //
  329. if ((TSToken == NULL) || (TsaCert == NULL) || (TimestampedData == NULL) ||
  330. (TokenSize > INT_MAX) || (CertSize > INT_MAX) || (DataSize > INT_MAX)) {
  331. return FALSE;
  332. }
  333. //
  334. // Initializations
  335. //
  336. if (SigningTime != NULL) {
  337. SetMem (SigningTime, sizeof (EFI_TIME), 0);
  338. }
  339. Pkcs7 = NULL;
  340. Cert = NULL;
  341. CertStore = NULL;
  342. OutBio = NULL;
  343. TstData = NULL;
  344. TstInfo = NULL;
  345. //
  346. // TimeStamp Token should contain one valid DER-encoded ASN.1 PKCS#7 structure.
  347. //
  348. TokenTemp = TSToken;
  349. Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &TokenTemp, (int) TokenSize);
  350. if (Pkcs7 == NULL) {
  351. goto _Exit;
  352. }
  353. //
  354. // The timestamp signature (TSA's response) will be one PKCS#7 signed data.
  355. //
  356. if (!PKCS7_type_is_signed (Pkcs7)) {
  357. goto _Exit;
  358. }
  359. //
  360. // Read the trusted TSA certificate (DER-encoded), and Construct X509 Certificate.
  361. //
  362. CertTemp = TsaCert;
  363. Cert = d2i_X509 (NULL, &CertTemp, (long) CertSize);
  364. if (Cert == NULL) {
  365. goto _Exit;
  366. }
  367. //
  368. // Setup X509 Store for trusted certificate.
  369. //
  370. CertStore = X509_STORE_new ();
  371. if ((CertStore == NULL) || !(X509_STORE_add_cert (CertStore, Cert))) {
  372. goto _Exit;
  373. }
  374. //
  375. // Allow partial certificate chains, terminated by a non-self-signed but
  376. // still trusted intermediate certificate. Also disable time checks.
  377. //
  378. X509_STORE_set_flags (CertStore,
  379. X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME);
  380. X509_STORE_set_purpose (CertStore, X509_PURPOSE_ANY);
  381. //
  382. // Verifies the PKCS#7 signedData structure, and output the signed contents.
  383. //
  384. OutBio = BIO_new (BIO_s_mem ());
  385. if (OutBio == NULL) {
  386. goto _Exit;
  387. }
  388. if (!PKCS7_verify (Pkcs7, NULL, CertStore, NULL, OutBio, PKCS7_BINARY)) {
  389. goto _Exit;
  390. }
  391. //
  392. // Read the signed contents detached in timestamp signature.
  393. //
  394. TstData = AllocateZeroPool (2048);
  395. if (TstData == NULL) {
  396. goto _Exit;
  397. }
  398. TstSize = BIO_read (OutBio, (void *) TstData, 2048);
  399. //
  400. // Construct TS_TST_INFO structure from the signed contents.
  401. //
  402. TstTemp = TstData;
  403. TstInfo = d2i_TS_TST_INFO (NULL, (const unsigned char **) &TstTemp,
  404. (int)TstSize);
  405. if (TstInfo == NULL) {
  406. goto _Exit;
  407. }
  408. //
  409. // Check TS_TST_INFO structure.
  410. //
  411. Status = CheckTSTInfo (TstInfo, TimestampedData, DataSize);
  412. if (!Status) {
  413. goto _Exit;
  414. }
  415. //
  416. // Retrieve the signing time from TS_TST_INFO structure.
  417. //
  418. if (SigningTime != NULL) {
  419. SetMem (SigningTime, sizeof (EFI_TIME), 0);
  420. Status = ConvertAsn1TimeToEfiTime (TstInfo->GenTime, SigningTime);
  421. }
  422. _Exit:
  423. //
  424. // Release Resources
  425. //
  426. PKCS7_free (Pkcs7);
  427. X509_free (Cert);
  428. X509_STORE_free (CertStore);
  429. BIO_free (OutBio);
  430. TS_TST_INFO_free (TstInfo);
  431. if (TstData != NULL) {
  432. FreePool (TstData);
  433. }
  434. return Status;
  435. }
  436. /**
  437. Verifies the validity of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode
  438. signature.
  439. If AuthData is NULL, then return FALSE.
  440. @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed
  441. PE/COFF image to be verified.
  442. @param[in] DataSize Size of the Authenticode Signature in bytes.
  443. @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER, which
  444. is used for TSA certificate chain verification.
  445. @param[in] CertSize Size of the trusted certificate in bytes.
  446. @param[out] SigningTime Return the time of timestamp generation time if the timestamp
  447. signature is valid.
  448. @retval TRUE The specified Authenticode includes a valid RFC3161 Timestamp CounterSignature.
  449. @retval FALSE No valid RFC3161 Timestamp CounterSignature in the specified Authenticode data.
  450. **/
  451. BOOLEAN
  452. EFIAPI
  453. ImageTimestampVerify (
  454. IN CONST UINT8 *AuthData,
  455. IN UINTN DataSize,
  456. IN CONST UINT8 *TsaCert,
  457. IN UINTN CertSize,
  458. OUT EFI_TIME *SigningTime
  459. )
  460. {
  461. BOOLEAN Status;
  462. PKCS7 *Pkcs7;
  463. CONST UINT8 *Temp;
  464. STACK_OF(PKCS7_SIGNER_INFO) *SignerInfos;
  465. PKCS7_SIGNER_INFO *SignInfo;
  466. UINTN Index;
  467. STACK_OF(X509_ATTRIBUTE) *Sk;
  468. X509_ATTRIBUTE *Xa;
  469. ASN1_OBJECT *XaObj;
  470. ASN1_TYPE *Asn1Type;
  471. ASN1_OCTET_STRING *EncDigest;
  472. UINT8 *TSToken;
  473. UINTN TokenSize;
  474. //
  475. // Input Parameters Checking.
  476. //
  477. if ((AuthData == NULL) || (TsaCert == NULL)) {
  478. return FALSE;
  479. }
  480. if ((DataSize > INT_MAX) || (CertSize > INT_MAX)) {
  481. return FALSE;
  482. }
  483. //
  484. // Register & Initialize necessary digest algorithms for PKCS#7 Handling.
  485. //
  486. if ((EVP_add_digest (EVP_md5 ()) == 0) || (EVP_add_digest (EVP_sha1 ()) == 0) ||
  487. (EVP_add_digest (EVP_sha256 ()) == 0) || (EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA)) == 0) {
  488. return FALSE;
  489. }
  490. //
  491. // Initialization.
  492. //
  493. Status = FALSE;
  494. Pkcs7 = NULL;
  495. SignInfo = NULL;
  496. //
  497. // Decode ASN.1-encoded Authenticode data into PKCS7 structure.
  498. //
  499. Temp = AuthData;
  500. Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) DataSize);
  501. if (Pkcs7 == NULL) {
  502. goto _Exit;
  503. }
  504. //
  505. // Check if there is one and only one signer.
  506. //
  507. SignerInfos = PKCS7_get_signer_info (Pkcs7);
  508. if (!SignerInfos || (sk_PKCS7_SIGNER_INFO_num (SignerInfos) != 1)) {
  509. goto _Exit;
  510. }
  511. //
  512. // Locate the TimeStamp CounterSignature.
  513. //
  514. SignInfo = sk_PKCS7_SIGNER_INFO_value (SignerInfos, 0);
  515. if (SignInfo == NULL) {
  516. goto _Exit;
  517. }
  518. //
  519. // Locate Message Digest which will be the data to be time-stamped.
  520. //
  521. EncDigest = SignInfo->enc_digest;
  522. if (EncDigest == NULL) {
  523. goto _Exit;
  524. }
  525. //
  526. // The RFC3161 timestamp counterSignature is contained in unauthenticatedAttributes field
  527. // of SignerInfo.
  528. //
  529. Sk = SignInfo->unauth_attr;
  530. if (Sk == NULL) { // No timestamp counterSignature.
  531. goto _Exit;
  532. }
  533. Asn1Type = NULL;
  534. for (Index = 0; Index < (UINTN) sk_X509_ATTRIBUTE_num (Sk); Index++) {
  535. //
  536. // Search valid RFC3161 timestamp counterSignature based on OBJID.
  537. //
  538. Xa = sk_X509_ATTRIBUTE_value (Sk, (int)Index);
  539. if (Xa == NULL) {
  540. continue;
  541. }
  542. XaObj = X509_ATTRIBUTE_get0_object(Xa);
  543. if (XaObj == NULL) {
  544. continue;
  545. }
  546. if ((OBJ_length(XaObj) != sizeof (mSpcRFC3161OidValue)) ||
  547. (CompareMem (OBJ_get0_data(XaObj), mSpcRFC3161OidValue, sizeof (mSpcRFC3161OidValue)) != 0)) {
  548. continue;
  549. }
  550. Asn1Type = X509_ATTRIBUTE_get0_type(Xa, 0);
  551. }
  552. if (Asn1Type == NULL) {
  553. Status = FALSE;
  554. goto _Exit;
  555. }
  556. TSToken = Asn1Type->value.octet_string->data;
  557. TokenSize = Asn1Type->value.octet_string->length;
  558. //
  559. // TimeStamp counterSignature (Token) verification.
  560. //
  561. Status = TimestampTokenVerify (
  562. TSToken,
  563. TokenSize,
  564. TsaCert,
  565. CertSize,
  566. EncDigest->data,
  567. EncDigest->length,
  568. SigningTime
  569. );
  570. _Exit:
  571. //
  572. // Release Resources
  573. //
  574. PKCS7_free (Pkcs7);
  575. return Status;
  576. }