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