]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c
CryptoPkg: Apply uncrustify changes
[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
7c342378 24UINT8 mSpcRFC3161OidValue[] = {\r
2ac68e8b 25 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x03, 0x03, 0x01\r
7c342378 26};\r
2ac68e8b
QL
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
7c342378
MK
39 X509_ALGOR *HashAlgorithm;\r
40 ASN1_OCTET_STRING *HashedMessage;\r
2ac68e8b
QL
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
7c342378
MK
63 ASN1_INTEGER *Seconds;\r
64 ASN1_INTEGER *Millis;\r
65 ASN1_INTEGER *Micros;\r
2ac68e8b
QL
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
7c342378 73 ASN1_OPT (TS_ACCURACY, Seconds, ASN1_INTEGER),\r
2ac68e8b
QL
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
7c342378
MK
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
2ac68e8b
QL
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
7c342378
MK
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
2ac68e8b
QL
129} ASN1_SEQUENCE_END (TS_TST_INFO)\r
130IMPLEMENT_ASN1_FUNCTIONS (TS_TST_INFO)\r
131\r
2ac68e8b
QL
132/**\r
133 Convert ASN.1 GeneralizedTime to EFI Time.\r
134\r
135 @param[in] Asn1Time Pointer to the ASN.1 GeneralizedTime to be converted.\r
136 @param[out] SigningTime Return the corresponding EFI Time.\r
137\r
2a784a2c 138 @retval TRUE The time conversion succeeds.\r
2ac68e8b
QL
139 @retval FALSE Invalid parameters.\r
140\r
141**/\r
142BOOLEAN\r
143EFIAPI\r
144ConvertAsn1TimeToEfiTime (\r
145 IN ASN1_TIME *Asn1Time,\r
146 OUT EFI_TIME *EfiTime\r
147 )\r
148{\r
149 CONST CHAR8 *Str;\r
150 UINTN Index;\r
151\r
152 if ((Asn1Time == NULL) || (EfiTime == NULL)) {\r
153 return FALSE;\r
154 }\r
155\r
7c342378 156 Str = (CONST CHAR8 *)Asn1Time->data;\r
7b4a99be 157 SetMem (EfiTime, sizeof (EFI_TIME), 0);\r
2ac68e8b
QL
158\r
159 Index = 0;\r
7c342378
MK
160 if (Asn1Time->type == V_ASN1_UTCTIME) {\r
161 /* two digit year */\r
2ac68e8b
QL
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
7c342378
MK
167 } else if (Asn1Time->type == V_ASN1_GENERALIZEDTIME) {\r
168 /* four digit year */\r
2ac68e8b
QL
169 EfiTime->Year = (Str[Index++] - '0') * 1000;\r
170 EfiTime->Year += (Str[Index++] - '0') * 100;\r
171 EfiTime->Year += (Str[Index++] - '0') * 10;\r
172 EfiTime->Year += (Str[Index++] - '0');\r
173 if ((EfiTime->Year < 1900) || (EfiTime->Year > 9999)) {\r
174 return FALSE;\r
175 }\r
176 }\r
177\r
7c342378
MK
178 EfiTime->Month = (Str[Index++] - '0') * 10;\r
179 EfiTime->Month += (Str[Index++] - '0');\r
2ac68e8b
QL
180 if ((EfiTime->Month < 1) || (EfiTime->Month > 12)) {\r
181 return FALSE;\r
182 }\r
183\r
7c342378
MK
184 EfiTime->Day = (Str[Index++] - '0') * 10;\r
185 EfiTime->Day += (Str[Index++] - '0');\r
2ac68e8b
QL
186 if ((EfiTime->Day < 1) || (EfiTime->Day > 31)) {\r
187 return FALSE;\r
188 }\r
189\r
7c342378
MK
190 EfiTime->Hour = (Str[Index++] - '0') * 10;\r
191 EfiTime->Hour += (Str[Index++] - '0');\r
2ac68e8b
QL
192 if (EfiTime->Hour > 23) {\r
193 return FALSE;\r
194 }\r
195\r
196 EfiTime->Minute = (Str[Index++] - '0') * 10;\r
197 EfiTime->Minute += (Str[Index++] - '0');\r
198 if (EfiTime->Minute > 59) {\r
199 return FALSE;\r
200 }\r
201\r
202 EfiTime->Second = (Str[Index++] - '0') * 10;\r
203 EfiTime->Second += (Str[Index++] - '0');\r
204 if (EfiTime->Second > 59) {\r
205 return FALSE;\r
206 }\r
207\r
208 /* Note: we did not adjust the time based on time zone information */\r
209\r
210 return TRUE;\r
211}\r
212\r
213/**\r
214\r
215 Check the validity of TimeStamp Token Information.\r
216\r
217 @param[in] TstInfo Pointer to the TS_TST_INFO structure.\r
218 @param[in] TimestampedData Pointer to the data to be time-stamped.\r
219 @param[in] DataSize Size of timestamped data in bytes.\r
220\r
221 @retval TRUE The TimeStamp Token Information is valid.\r
222 @retval FALSE Invalid TimeStamp Token Information.\r
223\r
224**/\r
225BOOLEAN\r
226EFIAPI\r
227CheckTSTInfo (\r
228 IN CONST TS_TST_INFO *TstInfo,\r
229 IN CONST UINT8 *TimestampedData,\r
230 IN UINTN DataSize\r
231 )\r
232{\r
233 BOOLEAN Status;\r
234 TS_MESSAGE_IMPRINT *Imprint;\r
235 X509_ALGOR *HashAlgo;\r
236 CONST EVP_MD *Md;\r
f56b11d2 237 EVP_MD_CTX *MdCtx;\r
2ac68e8b
QL
238 UINTN MdSize;\r
239 UINT8 *HashedMsg;\r
240\r
241 //\r
242 // Initialization\r
243 //\r
244 Status = FALSE;\r
245 HashAlgo = NULL;\r
246 HashedMsg = NULL;\r
f56b11d2 247 MdCtx = NULL;\r
2ac68e8b
QL
248\r
249 //\r
250 // -- Check version number of Timestamp:\r
251 // The version field (currently v1) describes the version of the time-stamp token.\r
252 // Conforming time-stamping servers MUST be able to provide version 1 time-stamp tokens.\r
253 //\r
254 if ((ASN1_INTEGER_get (TstInfo->Version)) != 1) {\r
255 return FALSE;\r
256 }\r
257\r
258 //\r
259 // -- Check Policies\r
260 // The policy field MUST indicate the TSA's policy under which the response was produced.\r
261 //\r
262 if (TstInfo->Policy == NULL) {\r
263 /// NOTE: Need to check if the requested and returned policies.\r
264 /// We have no information about the Requested TSA Policy.\r
265 return FALSE;\r
266 }\r
267\r
268 //\r
269 // -- Compute & Check Message Imprint\r
270 //\r
271 Imprint = TstInfo->MessageImprint;\r
272 HashAlgo = X509_ALGOR_dup (Imprint->HashAlgorithm);\r
273\r
274 Md = EVP_get_digestbyobj (HashAlgo->algorithm);\r
275 if (Md == NULL) {\r
276 goto _Exit;\r
277 }\r
278\r
7c342378 279 MdSize = EVP_MD_size (Md);\r
2ac68e8b
QL
280 HashedMsg = AllocateZeroPool (MdSize);\r
281 if (HashedMsg == NULL) {\r
282 goto _Exit;\r
283 }\r
7c342378 284\r
f56b11d2
QL
285 MdCtx = EVP_MD_CTX_new ();\r
286 if (MdCtx == NULL) {\r
287 goto _Exit;\r
288 }\r
7c342378 289\r
f56b11d2
QL
290 if ((EVP_DigestInit_ex (MdCtx, Md, NULL) != 1) ||\r
291 (EVP_DigestUpdate (MdCtx, TimestampedData, DataSize) != 1) ||\r
7c342378
MK
292 (EVP_DigestFinal (MdCtx, HashedMsg, NULL) != 1))\r
293 {\r
f56b11d2
QL
294 goto _Exit;\r
295 }\r
7c342378 296\r
2ac68e8b 297 if ((MdSize == (UINTN)ASN1_STRING_length (Imprint->HashedMessage)) &&\r
7c342378
MK
298 (CompareMem (HashedMsg, ASN1_STRING_get0_data (Imprint->HashedMessage), MdSize) != 0))\r
299 {\r
2ac68e8b
QL
300 goto _Exit;\r
301 }\r
302\r
303 //\r
304 // -- Check Nonces\r
305 //\r
306 if (TstInfo->Nonce != NULL) {\r
307 //\r
308 // Nonces is optional, No error if no nonce is returned;\r
309 //\r
310 }\r
311\r
312 //\r
313 // -- Check if the TSA name and signer certificate is matched.\r
314 //\r
315 if (TstInfo->Tsa != NULL) {\r
316 //\r
317 // Ignored the optional Tsa field checking.\r
318 //\r
319 }\r
320\r
321 Status = TRUE;\r
322\r
323_Exit:\r
324 X509_ALGOR_free (HashAlgo);\r
f56b11d2 325 EVP_MD_CTX_free (MdCtx);\r
2ac68e8b
QL
326 if (HashedMsg != NULL) {\r
327 FreePool (HashedMsg);\r
328 }\r
329\r
330 return Status;\r
331}\r
332\r
333/**\r
2998af86 334 Verifies the validity of a TimeStamp Token as described in RFC 3161 ("Internet\r
2ac68e8b
QL
335 X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)").\r
336\r
337 If TSToken is NULL, then return FALSE.\r
338 If TimestampedData is NULL, then return FALSE.\r
339\r
340 @param[in] TSToken Pointer to the RFC3161 TimeStamp Token, which is generated\r
341 by a TSA and located in the software publisher's SignerInfo\r
342 structure.\r
343 @param[in] TokenSize Size of the TimeStamp Token in bytes.\r
344 @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER.\r
345 @param[in] CertSize Size of the trusted TSA certificate in bytes.\r
346 @param[in] TimestampedData Pointer to the data to be time-stamped.\r
347 @param[in] DataSize Size of timestamped data in bytes.\r
348 @param[out] SigningTime Return the time of timestamp generation time if the timestamp\r
349 signature is valid.\r
350\r
351 @retval TRUE The specified timestamp token is valid.\r
352 @retval FALSE Invalid timestamp token.\r
353\r
354**/\r
355BOOLEAN\r
356EFIAPI\r
357TimestampTokenVerify (\r
358 IN CONST UINT8 *TSToken,\r
359 IN UINTN TokenSize,\r
360 IN CONST UINT8 *TsaCert,\r
361 IN UINTN CertSize,\r
362 IN CONST UINT8 *TimestampedData,\r
363 IN UINTN DataSize,\r
364 OUT EFI_TIME *SigningTime\r
365 )\r
366{\r
367 BOOLEAN Status;\r
368 CONST UINT8 *TokenTemp;\r
369 PKCS7 *Pkcs7;\r
370 X509 *Cert;\r
1463ce18 371 CONST UINT8 *CertTemp;\r
2ac68e8b
QL
372 X509_STORE *CertStore;\r
373 BIO *OutBio;\r
374 UINT8 *TstData;\r
375 UINTN TstSize;\r
1463ce18 376 CONST UINT8 *TstTemp;\r
2ac68e8b
QL
377 TS_TST_INFO *TstInfo;\r
378\r
379 Status = FALSE;\r
380\r
381 //\r
382 // Check input parameters\r
383 //\r
384 if ((TSToken == NULL) || (TsaCert == NULL) || (TimestampedData == NULL) ||\r
7c342378
MK
385 (TokenSize > INT_MAX) || (CertSize > INT_MAX) || (DataSize > INT_MAX))\r
386 {\r
2ac68e8b
QL
387 return FALSE;\r
388 }\r
389\r
390 //\r
391 // Initializations\r
392 //\r
393 if (SigningTime != NULL) {\r
394 SetMem (SigningTime, sizeof (EFI_TIME), 0);\r
395 }\r
7c342378 396\r
2ac68e8b
QL
397 Pkcs7 = NULL;\r
398 Cert = NULL;\r
399 CertStore = NULL;\r
400 OutBio = NULL;\r
401 TstData = NULL;\r
402 TstInfo = NULL;\r
403\r
404 //\r
405 // TimeStamp Token should contain one valid DER-encoded ASN.1 PKCS#7 structure.\r
406 //\r
407 TokenTemp = TSToken;\r
7c342378 408 Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&TokenTemp, (int)TokenSize);\r
2ac68e8b
QL
409 if (Pkcs7 == NULL) {\r
410 goto _Exit;\r
411 }\r
412\r
413 //\r
414 // The timestamp signature (TSA's response) will be one PKCS#7 signed data.\r
415 //\r
416 if (!PKCS7_type_is_signed (Pkcs7)) {\r
417 goto _Exit;\r
418 }\r
419\r
420 //\r
421 // Read the trusted TSA certificate (DER-encoded), and Construct X509 Certificate.\r
422 //\r
1463ce18 423 CertTemp = TsaCert;\r
7c342378 424 Cert = d2i_X509 (NULL, &CertTemp, (long)CertSize);\r
2ac68e8b
QL
425 if (Cert == NULL) {\r
426 goto _Exit;\r
427 }\r
428\r
429 //\r
430 // Setup X509 Store for trusted certificate.\r
431 //\r
432 CertStore = X509_STORE_new ();\r
433 if ((CertStore == NULL) || !(X509_STORE_add_cert (CertStore, Cert))) {\r
434 goto _Exit;\r
435 }\r
436\r
437 //\r
68547181 438 // Allow partial certificate chains, terminated by a non-self-signed but\r
de0408be 439 // still trusted intermediate certificate. Also disable time checks.\r
2ac68e8b 440 //\r
7c342378
MK
441 X509_STORE_set_flags (\r
442 CertStore,\r
443 X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME\r
444 );\r
2ac68e8b
QL
445\r
446 X509_STORE_set_purpose (CertStore, X509_PURPOSE_ANY);\r
447\r
448 //\r
449 // Verifies the PKCS#7 signedData structure, and output the signed contents.\r
450 //\r
451 OutBio = BIO_new (BIO_s_mem ());\r
452 if (OutBio == NULL) {\r
453 goto _Exit;\r
454 }\r
7c342378 455\r
2ac68e8b
QL
456 if (!PKCS7_verify (Pkcs7, NULL, CertStore, NULL, OutBio, PKCS7_BINARY)) {\r
457 goto _Exit;\r
458 }\r
459\r
460 //\r
461 // Read the signed contents detached in timestamp signature.\r
462 //\r
463 TstData = AllocateZeroPool (2048);\r
464 if (TstData == NULL) {\r
465 goto _Exit;\r
466 }\r
7c342378
MK
467\r
468 TstSize = BIO_read (OutBio, (void *)TstData, 2048);\r
2ac68e8b
QL
469\r
470 //\r
471 // Construct TS_TST_INFO structure from the signed contents.\r
472 //\r
473 TstTemp = TstData;\r
7c342378
MK
474 TstInfo = d2i_TS_TST_INFO (\r
475 NULL,\r
476 (const unsigned char **)&TstTemp,\r
477 (int)TstSize\r
478 );\r
2ac68e8b
QL
479 if (TstInfo == NULL) {\r
480 goto _Exit;\r
481 }\r
482\r
483 //\r
484 // Check TS_TST_INFO structure.\r
485 //\r
486 Status = CheckTSTInfo (TstInfo, TimestampedData, DataSize);\r
487 if (!Status) {\r
488 goto _Exit;\r
489 }\r
490\r
491 //\r
492 // Retrieve the signing time from TS_TST_INFO structure.\r
493 //\r
494 if (SigningTime != NULL) {\r
495 SetMem (SigningTime, sizeof (EFI_TIME), 0);\r
496 Status = ConvertAsn1TimeToEfiTime (TstInfo->GenTime, SigningTime);\r
497 }\r
498\r
499_Exit:\r
500 //\r
501 // Release Resources\r
502 //\r
503 PKCS7_free (Pkcs7);\r
504 X509_free (Cert);\r
505 X509_STORE_free (CertStore);\r
506 BIO_free (OutBio);\r
507 TS_TST_INFO_free (TstInfo);\r
508\r
509 if (TstData != NULL) {\r
510 FreePool (TstData);\r
511 }\r
512\r
513 return Status;\r
514}\r
515\r
516/**\r
2998af86 517 Verifies the validity of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode\r
2ac68e8b
QL
518 signature.\r
519\r
520 If AuthData is NULL, then return FALSE.\r
521\r
522 @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed\r
523 PE/COFF image to be verified.\r
524 @param[in] DataSize Size of the Authenticode Signature in bytes.\r
525 @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER, which\r
526 is used for TSA certificate chain verification.\r
527 @param[in] CertSize Size of the trusted certificate in bytes.\r
528 @param[out] SigningTime Return the time of timestamp generation time if the timestamp\r
529 signature is valid.\r
530\r
531 @retval TRUE The specified Authenticode includes a valid RFC3161 Timestamp CounterSignature.\r
532 @retval FALSE No valid RFC3161 Timestamp CounterSignature in the specified Authenticode data.\r
533\r
534**/\r
535BOOLEAN\r
536EFIAPI\r
537ImageTimestampVerify (\r
538 IN CONST UINT8 *AuthData,\r
539 IN UINTN DataSize,\r
540 IN CONST UINT8 *TsaCert,\r
541 IN UINTN CertSize,\r
542 OUT EFI_TIME *SigningTime\r
543 )\r
544{\r
7c342378
MK
545 BOOLEAN Status;\r
546 PKCS7 *Pkcs7;\r
547 CONST UINT8 *Temp;\r
548\r
549 STACK_OF (PKCS7_SIGNER_INFO) *SignerInfos;\r
550 PKCS7_SIGNER_INFO *SignInfo;\r
551 UINTN Index;\r
552\r
553 STACK_OF (X509_ATTRIBUTE) *Sk;\r
554 X509_ATTRIBUTE *Xa;\r
555 ASN1_OBJECT *XaObj;\r
556 ASN1_TYPE *Asn1Type;\r
557 ASN1_OCTET_STRING *EncDigest;\r
558 UINT8 *TSToken;\r
559 UINTN TokenSize;\r
2ac68e8b
QL
560\r
561 //\r
562 // Input Parameters Checking.\r
563 //\r
564 if ((AuthData == NULL) || (TsaCert == NULL)) {\r
565 return FALSE;\r
566 }\r
567\r
568 if ((DataSize > INT_MAX) || (CertSize > INT_MAX)) {\r
569 return FALSE;\r
570 }\r
571\r
572 //\r
573 // Register & Initialize necessary digest algorithms for PKCS#7 Handling.\r
574 //\r
575 if ((EVP_add_digest (EVP_md5 ()) == 0) || (EVP_add_digest (EVP_sha1 ()) == 0) ||\r
7c342378
MK
576 (EVP_add_digest (EVP_sha256 ()) == 0) || ((EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA)) == 0))\r
577 {\r
2ac68e8b
QL
578 return FALSE;\r
579 }\r
580\r
581 //\r
582 // Initialization.\r
583 //\r
7c342378
MK
584 Status = FALSE;\r
585 Pkcs7 = NULL;\r
586 SignInfo = NULL;\r
2ac68e8b
QL
587\r
588 //\r
589 // Decode ASN.1-encoded Authenticode data into PKCS7 structure.\r
590 //\r
1463ce18 591 Temp = AuthData;\r
7c342378 592 Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (int)DataSize);\r
2ac68e8b
QL
593 if (Pkcs7 == NULL) {\r
594 goto _Exit;\r
595 }\r
596\r
597 //\r
598 // Check if there is one and only one signer.\r
599 //\r
600 SignerInfos = PKCS7_get_signer_info (Pkcs7);\r
601 if (!SignerInfos || (sk_PKCS7_SIGNER_INFO_num (SignerInfos) != 1)) {\r
602 goto _Exit;\r
603 }\r
604\r
605 //\r
606 // Locate the TimeStamp CounterSignature.\r
607 //\r
608 SignInfo = sk_PKCS7_SIGNER_INFO_value (SignerInfos, 0);\r
609 if (SignInfo == NULL) {\r
610 goto _Exit;\r
611 }\r
612\r
613 //\r
614 // Locate Message Digest which will be the data to be time-stamped.\r
615 //\r
616 EncDigest = SignInfo->enc_digest;\r
617 if (EncDigest == NULL) {\r
618 goto _Exit;\r
619 }\r
620\r
621 //\r
622 // The RFC3161 timestamp counterSignature is contained in unauthenticatedAttributes field\r
623 // of SignerInfo.\r
624 //\r
625 Sk = SignInfo->unauth_attr;\r
7c342378
MK
626 if (Sk == NULL) {\r
627 // No timestamp counterSignature.\r
2ac68e8b
QL
628 goto _Exit;\r
629 }\r
630\r
631 Asn1Type = NULL;\r
7c342378 632 for (Index = 0; Index < (UINTN)sk_X509_ATTRIBUTE_num (Sk); Index++) {\r
2ac68e8b
QL
633 //\r
634 // Search valid RFC3161 timestamp counterSignature based on OBJID.\r
635 //\r
636 Xa = sk_X509_ATTRIBUTE_value (Sk, (int)Index);\r
4ffe0fac 637 if (Xa == NULL) {\r
2ac68e8b
QL
638 continue;\r
639 }\r
7c342378
MK
640\r
641 XaObj = X509_ATTRIBUTE_get0_object (Xa);\r
4ffe0fac
DW
642 if (XaObj == NULL) {\r
643 continue;\r
644 }\r
7c342378
MK
645\r
646 if ((OBJ_length (XaObj) != sizeof (mSpcRFC3161OidValue)) ||\r
647 (CompareMem (OBJ_get0_data (XaObj), mSpcRFC3161OidValue, sizeof (mSpcRFC3161OidValue)) != 0))\r
648 {\r
4ffe0fac
DW
649 continue;\r
650 }\r
7c342378
MK
651\r
652 Asn1Type = X509_ATTRIBUTE_get0_type (Xa, 0);\r
2ac68e8b
QL
653 }\r
654\r
655 if (Asn1Type == NULL) {\r
656 Status = FALSE;\r
657 goto _Exit;\r
658 }\r
7c342378 659\r
2ac68e8b
QL
660 TSToken = Asn1Type->value.octet_string->data;\r
661 TokenSize = Asn1Type->value.octet_string->length;\r
662\r
663 //\r
664 // TimeStamp counterSignature (Token) verification.\r
665 //\r
666 Status = TimestampTokenVerify (\r
667 TSToken,\r
668 TokenSize,\r
669 TsaCert,\r
670 CertSize,\r
671 EncDigest->data,\r
672 EncDigest->length,\r
673 SigningTime\r
674 );\r
675\r
676_Exit:\r
677 //\r
678 // Release Resources\r
679 //\r
680 PKCS7_free (Pkcs7);\r
681\r
682 return Status;\r
683}\r