]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c
CryptoPkg/BaseCryptLib: Add missing OpenSSL includes
[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 - 2015, 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 CONST UINT8 *CertTemp;
445 X509_STORE *CertStore;
446 BIO *OutBio;
447 UINT8 *TstData;
448 UINTN TstSize;
449 CONST UINT8 *TstTemp;
450 TS_TST_INFO *TstInfo;
451
452 Status = FALSE;
453
454 //
455 // Check input parameters
456 //
457 if ((TSToken == NULL) || (TsaCert == NULL) || (TimestampedData == NULL) ||
458 (TokenSize > INT_MAX) || (CertSize > INT_MAX) || (DataSize > INT_MAX)) {
459 return FALSE;
460 }
461
462 //
463 // Initializations
464 //
465 if (SigningTime != NULL) {
466 SetMem (SigningTime, sizeof (EFI_TIME), 0);
467 }
468 Pkcs7 = NULL;
469 Cert = NULL;
470 CertStore = NULL;
471 OutBio = NULL;
472 TstData = NULL;
473 TstInfo = NULL;
474
475 //
476 // TimeStamp Token should contain one valid DER-encoded ASN.1 PKCS#7 structure.
477 //
478 TokenTemp = TSToken;
479 Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &TokenTemp, (int) TokenSize);
480 if (Pkcs7 == NULL) {
481 goto _Exit;
482 }
483
484 //
485 // The timestamp signature (TSA's response) will be one PKCS#7 signed data.
486 //
487 if (!PKCS7_type_is_signed (Pkcs7)) {
488 goto _Exit;
489 }
490
491 //
492 // Read the trusted TSA certificate (DER-encoded), and Construct X509 Certificate.
493 //
494 CertTemp = TsaCert;
495 Cert = d2i_X509 (NULL, &CertTemp, (long) CertSize);
496 if (Cert == NULL) {
497 goto _Exit;
498 }
499
500 //
501 // Setup X509 Store for trusted certificate.
502 //
503 CertStore = X509_STORE_new ();
504 if ((CertStore == NULL) || !(X509_STORE_add_cert (CertStore, Cert))) {
505 goto _Exit;
506 }
507
508 //
509 // Register customized X509 verification callback function to support
510 // trusted intermediate TSA certificate anchor.
511 //
512 CertStore->verify_cb = TSVerifyCallback;
513
514 X509_STORE_set_purpose (CertStore, X509_PURPOSE_ANY);
515
516 //
517 // Verifies the PKCS#7 signedData structure, and output the signed contents.
518 //
519 OutBio = BIO_new (BIO_s_mem ());
520 if (OutBio == NULL) {
521 goto _Exit;
522 }
523 if (!PKCS7_verify (Pkcs7, NULL, CertStore, NULL, OutBio, PKCS7_BINARY)) {
524 goto _Exit;
525 }
526
527 //
528 // Read the signed contents detached in timestamp signature.
529 //
530 TstData = AllocateZeroPool (2048);
531 if (TstData == NULL) {
532 goto _Exit;
533 }
534 TstSize = BIO_read (OutBio, (void *) TstData, 2048);
535
536 //
537 // Construct TS_TST_INFO structure from the signed contents.
538 //
539 TstTemp = TstData;
540 TstInfo = d2i_TS_TST_INFO (NULL, (const unsigned char **) &TstTemp,
541 (int)TstSize);
542 if (TstInfo == NULL) {
543 goto _Exit;
544 }
545
546 //
547 // Check TS_TST_INFO structure.
548 //
549 Status = CheckTSTInfo (TstInfo, TimestampedData, DataSize);
550 if (!Status) {
551 goto _Exit;
552 }
553
554 //
555 // Retrieve the signing time from TS_TST_INFO structure.
556 //
557 if (SigningTime != NULL) {
558 SetMem (SigningTime, sizeof (EFI_TIME), 0);
559 Status = ConvertAsn1TimeToEfiTime (TstInfo->GenTime, SigningTime);
560 }
561
562 _Exit:
563 //
564 // Release Resources
565 //
566 PKCS7_free (Pkcs7);
567 X509_free (Cert);
568 X509_STORE_free (CertStore);
569 BIO_free (OutBio);
570 TS_TST_INFO_free (TstInfo);
571
572 if (TstData != NULL) {
573 FreePool (TstData);
574 }
575
576 return Status;
577 }
578
579 /**
580 Verifies the validility of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode
581 signature.
582
583 If AuthData is NULL, then return FALSE.
584
585 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed
586 PE/COFF image to be verified.
587 @param[in] DataSize Size of the Authenticode Signature in bytes.
588 @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER, which
589 is used for TSA certificate chain verification.
590 @param[in] CertSize Size of the trusted certificate in bytes.
591 @param[out] SigningTime Return the time of timestamp generation time if the timestamp
592 signature is valid.
593
594 @retval TRUE The specified Authenticode includes a valid RFC3161 Timestamp CounterSignature.
595 @retval FALSE No valid RFC3161 Timestamp CounterSignature in the specified Authenticode data.
596
597 **/
598 BOOLEAN
599 EFIAPI
600 ImageTimestampVerify (
601 IN CONST UINT8 *AuthData,
602 IN UINTN DataSize,
603 IN CONST UINT8 *TsaCert,
604 IN UINTN CertSize,
605 OUT EFI_TIME *SigningTime
606 )
607 {
608 BOOLEAN Status;
609 PKCS7 *Pkcs7;
610 CONST UINT8 *Temp;
611 STACK_OF(PKCS7_SIGNER_INFO) *SignerInfos;
612 PKCS7_SIGNER_INFO *SignInfo;
613 UINTN Index;
614 STACK_OF(X509_ATTRIBUTE) *Sk;
615 X509_ATTRIBUTE *Xa;
616 ASN1_TYPE *Asn1Type;
617 ASN1_OCTET_STRING *EncDigest;
618 UINT8 *TSToken;
619 UINTN TokenSize;
620
621 //
622 // Input Parameters Checking.
623 //
624 if ((AuthData == NULL) || (TsaCert == NULL)) {
625 return FALSE;
626 }
627
628 if ((DataSize > INT_MAX) || (CertSize > INT_MAX)) {
629 return FALSE;
630 }
631
632 //
633 // Register & Initialize necessary digest algorithms for PKCS#7 Handling.
634 //
635 if ((EVP_add_digest (EVP_md5 ()) == 0) || (EVP_add_digest (EVP_sha1 ()) == 0) ||
636 (EVP_add_digest (EVP_sha256 ()) == 0) || (EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA)) == 0) {
637 return FALSE;
638 }
639
640 //
641 // Initialization.
642 //
643 Status = FALSE;
644 Pkcs7 = NULL;
645 SignInfo = NULL;
646
647 //
648 // Decode ASN.1-encoded Authenticode data into PKCS7 structure.
649 //
650 Temp = AuthData;
651 Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) DataSize);
652 if (Pkcs7 == NULL) {
653 goto _Exit;
654 }
655
656 //
657 // Check if there is one and only one signer.
658 //
659 SignerInfos = PKCS7_get_signer_info (Pkcs7);
660 if (!SignerInfos || (sk_PKCS7_SIGNER_INFO_num (SignerInfos) != 1)) {
661 goto _Exit;
662 }
663
664 //
665 // Locate the TimeStamp CounterSignature.
666 //
667 SignInfo = sk_PKCS7_SIGNER_INFO_value (SignerInfos, 0);
668 if (SignInfo == NULL) {
669 goto _Exit;
670 }
671
672 //
673 // Locate Message Digest which will be the data to be time-stamped.
674 //
675 EncDigest = SignInfo->enc_digest;
676 if (EncDigest == NULL) {
677 goto _Exit;
678 }
679
680 //
681 // The RFC3161 timestamp counterSignature is contained in unauthenticatedAttributes field
682 // of SignerInfo.
683 //
684 Sk = SignInfo->unauth_attr;
685 if (Sk == NULL) { // No timestamp counterSignature.
686 goto _Exit;
687 }
688
689 Asn1Type = NULL;
690 for (Index = 0; Index < (UINTN) sk_X509_ATTRIBUTE_num (Sk); Index++) {
691 //
692 // Search valid RFC3161 timestamp counterSignature based on OBJID.
693 //
694 Xa = sk_X509_ATTRIBUTE_value (Sk, (int)Index);
695 if ((Xa->object->length != sizeof (mSpcRFC3161OidValue)) ||
696 (CompareMem (Xa->object->data, mSpcRFC3161OidValue, sizeof (mSpcRFC3161OidValue)) != 0)) {
697 continue;
698 }
699 Asn1Type = sk_ASN1_TYPE_value (Xa->value.set, 0);
700 }
701
702 if (Asn1Type == NULL) {
703 Status = FALSE;
704 goto _Exit;
705 }
706 TSToken = Asn1Type->value.octet_string->data;
707 TokenSize = Asn1Type->value.octet_string->length;
708
709 //
710 // TimeStamp counterSignature (Token) verification.
711 //
712 Status = TimestampTokenVerify (
713 TSToken,
714 TokenSize,
715 TsaCert,
716 CertSize,
717 EncDigest->data,
718 EncDigest->length,
719 SigningTime
720 );
721
722 _Exit:
723 //
724 // Release Resources
725 //
726 PKCS7_free (Pkcs7);
727
728 return Status;
729 }