]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
Enable/Disable Secured Boot by 'Secure Boot Configuration' Page which is under Setup...
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / RuntimeDxe / AuthService.c
1 /** @file
2 Implement authentication services for the authenticated variable
3 service in UEFI2.2.
4
5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Variable.h"
17 #include "AuthService.h"
18
19 ///
20 /// Global database array for scratch
21 ///
22 UINT8 mPubKeyStore[MAX_KEYDB_SIZE];
23 UINT32 mPubKeyNumber;
24 UINT32 mPlatformMode;
25 EFI_GUID mSignatureSupport[SIGSUPPORT_NUM] = {EFI_CERT_RSA2048_SHA256_GUID, EFI_CERT_RSA2048_SHA1_GUID};
26 //
27 // Public Exponent of RSA Key.
28 //
29 CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
30 //
31 // Hash context pointer
32 //
33 VOID *mHashCtx = NULL;
34
35
36 //
37 // Pointer to runtime buffer.
38 // For "Append" operation to an existing variable, a read/modify/write operation
39 // is supported by firmware internally. Reserve runtime buffer to cache previous
40 // variable data in runtime phase because memory allocation is forbidden in virtual mode.
41 //
42 VOID *mStorageArea = NULL;
43
44 /**
45 Update platform mode.
46
47 @param[in] Mode SETUP_MODE or USER_MODE.
48
49 @return EFI_INVALID_PARAMETER Invalid parameter.
50 @return EFI_SUCCESS Update platform mode successfully.
51
52 **/
53 EFI_STATUS
54 UpdatePlatformMode (
55 IN UINT32 Mode
56 );
57
58 /**
59 Initializes for authenticated varibale service.
60
61 @retval EFI_SUCCESS Function successfully executed.
62 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resources.
63
64 **/
65 EFI_STATUS
66 AutenticatedVariableServiceInitialize (
67 VOID
68 )
69 {
70 EFI_STATUS Status;
71 VARIABLE_POINTER_TRACK Variable;
72 VARIABLE_POINTER_TRACK Variable2;
73 UINT8 VarValue;
74 UINT32 VarAttr;
75 UINT8 *Data;
76 UINTN DataSize;
77 UINTN CtxSize;
78 UINT8 SecureBootMode;
79 UINT8 SecureBootEnable;
80
81 //
82 // Initialize hash context.
83 //
84 CtxSize = Sha256GetContextSize ();
85 mHashCtx = AllocateRuntimePool (CtxSize);
86 if (mHashCtx == NULL) {
87 return EFI_OUT_OF_RESOURCES;
88 }
89
90 //
91 // Reserved runtime buffer for "Append" operation in virtual mode.
92 //
93 mStorageArea = AllocateRuntimePool (PcdGet32 (PcdMaxAppendVariableSize));
94 if (mStorageArea == NULL) {
95 return EFI_OUT_OF_RESOURCES;
96 }
97
98 //
99 // Check "AuthVarKeyDatabase" variable's existence.
100 // If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
101 //
102 Status = FindVariable (
103 AUTHVAR_KEYDB_NAME,
104 &gEfiAuthenticatedVariableGuid,
105 &Variable,
106 &mVariableModuleGlobal->VariableGlobal
107 );
108
109 if (Variable.CurrPtr == NULL) {
110 VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
111 VarValue = 0;
112 mPubKeyNumber = 0;
113 Status = UpdateVariable (
114 AUTHVAR_KEYDB_NAME,
115 &gEfiAuthenticatedVariableGuid,
116 &VarValue,
117 sizeof(UINT8),
118 VarAttr,
119 0,
120 0,
121 &Variable,
122 NULL
123 );
124 if (EFI_ERROR (Status)) {
125 return Status;
126 }
127 } else {
128 //
129 // Load database in global variable for cache.
130 //
131 DataSize = DataSizeOfVariable (Variable.CurrPtr);
132 Data = GetVariableDataPtr (Variable.CurrPtr);
133 ASSERT ((DataSize != 0) && (Data != NULL));
134 CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);
135 mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
136 }
137 //
138 // Check "SetupMode" variable's existence.
139 // If it doesn't exist, check PK database's existence to determine the value.
140 // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
141 //
142 Status = FindVariable (
143 EFI_SETUP_MODE_NAME,
144 &gEfiGlobalVariableGuid,
145 &Variable,
146 &mVariableModuleGlobal->VariableGlobal
147 );
148
149 if (Variable.CurrPtr == NULL) {
150 Status = FindVariable (
151 EFI_PLATFORM_KEY_NAME,
152 &gEfiGlobalVariableGuid,
153 &Variable2,
154 &mVariableModuleGlobal->VariableGlobal
155 );
156 if (Variable2.CurrPtr == NULL) {
157 mPlatformMode = SETUP_MODE;
158 } else {
159 mPlatformMode = USER_MODE;
160 }
161
162 VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
163 Status = UpdateVariable (
164 EFI_SETUP_MODE_NAME,
165 &gEfiGlobalVariableGuid,
166 &mPlatformMode,
167 sizeof(UINT8),
168 VarAttr,
169 0,
170 0,
171 &Variable,
172 NULL
173 );
174 if (EFI_ERROR (Status)) {
175 return Status;
176 }
177 } else {
178 mPlatformMode = *(GetVariableDataPtr (Variable.CurrPtr));
179 }
180 //
181 // Check "SignatureSupport" variable's existence.
182 // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
183 //
184 Status = FindVariable (
185 EFI_SIGNATURE_SUPPORT_NAME,
186 &gEfiGlobalVariableGuid,
187 &Variable,
188 &mVariableModuleGlobal->VariableGlobal
189 );
190
191
192 if (Variable.CurrPtr == NULL) {
193 VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
194 Status = UpdateVariable (
195 EFI_SIGNATURE_SUPPORT_NAME,
196 &gEfiGlobalVariableGuid,
197 mSignatureSupport,
198 SIGSUPPORT_NUM * sizeof(EFI_GUID),
199 VarAttr,
200 0,
201 0,
202 &Variable,
203 NULL
204 );
205 }
206
207 //
208 // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.
209 // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
210 // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.
211 //
212 FindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
213 if (Variable.CurrPtr != NULL) {
214 SecureBootEnable = *(GetVariableDataPtr (Variable.CurrPtr));
215 if (SecureBootEnable == SECURE_BOOT_ENABLE) {
216 SecureBootMode = SECURE_BOOT_MODE_ENABLE;
217 } else {
218 SecureBootMode = SECURE_BOOT_MODE_DISABLE;
219 }
220 FindVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal);
221 Status = UpdateVariable (
222 EFI_SECURE_BOOT_MODE_NAME,
223 &gEfiGlobalVariableGuid,
224 &SecureBootMode,
225 sizeof(UINT8),
226 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
227 0,
228 0,
229 &Variable,
230 NULL
231 );
232 if (EFI_ERROR (Status)) {
233 return Status;
234 }
235 }
236
237 //
238 // Detect whether a secure platform-specific method to clear PK(Platform Key)
239 // is configured by platform owner. This method is provided for users force to clear PK
240 // in case incorrect enrollment mis-haps.
241 //
242 if (ForceClearPK ()) {
243 //
244 // 1. Check whether PK is existing, and clear PK if existing
245 //
246 FindVariable (
247 EFI_PLATFORM_KEY_NAME,
248 &gEfiGlobalVariableGuid,
249 &Variable,
250 &mVariableModuleGlobal->VariableGlobal
251 );
252 if (Variable.CurrPtr != NULL) {
253 VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
254 Status = UpdateVariable (
255 EFI_PLATFORM_KEY_NAME,
256 &gEfiGlobalVariableGuid,
257 NULL,
258 0,
259 VarAttr,
260 0,
261 0,
262 &Variable,
263 NULL
264 );
265 if (EFI_ERROR (Status)) {
266 return Status;
267 }
268 }
269
270 //
271 // 2. Update "SetupMode" variable to SETUP_MODE
272 //
273 UpdatePlatformMode (SETUP_MODE);
274 }
275 return Status;
276 }
277
278 /**
279 Add public key in store and return its index.
280
281 @param[in] PubKey Input pointer to Public Key data
282
283 @return Index of new added item
284
285 **/
286 UINT32
287 AddPubKeyInStore (
288 IN UINT8 *PubKey
289 )
290 {
291 EFI_STATUS Status;
292 BOOLEAN IsFound;
293 UINT32 Index;
294 VARIABLE_POINTER_TRACK Variable;
295 UINT8 *Ptr;
296
297 if (PubKey == NULL) {
298 return 0;
299 }
300
301 Status = FindVariable (
302 AUTHVAR_KEYDB_NAME,
303 &gEfiAuthenticatedVariableGuid,
304 &Variable,
305 &mVariableModuleGlobal->VariableGlobal
306 );
307 ASSERT_EFI_ERROR (Status);
308 //
309 // Check whether the public key entry does exist.
310 //
311 IsFound = FALSE;
312 for (Ptr = mPubKeyStore, Index = 1; Index <= mPubKeyNumber; Index++) {
313 if (CompareMem (Ptr, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
314 IsFound = TRUE;
315 break;
316 }
317 Ptr += EFI_CERT_TYPE_RSA2048_SIZE;
318 }
319
320 if (!IsFound) {
321 //
322 // Add public key in database.
323 //
324 if (mPubKeyNumber == MAX_KEY_NUM) {
325 //
326 // Notes: Database is full, need enhancement here, currently just return 0.
327 //
328 return 0;
329 }
330
331 CopyMem (mPubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
332 Index = ++mPubKeyNumber;
333 //
334 // Update public key database variable.
335 //
336 Status = UpdateVariable (
337 AUTHVAR_KEYDB_NAME,
338 &gEfiAuthenticatedVariableGuid,
339 mPubKeyStore,
340 mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE,
341 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
342 0,
343 0,
344 &Variable,
345 NULL
346 );
347 ASSERT_EFI_ERROR (Status);
348 }
349
350 return Index;
351 }
352
353 /**
354 Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256 type.
355 Follow the steps in UEFI2.2.
356
357 @param[in] Data Pointer to data with AuthInfo.
358 @param[in] DataSize Size of Data.
359 @param[in] PubKey Public key used for verification.
360
361 @return EFI_INVALID_PARAMETER Invalid parameter.
362 @retval EFI_SECURITY_VIOLATION If authentication failed.
363 @return EFI_SUCCESS Authentication successful.
364
365 **/
366 EFI_STATUS
367 VerifyCounterBasedPayload (
368 IN UINT8 *Data,
369 IN UINTN DataSize,
370 IN UINT8 *PubKey
371 )
372 {
373 BOOLEAN Status;
374 EFI_VARIABLE_AUTHENTICATION *CertData;
375 EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
376 UINT8 Digest[SHA256_DIGEST_SIZE];
377 VOID *Rsa;
378
379 Rsa = NULL;
380 CertData = NULL;
381 CertBlock = NULL;
382
383 if (Data == NULL || PubKey == NULL) {
384 return EFI_INVALID_PARAMETER;
385 }
386
387 CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
388 CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
389
390 //
391 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
392 // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256.
393 //
394 if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
395 !CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertRsa2048Sha256Guid)
396 ) {
397 //
398 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
399 //
400 return EFI_SECURITY_VIOLATION;
401 }
402 //
403 // Hash data payload with SHA256.
404 //
405 ZeroMem (Digest, SHA256_DIGEST_SIZE);
406 Status = Sha256Init (mHashCtx);
407 if (!Status) {
408 goto Done;
409 }
410 Status = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, (UINTN) (DataSize - AUTHINFO_SIZE));
411 if (!Status) {
412 goto Done;
413 }
414 //
415 // Hash Monotonic Count.
416 //
417 Status = Sha256Update (mHashCtx, &CertData->MonotonicCount, sizeof (UINT64));
418 if (!Status) {
419 goto Done;
420 }
421 Status = Sha256Final (mHashCtx, Digest);
422 if (!Status) {
423 goto Done;
424 }
425 //
426 // Generate & Initialize RSA Context.
427 //
428 Rsa = RsaNew ();
429 ASSERT (Rsa != NULL);
430 //
431 // Set RSA Key Components.
432 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
433 //
434 Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
435 if (!Status) {
436 goto Done;
437 }
438 Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
439 if (!Status) {
440 goto Done;
441 }
442 //
443 // Verify the signature.
444 //
445 Status = RsaPkcs1Verify (
446 Rsa,
447 Digest,
448 SHA256_DIGEST_SIZE,
449 CertBlock->Signature,
450 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
451 );
452
453 Done:
454 if (Rsa != NULL) {
455 RsaFree (Rsa);
456 }
457 if (Status) {
458 return EFI_SUCCESS;
459 } else {
460 return EFI_SECURITY_VIOLATION;
461 }
462 }
463
464
465 /**
466 Update platform mode.
467
468 @param[in] Mode SETUP_MODE or USER_MODE.
469
470 @return EFI_INVALID_PARAMETER Invalid parameter.
471 @return EFI_SUCCESS Update platform mode successfully.
472
473 **/
474 EFI_STATUS
475 UpdatePlatformMode (
476 IN UINT32 Mode
477 )
478 {
479 EFI_STATUS Status;
480 VARIABLE_POINTER_TRACK Variable;
481 UINT32 VarAttr;
482 UINT8 SecureBootMode;
483 UINT8 SecureBootEnable;
484 UINTN VariableDataSize;
485
486 Status = FindVariable (
487 EFI_SETUP_MODE_NAME,
488 &gEfiGlobalVariableGuid,
489 &Variable,
490 &mVariableModuleGlobal->VariableGlobal
491 );
492 if (EFI_ERROR (Status)) {
493 return Status;
494 }
495
496 mPlatformMode = Mode;
497 VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
498 Status = UpdateVariable (
499 EFI_SETUP_MODE_NAME,
500 &gEfiGlobalVariableGuid,
501 &mPlatformMode,
502 sizeof(UINT8),
503 VarAttr,
504 0,
505 0,
506 &Variable,
507 NULL
508 );
509 if (EFI_ERROR (Status)) {
510 return Status;
511 }
512
513 //
514 // Check "SecureBoot" variable's existence.
515 // If it doesn't exist, firmware has no capability to perform driver signing verification,
516 // then set "SecureBoot" to 0.
517 //
518 Status = FindVariable (
519 EFI_SECURE_BOOT_MODE_NAME,
520 &gEfiGlobalVariableGuid,
521 &Variable,
522 &mVariableModuleGlobal->VariableGlobal
523 );
524 //
525 // If "SecureBoot" variable exists, then check "SetupMode" variable update.
526 // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1.
527 // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0.
528 //
529 if (Variable.CurrPtr == NULL) {
530 SecureBootMode = SECURE_BOOT_MODE_DISABLE;
531 } else {
532 if (mPlatformMode == USER_MODE) {
533 SecureBootMode = SECURE_BOOT_MODE_ENABLE;
534 } else if (mPlatformMode == SETUP_MODE) {
535 SecureBootMode = SECURE_BOOT_MODE_DISABLE;
536 } else {
537 return EFI_NOT_FOUND;
538 }
539 }
540
541 VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
542 Status = UpdateVariable (
543 EFI_SECURE_BOOT_MODE_NAME,
544 &gEfiGlobalVariableGuid,
545 &SecureBootMode,
546 sizeof(UINT8),
547 VarAttr,
548 0,
549 0,
550 &Variable,
551 NULL
552 );
553
554 if (EFI_ERROR (Status)) {
555 return Status;
556 }
557
558 //
559 // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature.
560 //
561 Status = FindVariable (
562 EFI_SECURE_BOOT_ENABLE_NAME,
563 &gEfiSecureBootEnableDisableGuid,
564 &Variable,
565 &mVariableModuleGlobal->VariableGlobal
566 );
567
568 if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) {
569 //
570 // Create the "SecureBootEnable" variable as secure boot is enabled.
571 //
572 SecureBootEnable = SECURE_BOOT_ENABLE;
573 VariableDataSize = sizeof (SecureBootEnable);
574 } else {
575 //
576 // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot"
577 // variable is not in secure boot state.
578 //
579 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
580 return EFI_SUCCESS;
581 }
582 SecureBootEnable = SECURE_BOOT_DISABLE;
583 VariableDataSize = 0;
584 }
585
586 Status = UpdateVariable (
587 EFI_SECURE_BOOT_ENABLE_NAME,
588 &gEfiSecureBootEnableDisableGuid,
589 &SecureBootEnable,
590 VariableDataSize,
591 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
592 0,
593 0,
594 &Variable,
595 NULL
596 );
597 return Status;
598 }
599
600 /**
601 Process variable with platform key for verification.
602
603 @param[in] VariableName Name of Variable to be found.
604 @param[in] VendorGuid Variable vendor GUID.
605 @param[in] Data Data pointer.
606 @param[in] DataSize Size of Data found. If size is less than the
607 data, this value contains the required size.
608 @param[in] Variable The variable information which is used to keep track of variable usage.
609 @param[in] Attributes Attribute value of the variable
610 @param[in] IsPk Indicate whether it is to process pk.
611
612 @return EFI_INVALID_PARAMETER Invalid parameter.
613 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
614 check carried out by the firmware.
615 @return EFI_SUCCESS Variable passed validation successfully.
616
617 **/
618 EFI_STATUS
619 ProcessVarWithPk (
620 IN CHAR16 *VariableName,
621 IN EFI_GUID *VendorGuid,
622 IN VOID *Data,
623 IN UINTN DataSize,
624 IN VARIABLE_POINTER_TRACK *Variable,
625 IN UINT32 Attributes OPTIONAL,
626 IN BOOLEAN IsPk
627 )
628 {
629 EFI_STATUS Status;
630 VARIABLE_POINTER_TRACK PkVariable;
631 EFI_SIGNATURE_LIST *OldPkList;
632 EFI_SIGNATURE_DATA *OldPkData;
633 EFI_VARIABLE_AUTHENTICATION *CertData;
634 BOOLEAN TimeBase;
635 BOOLEAN Del;
636
637 if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
638 //
639 // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
640 //
641 return EFI_INVALID_PARAMETER;
642 }
643
644 if (mPlatformMode == USER_MODE) {
645
646 if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
647 //
648 // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute means time-based X509 Cert PK.
649 //
650 TimeBase = TRUE;
651 } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
652 //
653 // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute means counter-based RSA-2048 Cert PK.
654 //
655 TimeBase = FALSE;
656 } else {
657 return EFI_INVALID_PARAMETER;
658 }
659
660 if (TimeBase) {
661 //
662 // Verify against X509 Cert PK.
663 //
664 Del = FALSE;
665 Status = VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, TRUE, &Del);
666 if (!EFI_ERROR (Status)) {
667 //
668 // If delete PK in user mode, need change to setup mode.
669 //
670 if (Del && IsPk) {
671 Status = UpdatePlatformMode (SETUP_MODE);
672 }
673 }
674 return Status;
675 } else {
676 //
677 // Verify against RSA2048 Cert PK.
678 //
679 CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
680 if ((Variable->CurrPtr != NULL) && (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount)) {
681 //
682 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
683 //
684 return EFI_SECURITY_VIOLATION;
685 }
686 //
687 // Get platform key from variable.
688 //
689 Status = FindVariable (
690 EFI_PLATFORM_KEY_NAME,
691 &gEfiGlobalVariableGuid,
692 &PkVariable,
693 &mVariableModuleGlobal->VariableGlobal
694 );
695 ASSERT_EFI_ERROR (Status);
696
697 OldPkList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (PkVariable.CurrPtr);
698 OldPkData = (EFI_SIGNATURE_DATA *) ((UINT8 *) OldPkList + sizeof (EFI_SIGNATURE_LIST) + OldPkList->SignatureHeaderSize);
699 Status = VerifyCounterBasedPayload (Data, DataSize, OldPkData->SignatureData);
700 if (!EFI_ERROR (Status)) {
701 Status = UpdateVariable (
702 VariableName,
703 VendorGuid,
704 (UINT8*)Data + AUTHINFO_SIZE,
705 DataSize - AUTHINFO_SIZE,
706 Attributes,
707 0,
708 CertData->MonotonicCount,
709 Variable,
710 NULL
711 );
712
713 if (!EFI_ERROR (Status)) {
714 //
715 // If delete PK in user mode, need change to setup mode.
716 //
717 if ((DataSize == AUTHINFO_SIZE) && IsPk) {
718 Status = UpdatePlatformMode (SETUP_MODE);
719 }
720 }
721 }
722 }
723 } else {
724 Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, Variable, NULL);
725 //
726 // If enroll PK in setup mode, need change to user mode.
727 //
728 if ((DataSize != 0) && IsPk) {
729 Status = UpdatePlatformMode (USER_MODE);
730 }
731 }
732
733 return Status;
734 }
735
736 /**
737 Process variable with key exchange key for verification.
738
739 @param[in] VariableName Name of Variable to be found.
740 @param[in] VendorGuid Variable vendor GUID.
741 @param[in] Data Data pointer.
742 @param[in] DataSize Size of Data found. If size is less than the
743 data, this value contains the required size.
744 @param[in] Variable The variable information which is used to keep track of variable usage.
745 @param[in] Attributes Attribute value of the variable.
746
747 @return EFI_INVALID_PARAMETER Invalid parameter.
748 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation
749 check carried out by the firmware.
750 @return EFI_SUCCESS Variable pass validation successfully.
751
752 **/
753 EFI_STATUS
754 ProcessVarWithKek (
755 IN CHAR16 *VariableName,
756 IN EFI_GUID *VendorGuid,
757 IN VOID *Data,
758 IN UINTN DataSize,
759 IN VARIABLE_POINTER_TRACK *Variable,
760 IN UINT32 Attributes OPTIONAL
761 )
762 {
763 EFI_STATUS Status;
764 VARIABLE_POINTER_TRACK KekVariable;
765 EFI_SIGNATURE_LIST *KekList;
766 EFI_SIGNATURE_DATA *KekItem;
767 UINT32 KekCount;
768 EFI_VARIABLE_AUTHENTICATION *CertData;
769 EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
770 BOOLEAN IsFound;
771 UINT32 Index;
772 UINT32 KekDataSize;
773
774 if (mPlatformMode == USER_MODE) {
775 if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
776 //
777 // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
778 //
779 return EFI_INVALID_PARAMETER;
780 }
781
782 CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
783 CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
784 if ((Variable->CurrPtr != NULL) && (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount)) {
785 //
786 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
787 //
788 return EFI_SECURITY_VIOLATION;
789 }
790 //
791 // Get KEK database from variable.
792 //
793 Status = FindVariable (
794 EFI_KEY_EXCHANGE_KEY_NAME,
795 &gEfiGlobalVariableGuid,
796 &KekVariable,
797 &mVariableModuleGlobal->VariableGlobal
798 );
799 ASSERT_EFI_ERROR (Status);
800
801 KekDataSize = KekVariable.CurrPtr->DataSize;
802 KekList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (KekVariable.CurrPtr);
803
804 //
805 // Enumerate all Kek items in this list to verify the variable certificate data.
806 // If anyone is authenticated successfully, it means the variable is correct!
807 //
808 IsFound = FALSE;
809 while ((KekDataSize > 0) && (KekDataSize >= KekList->SignatureListSize)) {
810 if (CompareGuid (&KekList->SignatureType, &gEfiCertRsa2048Guid)) {
811 KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekList + sizeof (EFI_SIGNATURE_LIST) + KekList->SignatureHeaderSize);
812 KekCount = (KekList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - KekList->SignatureHeaderSize) / KekList->SignatureSize;
813 for (Index = 0; Index < KekCount; Index++) {
814 if (CompareMem (KekItem->SignatureData, CertBlock->PublicKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
815 IsFound = TRUE;
816 break;
817 }
818 KekItem = (EFI_SIGNATURE_DATA *) ((UINT8 *) KekItem + KekList->SignatureSize);
819 }
820 }
821 KekDataSize -= KekList->SignatureListSize;
822 KekList = (EFI_SIGNATURE_LIST *) ((UINT8 *) KekList + KekList->SignatureListSize);
823 }
824
825 if (!IsFound) {
826 return EFI_SECURITY_VIOLATION;
827 }
828
829 Status = VerifyCounterBasedPayload (Data, DataSize, CertBlock->PublicKey);
830 if (!EFI_ERROR (Status)) {
831 Status = UpdateVariable (
832 VariableName,
833 VendorGuid,
834 (UINT8*)Data + AUTHINFO_SIZE,
835 DataSize - AUTHINFO_SIZE,
836 Attributes,
837 0,
838 CertData->MonotonicCount,
839 Variable,
840 NULL
841 );
842 }
843 } else {
844 //
845 // If in setup mode, no authentication needed.
846 //
847 Status = UpdateVariable (
848 VariableName,
849 VendorGuid,
850 Data,
851 DataSize,
852 Attributes,
853 0,
854 0,
855 Variable,
856 NULL
857 );
858 }
859
860 return Status;
861 }
862
863 /**
864 Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
865
866 @param[in] VariableName Name of Variable to be found.
867 @param[in] VendorGuid Variable vendor GUID.
868
869 @param[in] Data Data pointer.
870 @param[in] DataSize Size of Data found. If size is less than the
871 data, this value contains the required size.
872 @param[in] Variable The variable information which is used to keep track of variable usage.
873 @param[in] Attributes Attribute value of the variable.
874
875 @return EFI_INVALID_PARAMETER Invalid parameter.
876 @return EFI_WRITE_PROTECTED Variable is write-protected and needs authentication with
877 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
878 @return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
879 set, but the AuthInfo does NOT pass the validation
880 check carried out by the firmware.
881 @return EFI_SUCCESS Variable is not write-protected or pass validation successfully.
882
883 **/
884 EFI_STATUS
885 ProcessVariable (
886 IN CHAR16 *VariableName,
887 IN EFI_GUID *VendorGuid,
888 IN VOID *Data,
889 IN UINTN DataSize,
890 IN VARIABLE_POINTER_TRACK *Variable,
891 IN UINT32 Attributes
892 )
893 {
894 EFI_STATUS Status;
895 BOOLEAN IsDeletion;
896 BOOLEAN IsFirstTime;
897 UINT8 *PubKey;
898 EFI_VARIABLE_AUTHENTICATION *CertData;
899 EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
900 UINT32 KeyIndex;
901 UINT64 MonotonicCount;
902
903 KeyIndex = 0;
904 CertData = NULL;
905 CertBlock = NULL;
906 PubKey = NULL;
907 IsDeletion = FALSE;
908
909 //
910 // Process Time-based Authenticated variable.
911 //
912 if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
913 return VerifyTimeBasedPayload (VariableName, VendorGuid, Data, DataSize, Variable, Attributes, FALSE, NULL);
914 }
915
916 //
917 // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.
918 //
919 if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
920 //
921 // Determine current operation type.
922 //
923 if (DataSize == AUTHINFO_SIZE) {
924 IsDeletion = TRUE;
925 }
926 //
927 // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
928 //
929 if (Variable->CurrPtr == NULL) {
930 IsFirstTime = TRUE;
931 } else if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
932 IsFirstTime = TRUE;
933 } else {
934 KeyIndex = Variable->CurrPtr->PubKeyIndex;
935 IsFirstTime = FALSE;
936 }
937 } else if ((Variable->CurrPtr != NULL) &&
938 (Variable->CurrPtr->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0
939 ) {
940 //
941 // If the variable is already write-protected, it always needs authentication before update.
942 //
943 return EFI_WRITE_PROTECTED;
944 } else {
945 //
946 // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.
947 // That means it is not authenticated variable, just update variable as usual.
948 //
949 Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, Variable, NULL);
950 return Status;
951 }
952
953 //
954 // Get PubKey and check Monotonic Count value corresponding to the variable.
955 //
956 CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
957 CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
958 PubKey = CertBlock->PublicKey;
959
960 //
961 // Update Monotonic Count value.
962 //
963 MonotonicCount = CertData->MonotonicCount;
964
965 if (!IsFirstTime) {
966 //
967 // Check input PubKey.
968 //
969 if (CompareMem (PubKey, mPubKeyStore + (KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) {
970 return EFI_SECURITY_VIOLATION;
971 }
972 //
973 // Compare the current monotonic count and ensure that it is greater than the last SetVariable
974 // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.
975 //
976 if (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount) {
977 //
978 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
979 //
980 return EFI_SECURITY_VIOLATION;
981 }
982 }
983 //
984 // Verify the certificate in Data payload.
985 //
986 Status = VerifyCounterBasedPayload (Data, DataSize, PubKey);
987 if (EFI_ERROR (Status)) {
988 return Status;
989 }
990
991 //
992 // Now, the signature has been verified!
993 //
994 if (IsFirstTime && !IsDeletion) {
995 //
996 // Update public key database variable if need.
997 //
998 KeyIndex = AddPubKeyInStore (PubKey);
999 }
1000
1001 //
1002 // Verification pass.
1003 //
1004 return UpdateVariable (VariableName, VendorGuid, (UINT8*)Data + AUTHINFO_SIZE, DataSize - AUTHINFO_SIZE, Attributes, KeyIndex, MonotonicCount, Variable, NULL);
1005 }
1006
1007 /**
1008 Compare two EFI_TIME data.
1009
1010
1011 @param FirstTime A pointer to the first EFI_TIME data.
1012 @param SecondTime A pointer to the second EFI_TIME data.
1013
1014 @retval TRUE The FirstTime is not later than the SecondTime.
1015 @retval FALSE The FirstTime is later than the SecondTime.
1016
1017 **/
1018 BOOLEAN
1019 CompareTimeStamp (
1020 IN EFI_TIME *FirstTime,
1021 IN EFI_TIME *SecondTime
1022 )
1023 {
1024 if (FirstTime->Year != SecondTime->Year) {
1025 return (BOOLEAN) (FirstTime->Year < SecondTime->Year);
1026 } else if (FirstTime->Month != SecondTime->Month) {
1027 return (BOOLEAN) (FirstTime->Month < SecondTime->Month);
1028 } else if (FirstTime->Day != SecondTime->Day) {
1029 return (BOOLEAN) (FirstTime->Day < SecondTime->Day);
1030 } else if (FirstTime->Hour != SecondTime->Hour) {
1031 return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
1032 } else if (FirstTime->Minute != SecondTime->Minute) {
1033 return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);
1034 }
1035
1036 return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);
1037 }
1038
1039 /**
1040 Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
1041
1042 @param[in] VariableName Name of Variable to be found.
1043 @param[in] VendorGuid Variable vendor GUID.
1044 @param[in] Data Data pointer.
1045 @param[in] DataSize Size of Data found. If size is less than the
1046 data, this value contains the required size.
1047 @param[in] Variable The variable information which is used to keep track of variable usage.
1048 @param[in] Attributes Attribute value of the variable.
1049 @param[in] Pk Verify against PK or KEK database.
1050 @param[out] VarDel Delete the variable or not.
1051
1052 @retval EFI_INVALID_PARAMETER Invalid parameter.
1053 @retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
1054 check carried out by the firmware.
1055 @retval EFI_OUT_OF_RESOURCES Failed to process variable due to lack
1056 of resources.
1057 @retval EFI_SUCCESS Variable pass validation successfully.
1058
1059 **/
1060 EFI_STATUS
1061 VerifyTimeBasedPayload (
1062 IN CHAR16 *VariableName,
1063 IN EFI_GUID *VendorGuid,
1064 IN VOID *Data,
1065 IN UINTN DataSize,
1066 IN VARIABLE_POINTER_TRACK *Variable,
1067 IN UINT32 Attributes,
1068 IN BOOLEAN Pk,
1069 OUT BOOLEAN *VarDel
1070 )
1071 {
1072 UINT8 *RootCert;
1073 UINT8 *SigData;
1074 UINT8 *PayLoadPtr;
1075 UINTN RootCertSize;
1076 UINTN Index;
1077 UINTN CertCount;
1078 UINTN PayLoadSize;
1079 UINT32 Attr;
1080 UINT32 SigDataSize;
1081 UINT32 KekDataSize;
1082 BOOLEAN Result;
1083 BOOLEAN VerifyStatus;
1084 EFI_STATUS Status;
1085 EFI_SIGNATURE_LIST *CertList;
1086 EFI_SIGNATURE_DATA *Cert;
1087 VARIABLE_POINTER_TRACK KekVariable;
1088 EFI_VARIABLE_AUTHENTICATION_2 *CertData;
1089 UINT8 *NewData;
1090 UINTN NewDataSize;
1091 VARIABLE_POINTER_TRACK PkVariable;
1092
1093
1094 Result = FALSE;
1095 VerifyStatus = FALSE;
1096 CertData = NULL;
1097 NewData = NULL;
1098 Attr = Attributes;
1099
1100 //
1101 // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
1102 // set, then the Data buffer shall begin with an instance of a complete (and serialized)
1103 // EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new
1104 // variable value and DataSize shall reflect the combined size of the descriptor and the new
1105 // variable value. The authentication descriptor is not part of the variable data and is not
1106 // returned by subsequent calls to GetVariable().
1107 //
1108 CertData = (EFI_VARIABLE_AUTHENTICATION_2 *) Data;
1109
1110 if ((Variable->CurrPtr != NULL) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
1111 if (CompareTimeStamp (&CertData->TimeStamp, &Variable->CurrPtr->TimeStamp)) {
1112 //
1113 // TimeStamp check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1114 //
1115 return EFI_SECURITY_VIOLATION;
1116 }
1117 }
1118
1119 //
1120 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
1121 // Cert type should be EFI_CERT_TYPE_PKCS7_GUID.
1122 //
1123 if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
1124 !CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertPkcs7Guid)
1125 ) {
1126 //
1127 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
1128 //
1129 return EFI_SECURITY_VIOLATION;
1130 }
1131
1132 //
1133 // Find out Pkcs7 SignedData which follows the EFI_VARIABLE_AUTHENTICATION_2 descriptor.
1134 // AuthInfo.Hdr.dwLength is the length of the entire certificate, including the length of the header.
1135 //
1136 SigData = (UINT8*) ((UINTN)Data + OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData));
1137
1138 //
1139 // Sanity check to avoid corrupted certificate input.
1140 //
1141 if (CertData->AuthInfo.Hdr.dwLength < (UINT32)(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData))) {
1142 return EFI_SECURITY_VIOLATION;
1143 }
1144
1145
1146
1147 SigDataSize = CertData->AuthInfo.Hdr.dwLength - (UINT32)(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData));
1148
1149 //
1150 // Find out the new data payload which follows Pkcs7 SignedData directly.
1151 //
1152 PayLoadPtr = (UINT8*) ((UINTN) SigData + (UINTN) SigDataSize);
1153
1154 //
1155 // Sanity check to avoid corrupted certificate input.
1156 //
1157 if (DataSize < (OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)+ (UINTN) SigDataSize)) {
1158 return EFI_SECURITY_VIOLATION;
1159 }
1160
1161 PayLoadSize = DataSize - OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) - OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData) - (UINTN) SigDataSize;
1162
1163
1164 //
1165 // Construct a buffer to fill with (VariableName, VendorGuid, Attributes, TimeStamp, Data).
1166 //
1167 NewDataSize = PayLoadSize + sizeof (EFI_TIME) + sizeof (UINT32) +
1168 sizeof (EFI_GUID) + StrSize (VariableName);
1169 NewData = (UINT8 *) AllocateZeroPool (NewDataSize);
1170
1171 if (NewData == NULL) {
1172 return EFI_OUT_OF_RESOURCES;
1173 }
1174
1175 CopyMem (NewData, VariableName, StrSize (VariableName));
1176
1177 CopyMem (NewData + StrSize (VariableName), VendorGuid, sizeof (EFI_GUID));
1178
1179 CopyMem (
1180 NewData + StrSize (VariableName) + sizeof (EFI_GUID),
1181 &Attr,
1182 sizeof (UINT32)
1183 );
1184
1185 CopyMem (
1186 NewData + StrSize (VariableName) + sizeof (EFI_GUID) + sizeof (UINT32),
1187 &CertData->TimeStamp,
1188 sizeof (EFI_TIME)
1189 );
1190
1191 CopyMem (NewData + (NewDataSize - PayLoadSize), PayLoadPtr, PayLoadSize);
1192
1193
1194 if (Pk) {
1195 //
1196 // Get platform key from variable.
1197 //
1198 Status = FindVariable (
1199 EFI_PLATFORM_KEY_NAME,
1200 &gEfiGlobalVariableGuid,
1201 &PkVariable,
1202 &mVariableModuleGlobal->VariableGlobal
1203 );
1204 if (EFI_ERROR (Status)) {
1205 return Status;
1206 }
1207
1208 CertList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (PkVariable.CurrPtr);
1209 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1210 RootCert = Cert->SignatureData;
1211 RootCertSize = CertList->SignatureSize;
1212
1213
1214 //
1215 // Verify Pkcs7 SignedData via Pkcs7Verify library.
1216 //
1217 VerifyStatus = Pkcs7Verify (
1218 SigData,
1219 SigDataSize,
1220 RootCert,
1221 RootCertSize,
1222 NewData,
1223 NewDataSize
1224 );
1225
1226 } else {
1227
1228 //
1229 // Get KEK database from variable.
1230 //
1231 Status = FindVariable (
1232 EFI_KEY_EXCHANGE_KEY_NAME,
1233 &gEfiGlobalVariableGuid,
1234 &KekVariable,
1235 &mVariableModuleGlobal->VariableGlobal
1236 );
1237 if (EFI_ERROR (Status)) {
1238 return Status;
1239 }
1240
1241 //
1242 // Ready to verify Pkcs7 SignedData. Go through KEK Signature Database to find out X.509 CertList.
1243 //
1244 KekDataSize = KekVariable.CurrPtr->DataSize;
1245 CertList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (KekVariable.CurrPtr);
1246 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
1247 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
1248 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1249 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1250 for (Index = 0; Index < CertCount; Index++) {
1251 //
1252 // Iterate each Signature Data Node within this CertList for a verify
1253 //
1254 RootCert = Cert->SignatureData;
1255 RootCertSize = CertList->SignatureSize;
1256
1257 //
1258 // Verify Pkcs7 SignedData via Pkcs7Verify library.
1259 //
1260 VerifyStatus = Pkcs7Verify (
1261 SigData,
1262 SigDataSize,
1263 RootCert,
1264 RootCertSize,
1265 NewData,
1266 NewDataSize
1267 );
1268 if (VerifyStatus) {
1269 goto Exit;
1270 }
1271 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
1272 }
1273 }
1274 KekDataSize -= CertList->SignatureListSize;
1275 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1276 }
1277 }
1278
1279 Exit:
1280
1281 FreePool (NewData);
1282
1283 if (!VerifyStatus) {
1284 return EFI_SECURITY_VIOLATION;
1285 }
1286
1287 if ((PayLoadSize == 0) && (VarDel != NULL)) {
1288 *VarDel = TRUE;
1289 }
1290
1291 //
1292 // Final step: Update/Append Variable if it pass Pkcs7Verify
1293 //
1294 return UpdateVariable (
1295 VariableName,
1296 VendorGuid,
1297 PayLoadPtr,
1298 PayLoadSize,
1299 Attributes,
1300 0,
1301 0,
1302 Variable,
1303 &CertData->TimeStamp
1304 );
1305 }