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