2 Implement authentication services for the authenticated variable
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
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.
17 #include "AuthService.h"
20 /// Global database array for scratch
22 UINT8 mPubKeyStore
[MAX_KEYDB_SIZE
];
25 EFI_GUID mSignatureSupport
[] = {EFI_CERT_SHA1_GUID
, EFI_CERT_SHA256_GUID
, EFI_CERT_RSA2048_GUID
, EFI_CERT_X509_GUID
};
27 // Public Exponent of RSA Key.
29 CONST UINT8 mRsaE
[] = { 0x01, 0x00, 0x01 };
31 // Hash context pointer
33 VOID
*mHashCtx
= NULL
;
36 // Pointer to runtime buffer.
37 // For "Append" operation to an existing variable, a read/modify/write operation
38 // is supported by firmware internally. Reserve runtime buffer to cache previous
39 // variable data in runtime phase because memory allocation is forbidden in virtual mode.
41 VOID
*mStorageArea
= NULL
;
44 // The serialization of the values of the VariableName, VendorGuid and Attributes
45 // parameters of the SetVariable() call and the TimeStamp component of the
46 // EFI_VARIABLE_AUTHENTICATION_2 descriptor followed by the variable's new value
47 // i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data)
49 UINT8
*mSerializationRuntimeBuffer
= NULL
;
52 // Requirement for different signature type which have been defined in UEFI spec.
53 // These data are used to peform SignatureList format check while setting PK/KEK variable.
55 EFI_SIGNATURE_ITEM mSupportSigItem
[] = {
56 //{SigType, SigHeaderSize, SigDataSize }
57 {EFI_CERT_SHA256_GUID
, 0, 32 },
58 {EFI_CERT_RSA2048_GUID
, 0, 256 },
59 {EFI_CERT_RSA2048_SHA256_GUID
, 0, 256 },
60 {EFI_CERT_SHA1_GUID
, 0, 20 },
61 {EFI_CERT_RSA2048_SHA1_GUID
, 0, 256 },
62 {EFI_CERT_X509_GUID
, 0, ((UINT32
) ~0)},
63 {EFI_CERT_SHA224_GUID
, 0, 28 },
64 {EFI_CERT_SHA384_GUID
, 0, 48 },
65 {EFI_CERT_SHA512_GUID
, 0, 64 }
69 Internal function to delete a Variable given its name and GUID, no authentication
72 @param[in] VariableName Name of the Variable.
73 @param[in] VendorGuid GUID of the Variable.
75 @retval EFI_SUCCESS Variable deleted successfully.
76 @retval Others The driver failded to start the device.
81 IN CHAR16
*VariableName
,
82 IN EFI_GUID
*VendorGuid
86 VARIABLE_POINTER_TRACK Variable
;
88 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
89 if (EFI_ERROR (Status
)) {
93 ASSERT (Variable
.CurrPtr
!= NULL
);
94 return UpdateVariable (VariableName
, VendorGuid
, NULL
, 0, 0, 0, 0, &Variable
, NULL
);
98 Initializes for authenticated varibale service.
100 @retval EFI_SUCCESS Function successfully executed.
101 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resources.
105 AutenticatedVariableServiceInitialize (
110 VARIABLE_POINTER_TRACK Variable
;
111 VARIABLE_POINTER_TRACK PkVariable
;
117 UINT8 SecureBootMode
;
118 UINT8 SecureBootEnable
;
121 // Initialize hash context.
123 CtxSize
= Sha256GetContextSize ();
124 mHashCtx
= AllocateRuntimePool (CtxSize
);
125 if (mHashCtx
== NULL
) {
126 return EFI_OUT_OF_RESOURCES
;
130 // Reserved runtime buffer for "Append" operation in virtual mode.
132 mStorageArea
= AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize
));
133 if (mStorageArea
== NULL
) {
134 return EFI_OUT_OF_RESOURCES
;
138 // Prepare runtime buffer for serialized data of time-based authenticated
139 // Variable, i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data).
141 mSerializationRuntimeBuffer
= AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize
) + sizeof (EFI_GUID
) + sizeof (UINT32
) + sizeof (EFI_TIME
));
142 if (mSerializationRuntimeBuffer
== NULL
) {
143 return EFI_OUT_OF_RESOURCES
;
147 // Check "AuthVarKeyDatabase" variable's existence.
148 // If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
150 Status
= FindVariable (
152 &gEfiAuthenticatedVariableGuid
,
154 &mVariableModuleGlobal
->VariableGlobal
157 if (Variable
.CurrPtr
== NULL
) {
158 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
161 Status
= UpdateVariable (
163 &gEfiAuthenticatedVariableGuid
,
172 if (EFI_ERROR (Status
)) {
177 // Load database in global variable for cache.
179 DataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
180 Data
= GetVariableDataPtr (Variable
.CurrPtr
);
181 ASSERT ((DataSize
!= 0) && (Data
!= NULL
));
182 CopyMem (mPubKeyStore
, (UINT8
*) Data
, DataSize
);
183 mPubKeyNumber
= (UINT32
) (DataSize
/ EFI_CERT_TYPE_RSA2048_SIZE
);
186 FindVariable (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, &PkVariable
, &mVariableModuleGlobal
->VariableGlobal
);
187 if (PkVariable
.CurrPtr
== NULL
) {
188 DEBUG ((EFI_D_INFO
, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME
));
190 DEBUG ((EFI_D_INFO
, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME
));
194 // Check "SetupMode" variable's existence.
195 // If it doesn't exist, check PK database's existence to determine the value.
196 // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
198 Status
= FindVariable (
200 &gEfiGlobalVariableGuid
,
202 &mVariableModuleGlobal
->VariableGlobal
205 if (Variable
.CurrPtr
== NULL
) {
206 if (PkVariable
.CurrPtr
== NULL
) {
207 mPlatformMode
= SETUP_MODE
;
209 mPlatformMode
= USER_MODE
;
212 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
213 Status
= UpdateVariable (
215 &gEfiGlobalVariableGuid
,
224 if (EFI_ERROR (Status
)) {
228 mPlatformMode
= *(GetVariableDataPtr (Variable
.CurrPtr
));
231 // Check "SignatureSupport" variable's existence.
232 // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
234 Status
= FindVariable (
235 EFI_SIGNATURE_SUPPORT_NAME
,
236 &gEfiGlobalVariableGuid
,
238 &mVariableModuleGlobal
->VariableGlobal
241 if (Variable
.CurrPtr
== NULL
) {
242 VarAttr
= EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
243 Status
= UpdateVariable (
244 EFI_SIGNATURE_SUPPORT_NAME
,
245 &gEfiGlobalVariableGuid
,
247 sizeof(mSignatureSupport
),
257 // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.
258 // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
259 // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.
261 SecureBootEnable
= SECURE_BOOT_MODE_DISABLE
;
262 FindVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
263 if (Variable
.CurrPtr
!= NULL
) {
264 SecureBootEnable
= *(GetVariableDataPtr (Variable
.CurrPtr
));
265 } else if (mPlatformMode
== USER_MODE
) {
267 // "SecureBootEnable" not exist, initialize it in USER_MODE.
269 SecureBootEnable
= SECURE_BOOT_MODE_ENABLE
;
270 Status
= UpdateVariable (
271 EFI_SECURE_BOOT_ENABLE_NAME
,
272 &gEfiSecureBootEnableDisableGuid
,
275 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
281 if (EFI_ERROR (Status
)) {
286 if (SecureBootEnable
== SECURE_BOOT_ENABLE
&& mPlatformMode
== USER_MODE
) {
287 SecureBootMode
= SECURE_BOOT_MODE_ENABLE
;
289 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
291 FindVariable (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
292 Status
= UpdateVariable (
293 EFI_SECURE_BOOT_MODE_NAME
,
294 &gEfiGlobalVariableGuid
,
297 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
,
303 if (EFI_ERROR (Status
)) {
307 DEBUG ((EFI_D_INFO
, "Variable %s is %x\n", EFI_SETUP_MODE_NAME
, mPlatformMode
));
308 DEBUG ((EFI_D_INFO
, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME
, SecureBootMode
));
309 DEBUG ((EFI_D_INFO
, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME
, SecureBootEnable
));
312 // Detect whether a secure platform-specific method to clear PK(Platform Key)
313 // is configured by platform owner. This method is provided for users force to clear PK
314 // in case incorrect enrollment mis-haps.
316 if (ForceClearPK ()) {
317 DEBUG ((EFI_D_INFO
, "Variable PK/KEK/DB/DBX will be cleared in clear PK mode.\n"));
322 Status
= DeleteVariable (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
);
323 if (EFI_ERROR (Status
)) {
328 // 2. Update "SetupMode" variable to SETUP_MODE.
330 UpdatePlatformMode (SETUP_MODE
);
333 // 3. Clear KEK, DB and DBX.
335 DeleteVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
);
336 DeleteVariable (EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
);
337 DeleteVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
);
344 Add public key in store and return its index.
346 @param[in] PubKey Input pointer to Public Key data
348 @return Index of new added item
359 VARIABLE_POINTER_TRACK Variable
;
362 if (PubKey
== NULL
) {
366 Status
= FindVariable (
368 &gEfiAuthenticatedVariableGuid
,
370 &mVariableModuleGlobal
->VariableGlobal
372 ASSERT_EFI_ERROR (Status
);
374 // Check whether the public key entry does exist.
377 for (Ptr
= mPubKeyStore
, Index
= 1; Index
<= mPubKeyNumber
; Index
++) {
378 if (CompareMem (Ptr
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
382 Ptr
+= EFI_CERT_TYPE_RSA2048_SIZE
;
387 // Add public key in database.
389 if (mPubKeyNumber
== MAX_KEY_NUM
) {
391 // Notes: Database is full, need enhancement here, currently just return 0.
396 CopyMem (mPubKeyStore
+ mPubKeyNumber
* EFI_CERT_TYPE_RSA2048_SIZE
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
397 Index
= ++mPubKeyNumber
;
399 // Update public key database variable.
401 Status
= UpdateVariable (
403 &gEfiAuthenticatedVariableGuid
,
405 mPubKeyNumber
* EFI_CERT_TYPE_RSA2048_SIZE
,
406 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
,
412 ASSERT_EFI_ERROR (Status
);
419 Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256_GUID type.
420 Follow the steps in UEFI2.2.
422 @param[in] Data Pointer to data with AuthInfo.
423 @param[in] DataSize Size of Data.
424 @param[in] PubKey Public key used for verification.
426 @retval EFI_INVALID_PARAMETER Invalid parameter.
427 @retval EFI_SECURITY_VIOLATION If authentication failed.
428 @retval EFI_SUCCESS Authentication successful.
432 VerifyCounterBasedPayload (
439 EFI_VARIABLE_AUTHENTICATION
*CertData
;
440 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
441 UINT8 Digest
[SHA256_DIGEST_SIZE
];
448 if (Data
== NULL
|| PubKey
== NULL
) {
449 return EFI_INVALID_PARAMETER
;
452 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
453 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
456 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
457 // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256_GUID.
459 if ((CertData
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) ||
460 !CompareGuid (&CertData
->AuthInfo
.CertType
, &gEfiCertTypeRsa2048Sha256Guid
)
463 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
465 return EFI_SECURITY_VIOLATION
;
468 // Hash data payload with SHA256.
470 ZeroMem (Digest
, SHA256_DIGEST_SIZE
);
471 Status
= Sha256Init (mHashCtx
);
475 Status
= Sha256Update (mHashCtx
, Data
+ AUTHINFO_SIZE
, (UINTN
) (DataSize
- AUTHINFO_SIZE
));
480 // Hash Monotonic Count.
482 Status
= Sha256Update (mHashCtx
, &CertData
->MonotonicCount
, sizeof (UINT64
));
486 Status
= Sha256Final (mHashCtx
, Digest
);
491 // Generate & Initialize RSA Context.
494 ASSERT (Rsa
!= NULL
);
496 // Set RSA Key Components.
497 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
499 Status
= RsaSetKey (Rsa
, RsaKeyN
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
503 Status
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
508 // Verify the signature.
510 Status
= RsaPkcs1Verify (
514 CertBlock
->Signature
,
515 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
525 return EFI_SECURITY_VIOLATION
;
530 Update platform mode.
532 @param[in] Mode SETUP_MODE or USER_MODE.
534 @return EFI_INVALID_PARAMETER Invalid parameter.
535 @return EFI_SUCCESS Update platform mode successfully.
544 VARIABLE_POINTER_TRACK Variable
;
546 UINT8 SecureBootMode
;
547 UINT8 SecureBootEnable
;
548 UINTN VariableDataSize
;
550 Status
= FindVariable (
552 &gEfiGlobalVariableGuid
,
554 &mVariableModuleGlobal
->VariableGlobal
556 if (EFI_ERROR (Status
)) {
560 mPlatformMode
= Mode
;
561 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
562 Status
= UpdateVariable (
564 &gEfiGlobalVariableGuid
,
573 if (EFI_ERROR (Status
)) {
579 // SecureBoot Variable indicates whether the platform firmware is operating
580 // in Secure boot mode (1) or not (0), so we should not change SecureBoot
581 // Variable in runtime.
587 // Check "SecureBoot" variable's existence.
588 // If it doesn't exist, firmware has no capability to perform driver signing verification,
589 // then set "SecureBoot" to 0.
591 Status
= FindVariable (
592 EFI_SECURE_BOOT_MODE_NAME
,
593 &gEfiGlobalVariableGuid
,
595 &mVariableModuleGlobal
->VariableGlobal
598 // If "SecureBoot" variable exists, then check "SetupMode" variable update.
599 // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1.
600 // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0.
602 if (Variable
.CurrPtr
== NULL
) {
603 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
605 if (mPlatformMode
== USER_MODE
) {
606 SecureBootMode
= SECURE_BOOT_MODE_ENABLE
;
607 } else if (mPlatformMode
== SETUP_MODE
) {
608 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
610 return EFI_NOT_FOUND
;
614 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
615 Status
= UpdateVariable (
616 EFI_SECURE_BOOT_MODE_NAME
,
617 &gEfiGlobalVariableGuid
,
626 if (EFI_ERROR (Status
)) {
631 // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature.
633 Status
= FindVariable (
634 EFI_SECURE_BOOT_ENABLE_NAME
,
635 &gEfiSecureBootEnableDisableGuid
,
637 &mVariableModuleGlobal
->VariableGlobal
640 if (SecureBootMode
== SECURE_BOOT_MODE_ENABLE
) {
642 // Create the "SecureBootEnable" variable as secure boot is enabled.
644 SecureBootEnable
= SECURE_BOOT_ENABLE
;
645 VariableDataSize
= sizeof (SecureBootEnable
);
648 // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot"
649 // variable is not in secure boot state.
651 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
654 SecureBootEnable
= SECURE_BOOT_DISABLE
;
655 VariableDataSize
= 0;
658 Status
= UpdateVariable (
659 EFI_SECURE_BOOT_ENABLE_NAME
,
660 &gEfiSecureBootEnableDisableGuid
,
663 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
673 Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK variable.
675 @param[in] VariableName Name of Variable to be check.
676 @param[in] VendorGuid Variable vendor GUID.
677 @param[in] Data Point to the variable data to be checked.
678 @param[in] DataSize Size of Data.
680 @return EFI_INVALID_PARAMETER Invalid signature list format.
681 @return EFI_SUCCESS Passed signature list format check successfully.
685 CheckSignatureListFormat(
686 IN CHAR16
*VariableName
,
687 IN EFI_GUID
*VendorGuid
,
692 EFI_SIGNATURE_LIST
*SigList
;
702 ASSERT (VariableName
!= NULL
&& VendorGuid
!= NULL
&& Data
!= NULL
);
704 if (CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
) && (StrCmp (VariableName
, EFI_PLATFORM_KEY_NAME
) == 0)){
706 } else if (CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
) && (StrCmp (VariableName
, EFI_KEY_EXCHANGE_KEY_NAME
) == 0)) {
713 SigList
= (EFI_SIGNATURE_LIST
*) Data
;
714 SigDataSize
= DataSize
;
717 // Walk throuth the input signature list and check the data format.
718 // If any signature is incorrectly formed, the whole check will fail.
720 while ((SigDataSize
> 0) && (SigDataSize
>= SigList
->SignatureListSize
)) {
721 for (Index
= 0; Index
< (sizeof (mSupportSigItem
) / sizeof (EFI_SIGNATURE_ITEM
)); Index
++ ) {
722 if (CompareGuid (&SigList
->SignatureType
, &mSupportSigItem
[Index
].SigType
)) {
724 // The value of SignatureSize should always be 16 (size of SignatureOwner
725 // component) add the data length according to signature type.
727 if (mSupportSigItem
[Index
].SigDataSize
!= ((UINT32
) ~0) &&
728 (SigList
->SignatureSize
- sizeof (EFI_GUID
)) != mSupportSigItem
[Index
].SigDataSize
) {
729 return EFI_INVALID_PARAMETER
;
731 if (mSupportSigItem
[Index
].SigHeaderSize
!= ((UINTN
) ~0) &&
732 SigList
->SignatureHeaderSize
!= mSupportSigItem
[Index
].SigHeaderSize
) {
733 return EFI_INVALID_PARAMETER
;
739 if (Index
== (sizeof (mSupportSigItem
) / sizeof (EFI_SIGNATURE_ITEM
))) {
741 // Undefined signature type.
743 return EFI_INVALID_PARAMETER
;
746 if ((SigList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - SigList
->SignatureHeaderSize
) % SigList
->SignatureSize
!= 0) {
747 return EFI_INVALID_PARAMETER
;
749 SigCount
+= (SigList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - SigList
->SignatureHeaderSize
) / SigList
->SignatureSize
;
751 SigDataSize
-= SigList
->SignatureListSize
;
752 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
755 if (((UINTN
) SigList
- (UINTN
) Data
) != DataSize
) {
756 return EFI_INVALID_PARAMETER
;
759 if (IsPk
&& SigCount
> 1) {
760 return EFI_INVALID_PARAMETER
;
767 Process variable with platform key for verification.
769 @param[in] VariableName Name of Variable to be found.
770 @param[in] VendorGuid Variable vendor GUID.
771 @param[in] Data Data pointer.
772 @param[in] DataSize Size of Data found. If size is less than the
773 data, this value contains the required size.
774 @param[in] Variable The variable information which is used to keep track of variable usage.
775 @param[in] Attributes Attribute value of the variable
776 @param[in] IsPk Indicate whether it is to process pk.
778 @return EFI_INVALID_PARAMETER Invalid parameter.
779 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
780 check carried out by the firmware.
781 @return EFI_SUCCESS Variable passed validation successfully.
786 IN CHAR16
*VariableName
,
787 IN EFI_GUID
*VendorGuid
,
790 IN VARIABLE_POINTER_TRACK
*Variable
,
791 IN UINT32 Attributes OPTIONAL
,
796 VARIABLE_POINTER_TRACK PkVariable
;
797 EFI_SIGNATURE_LIST
*OldPkList
;
798 EFI_SIGNATURE_DATA
*OldPkData
;
799 EFI_VARIABLE_AUTHENTICATION
*CertData
;
804 UINT64 MonotonicCount
;
807 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
809 // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
811 return EFI_INVALID_PARAMETER
;
814 if (mPlatformMode
== USER_MODE
) {
816 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
818 // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute means time-based X509 Cert PK.
821 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
823 // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute means counter-based RSA-2048 Cert PK.
827 return EFI_INVALID_PARAMETER
;
832 // Verify against X509 Cert PK.
835 Status
= VerifyTimeBasedPayload (VariableName
, VendorGuid
, Data
, DataSize
, Variable
, Attributes
, TRUE
, &Del
);
836 if (!EFI_ERROR (Status
)) {
838 // If delete PK in user mode, need change to setup mode.
841 Status
= UpdatePlatformMode (SETUP_MODE
);
847 // Verify against RSA2048 Cert PK.
849 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
850 if ((Variable
->CurrPtr
!= NULL
) && (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
)) {
852 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
854 return EFI_SECURITY_VIOLATION
;
857 // Get platform key from variable.
859 Status
= FindVariable (
860 EFI_PLATFORM_KEY_NAME
,
861 &gEfiGlobalVariableGuid
,
863 &mVariableModuleGlobal
->VariableGlobal
865 ASSERT_EFI_ERROR (Status
);
867 OldPkList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (PkVariable
.CurrPtr
);
868 OldPkData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) OldPkList
+ sizeof (EFI_SIGNATURE_LIST
) + OldPkList
->SignatureHeaderSize
);
869 Status
= VerifyCounterBasedPayload (Data
, DataSize
, OldPkData
->SignatureData
);
870 if (!EFI_ERROR (Status
)) {
871 Status
= CheckSignatureListFormat(
874 (UINT8
*)Data
+ AUTHINFO_SIZE
,
875 DataSize
- AUTHINFO_SIZE
);
876 if (EFI_ERROR (Status
)) {
880 Status
= UpdateVariable (
883 (UINT8
*)Data
+ AUTHINFO_SIZE
,
884 DataSize
- AUTHINFO_SIZE
,
887 CertData
->MonotonicCount
,
892 if (!EFI_ERROR (Status
)) {
894 // If delete PK in user mode, need change to setup mode.
896 if ((DataSize
== AUTHINFO_SIZE
) && IsPk
) {
897 Status
= UpdatePlatformMode (SETUP_MODE
);
904 // Process PK or KEK in Setup mode.
906 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
908 // Time-based Authentication descriptor.
911 TimeStamp
= &((EFI_VARIABLE_AUTHENTICATION_2
*) Data
)->TimeStamp
;
912 Payload
= (UINT8
*) Data
+ AUTHINFO2_SIZE (Data
);
913 PayloadSize
= DataSize
- AUTHINFO2_SIZE (Data
);
914 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
916 // Counter-based Authentication descriptor.
918 MonotonicCount
= ((EFI_VARIABLE_AUTHENTICATION
*) Data
)->MonotonicCount
;
920 Payload
= (UINT8
*) Data
+ AUTHINFO_SIZE
;
921 PayloadSize
= DataSize
- AUTHINFO_SIZE
;
924 // No Authentication descriptor.
929 PayloadSize
= DataSize
;
932 Status
= CheckSignatureListFormat(VariableName
, VendorGuid
, Payload
, PayloadSize
);
933 if (EFI_ERROR (Status
)) {
937 Status
= UpdateVariable (
949 // If enroll PK in setup mode, need change to user mode.
951 if ((DataSize
!= 0) && IsPk
) {
952 Status
= UpdatePlatformMode (USER_MODE
);
960 Process variable with key exchange key for verification.
962 @param[in] VariableName Name of Variable to be found.
963 @param[in] VendorGuid Variable vendor GUID.
964 @param[in] Data Data pointer.
965 @param[in] DataSize Size of Data found. If size is less than the
966 data, this value contains the required size.
967 @param[in] Variable The variable information which is used to keep track of variable usage.
968 @param[in] Attributes Attribute value of the variable.
970 @return EFI_INVALID_PARAMETER Invalid parameter.
971 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation
972 check carried out by the firmware.
973 @return EFI_SUCCESS Variable pass validation successfully.
978 IN CHAR16
*VariableName
,
979 IN EFI_GUID
*VendorGuid
,
982 IN VARIABLE_POINTER_TRACK
*Variable
,
983 IN UINT32 Attributes OPTIONAL
987 VARIABLE_POINTER_TRACK KekVariable
;
988 EFI_SIGNATURE_LIST
*KekList
;
989 EFI_SIGNATURE_DATA
*KekItem
;
991 EFI_VARIABLE_AUTHENTICATION
*CertData
;
992 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
998 UINT64 MonotonicCount
;
1000 if (mPlatformMode
== USER_MODE
) {
1001 if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) == 0) {
1003 // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
1005 return EFI_INVALID_PARAMETER
;
1008 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
1009 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
1010 if ((Variable
->CurrPtr
!= NULL
) && (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
)) {
1012 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1014 return EFI_SECURITY_VIOLATION
;
1017 // Get KEK database from variable.
1019 Status
= FindVariable (
1020 EFI_KEY_EXCHANGE_KEY_NAME
,
1021 &gEfiGlobalVariableGuid
,
1023 &mVariableModuleGlobal
->VariableGlobal
1025 ASSERT_EFI_ERROR (Status
);
1027 KekDataSize
= KekVariable
.CurrPtr
->DataSize
;
1028 KekList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (KekVariable
.CurrPtr
);
1031 // Enumerate all Kek items in this list to verify the variable certificate data.
1032 // If anyone is authenticated successfully, it means the variable is correct!
1035 while ((KekDataSize
> 0) && (KekDataSize
>= KekList
->SignatureListSize
)) {
1036 if (CompareGuid (&KekList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1037 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekList
+ sizeof (EFI_SIGNATURE_LIST
) + KekList
->SignatureHeaderSize
);
1038 KekCount
= (KekList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - KekList
->SignatureHeaderSize
) / KekList
->SignatureSize
;
1039 for (Index
= 0; Index
< KekCount
; Index
++) {
1040 if (CompareMem (KekItem
->SignatureData
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
1044 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekItem
+ KekList
->SignatureSize
);
1047 KekDataSize
-= KekList
->SignatureListSize
;
1048 KekList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) KekList
+ KekList
->SignatureListSize
);
1052 return EFI_SECURITY_VIOLATION
;
1055 Status
= VerifyCounterBasedPayload (Data
, DataSize
, CertBlock
->PublicKey
);
1056 if (!EFI_ERROR (Status
)) {
1057 Status
= UpdateVariable (
1060 (UINT8
*)Data
+ AUTHINFO_SIZE
,
1061 DataSize
- AUTHINFO_SIZE
,
1064 CertData
->MonotonicCount
,
1071 // If in setup mode, no authentication needed.
1073 if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1075 // Counter-based Authentication descriptor.
1077 MonotonicCount
= ((EFI_VARIABLE_AUTHENTICATION
*) Data
)->MonotonicCount
;
1078 Payload
= (UINT8
*) Data
+ AUTHINFO_SIZE
;
1079 PayloadSize
= DataSize
- AUTHINFO_SIZE
;
1082 // No Authentication descriptor.
1086 PayloadSize
= DataSize
;
1089 Status
= UpdateVariable (
1106 Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
1108 @param[in] VariableName Name of Variable to be found.
1109 @param[in] VendorGuid Variable vendor GUID.
1111 @param[in] Data Data pointer.
1112 @param[in] DataSize Size of Data found. If size is less than the
1113 data, this value contains the required size.
1114 @param[in] Variable The variable information which is used to keep track of variable usage.
1115 @param[in] Attributes Attribute value of the variable.
1117 @return EFI_INVALID_PARAMETER Invalid parameter.
1118 @return EFI_WRITE_PROTECTED Variable is write-protected and needs authentication with
1119 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
1120 @return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
1121 set, but the AuthInfo does NOT pass the validation
1122 check carried out by the firmware.
1123 @return EFI_SUCCESS Variable is not write-protected or pass validation successfully.
1128 IN CHAR16
*VariableName
,
1129 IN EFI_GUID
*VendorGuid
,
1132 IN VARIABLE_POINTER_TRACK
*Variable
,
1133 IN UINT32 Attributes
1138 BOOLEAN IsFirstTime
;
1140 EFI_VARIABLE_AUTHENTICATION
*CertData
;
1141 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
1143 UINT64 MonotonicCount
;
1152 // Process Time-based Authenticated variable.
1154 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1155 return VerifyTimeBasedPayload (VariableName
, VendorGuid
, Data
, DataSize
, Variable
, Attributes
, FALSE
, NULL
);
1159 // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.
1161 if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1163 // Determine current operation type.
1165 if (DataSize
== AUTHINFO_SIZE
) {
1169 // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
1171 if (Variable
->CurrPtr
== NULL
) {
1173 } else if ((Variable
->CurrPtr
->Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) == 0) {
1176 KeyIndex
= Variable
->CurrPtr
->PubKeyIndex
;
1177 IsFirstTime
= FALSE
;
1179 } else if ((Variable
->CurrPtr
!= NULL
) &&
1180 (Variable
->CurrPtr
->Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0
1183 // If the variable is already write-protected, it always needs authentication before update.
1185 return EFI_WRITE_PROTECTED
;
1188 // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.
1189 // That means it is not authenticated variable, just update variable as usual.
1191 Status
= UpdateVariable (VariableName
, VendorGuid
, Data
, DataSize
, Attributes
, 0, 0, Variable
, NULL
);
1196 // Get PubKey and check Monotonic Count value corresponding to the variable.
1198 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
1199 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
1200 PubKey
= CertBlock
->PublicKey
;
1203 // Update Monotonic Count value.
1205 MonotonicCount
= CertData
->MonotonicCount
;
1209 // Check input PubKey.
1211 if (CompareMem (PubKey
, mPubKeyStore
+ (KeyIndex
- 1) * EFI_CERT_TYPE_RSA2048_SIZE
, EFI_CERT_TYPE_RSA2048_SIZE
) != 0) {
1212 return EFI_SECURITY_VIOLATION
;
1215 // Compare the current monotonic count and ensure that it is greater than the last SetVariable
1216 // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.
1218 if (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
) {
1220 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1222 return EFI_SECURITY_VIOLATION
;
1226 // Verify the certificate in Data payload.
1228 Status
= VerifyCounterBasedPayload (Data
, DataSize
, PubKey
);
1229 if (EFI_ERROR (Status
)) {
1234 // Now, the signature has been verified!
1236 if (IsFirstTime
&& !IsDeletion
) {
1238 // Update public key database variable if need.
1240 KeyIndex
= AddPubKeyInStore (PubKey
);
1244 // Verification pass.
1246 return UpdateVariable (VariableName
, VendorGuid
, (UINT8
*)Data
+ AUTHINFO_SIZE
, DataSize
- AUTHINFO_SIZE
, Attributes
, KeyIndex
, MonotonicCount
, Variable
, NULL
);
1250 Merge two buffers which formatted as EFI_SIGNATURE_LIST. Only the new EFI_SIGNATURE_DATA
1251 will be appended to the original EFI_SIGNATURE_LIST, duplicate EFI_SIGNATURE_DATA
1254 @param[in, out] Data Pointer to original EFI_SIGNATURE_LIST.
1255 @param[in] DataSize Size of Data buffer.
1256 @param[in] NewData Pointer to new EFI_SIGNATURE_LIST to be appended.
1257 @param[in] NewDataSize Size of NewData buffer.
1259 @return Size of the merged buffer.
1263 AppendSignatureList (
1267 IN UINTN NewDataSize
1270 EFI_SIGNATURE_LIST
*CertList
;
1271 EFI_SIGNATURE_DATA
*Cert
;
1273 EFI_SIGNATURE_LIST
*NewCertList
;
1274 EFI_SIGNATURE_DATA
*NewCert
;
1281 UINTN SignatureListSize
;
1284 Tail
= (UINT8
*) Data
+ DataSize
;
1286 NewCertList
= (EFI_SIGNATURE_LIST
*) NewData
;
1287 while ((NewDataSize
> 0) && (NewDataSize
>= NewCertList
->SignatureListSize
)) {
1288 NewCert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) NewCertList
+ sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
);
1289 NewCertCount
= (NewCertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - NewCertList
->SignatureHeaderSize
) / NewCertList
->SignatureSize
;
1292 for (Index
= 0; Index
< NewCertCount
; Index
++) {
1296 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1297 while ((Size
> 0) && (Size
>= CertList
->SignatureListSize
)) {
1298 if (CompareGuid (&CertList
->SignatureType
, &NewCertList
->SignatureType
) &&
1299 (CertList
->SignatureSize
== NewCertList
->SignatureSize
)) {
1300 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1301 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1302 for (Index2
= 0; Index2
< CertCount
; Index2
++) {
1304 // Iterate each Signature Data in this Signature List.
1306 if (CompareMem (NewCert
, Cert
, CertList
->SignatureSize
) == 0) {
1310 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1317 Size
-= CertList
->SignatureListSize
;
1318 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1323 // New EFI_SIGNATURE_DATA, append it.
1325 if (CopiedCount
== 0) {
1327 // Copy EFI_SIGNATURE_LIST header for only once.
1329 CopyMem (Tail
, NewCertList
, sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
);
1330 Tail
= Tail
+ sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
;
1333 CopyMem (Tail
, NewCert
, NewCertList
->SignatureSize
);
1334 Tail
+= NewCertList
->SignatureSize
;
1338 NewCert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) NewCert
+ NewCertList
->SignatureSize
);
1342 // Update SignatureListSize in newly appended EFI_SIGNATURE_LIST.
1344 if (CopiedCount
!= 0) {
1345 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
+ (CopiedCount
* NewCertList
->SignatureSize
);
1346 CertList
= (EFI_SIGNATURE_LIST
*) (Tail
- SignatureListSize
);
1347 CertList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1350 NewDataSize
-= NewCertList
->SignatureListSize
;
1351 NewCertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) NewCertList
+ NewCertList
->SignatureListSize
);
1354 return (Tail
- (UINT8
*) Data
);
1358 Compare two EFI_TIME data.
1361 @param FirstTime A pointer to the first EFI_TIME data.
1362 @param SecondTime A pointer to the second EFI_TIME data.
1364 @retval TRUE The FirstTime is not later than the SecondTime.
1365 @retval FALSE The FirstTime is later than the SecondTime.
1370 IN EFI_TIME
*FirstTime
,
1371 IN EFI_TIME
*SecondTime
1374 if (FirstTime
->Year
!= SecondTime
->Year
) {
1375 return (BOOLEAN
) (FirstTime
->Year
< SecondTime
->Year
);
1376 } else if (FirstTime
->Month
!= SecondTime
->Month
) {
1377 return (BOOLEAN
) (FirstTime
->Month
< SecondTime
->Month
);
1378 } else if (FirstTime
->Day
!= SecondTime
->Day
) {
1379 return (BOOLEAN
) (FirstTime
->Day
< SecondTime
->Day
);
1380 } else if (FirstTime
->Hour
!= SecondTime
->Hour
) {
1381 return (BOOLEAN
) (FirstTime
->Hour
< SecondTime
->Hour
);
1382 } else if (FirstTime
->Minute
!= SecondTime
->Minute
) {
1383 return (BOOLEAN
) (FirstTime
->Minute
< FirstTime
->Minute
);
1386 return (BOOLEAN
) (FirstTime
->Second
<= SecondTime
->Second
);
1390 Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
1392 @param[in] VariableName Name of Variable to be found.
1393 @param[in] VendorGuid Variable vendor GUID.
1394 @param[in] Data Data pointer.
1395 @param[in] DataSize Size of Data found. If size is less than the
1396 data, this value contains the required size.
1397 @param[in] Variable The variable information which is used to keep track of variable usage.
1398 @param[in] Attributes Attribute value of the variable.
1399 @param[in] Pk Verify against PK or KEK database.
1400 @param[out] VarDel Delete the variable or not.
1402 @retval EFI_INVALID_PARAMETER Invalid parameter.
1403 @retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
1404 check carried out by the firmware.
1405 @retval EFI_OUT_OF_RESOURCES Failed to process variable due to lack
1407 @retval EFI_SUCCESS Variable pass validation successfully.
1411 VerifyTimeBasedPayload (
1412 IN CHAR16
*VariableName
,
1413 IN EFI_GUID
*VendorGuid
,
1416 IN VARIABLE_POINTER_TRACK
*Variable
,
1417 IN UINT32 Attributes
,
1433 BOOLEAN VerifyStatus
;
1435 EFI_SIGNATURE_LIST
*CertList
;
1436 EFI_SIGNATURE_DATA
*Cert
;
1437 VARIABLE_POINTER_TRACK KekVariable
;
1438 EFI_VARIABLE_AUTHENTICATION_2
*CertData
;
1441 VARIABLE_POINTER_TRACK PkVariable
;
1446 VerifyStatus
= FALSE
;
1452 // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
1453 // set, then the Data buffer shall begin with an instance of a complete (and serialized)
1454 // EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new
1455 // variable value and DataSize shall reflect the combined size of the descriptor and the new
1456 // variable value. The authentication descriptor is not part of the variable data and is not
1457 // returned by subsequent calls to GetVariable().
1459 CertData
= (EFI_VARIABLE_AUTHENTICATION_2
*) Data
;
1462 // Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components of the
1463 // TimeStamp value are set to zero.
1465 if ((CertData
->TimeStamp
.Pad1
!= 0) ||
1466 (CertData
->TimeStamp
.Nanosecond
!= 0) ||
1467 (CertData
->TimeStamp
.TimeZone
!= 0) ||
1468 (CertData
->TimeStamp
.Daylight
!= 0) ||
1469 (CertData
->TimeStamp
.Pad2
!= 0)) {
1470 return EFI_SECURITY_VIOLATION
;
1473 if ((Variable
->CurrPtr
!= NULL
) && ((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0)) {
1474 if (CompareTimeStamp (&CertData
->TimeStamp
, &Variable
->CurrPtr
->TimeStamp
)) {
1476 // TimeStamp check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1478 return EFI_SECURITY_VIOLATION
;
1483 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
1484 // Cert type should be EFI_CERT_TYPE_PKCS7_GUID.
1486 if ((CertData
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) ||
1487 !CompareGuid (&CertData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
)) {
1489 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
1491 return EFI_SECURITY_VIOLATION
;
1495 // Find out Pkcs7 SignedData which follows the EFI_VARIABLE_AUTHENTICATION_2 descriptor.
1496 // AuthInfo.Hdr.dwLength is the length of the entire certificate, including the length of the header.
1498 SigData
= CertData
->AuthInfo
.CertData
;
1499 SigDataSize
= CertData
->AuthInfo
.Hdr
.dwLength
- (UINT32
) (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
));
1502 // Find out the new data payload which follows Pkcs7 SignedData directly.
1504 PayloadPtr
= SigData
+ SigDataSize
;
1505 PayloadSize
= DataSize
- OFFSET_OF_AUTHINFO2_CERT_DATA
- (UINTN
) SigDataSize
;
1508 // Construct a buffer to fill with (VariableName, VendorGuid, Attributes, TimeStamp, Data).
1510 NewDataSize
= PayloadSize
+ sizeof (EFI_TIME
) + sizeof (UINT32
) +
1511 sizeof (EFI_GUID
) + StrSize (VariableName
) - sizeof (CHAR16
);
1512 NewData
= mSerializationRuntimeBuffer
;
1515 Length
= StrLen (VariableName
) * sizeof (CHAR16
);
1516 CopyMem (Buffer
, VariableName
, Length
);
1519 Length
= sizeof (EFI_GUID
);
1520 CopyMem (Buffer
, VendorGuid
, Length
);
1523 Length
= sizeof (UINT32
);
1524 CopyMem (Buffer
, &Attr
, Length
);
1527 Length
= sizeof (EFI_TIME
);
1528 CopyMem (Buffer
, &CertData
->TimeStamp
, Length
);
1531 CopyMem (Buffer
, PayloadPtr
, PayloadSize
);
1535 // Get platform key from variable.
1537 Status
= FindVariable (
1538 EFI_PLATFORM_KEY_NAME
,
1539 &gEfiGlobalVariableGuid
,
1541 &mVariableModuleGlobal
->VariableGlobal
1543 if (EFI_ERROR (Status
)) {
1547 CertList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (PkVariable
.CurrPtr
);
1548 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1549 RootCert
= Cert
->SignatureData
;
1550 RootCertSize
= CertList
->SignatureSize
;
1554 // Verify Pkcs7 SignedData via Pkcs7Verify library.
1556 VerifyStatus
= Pkcs7Verify (
1568 // Get KEK database from variable.
1570 Status
= FindVariable (
1571 EFI_KEY_EXCHANGE_KEY_NAME
,
1572 &gEfiGlobalVariableGuid
,
1574 &mVariableModuleGlobal
->VariableGlobal
1576 if (EFI_ERROR (Status
)) {
1581 // Ready to verify Pkcs7 SignedData. Go through KEK Signature Database to find out X.509 CertList.
1583 KekDataSize
= KekVariable
.CurrPtr
->DataSize
;
1584 CertList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (KekVariable
.CurrPtr
);
1585 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1586 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1587 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1588 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1589 for (Index
= 0; Index
< CertCount
; Index
++) {
1591 // Iterate each Signature Data Node within this CertList for a verify
1593 RootCert
= Cert
->SignatureData
;
1594 RootCertSize
= CertList
->SignatureSize
;
1597 // Verify Pkcs7 SignedData via Pkcs7Verify library.
1599 VerifyStatus
= Pkcs7Verify (
1610 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1613 KekDataSize
-= CertList
->SignatureListSize
;
1614 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1620 if (!VerifyStatus
) {
1621 return EFI_SECURITY_VIOLATION
;
1624 Status
= CheckSignatureListFormat(VariableName
, VendorGuid
, PayloadPtr
, PayloadSize
);
1625 if (EFI_ERROR (Status
)) {
1629 if ((PayloadSize
== 0) && (VarDel
!= NULL
)) {
1634 // Final step: Update/Append Variable if it pass Pkcs7Verify
1636 return UpdateVariable (
1645 &CertData
->TimeStamp