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