2 Implement authentication services for the authenticated variable
5 Copyright (c) 2009 - 2012, 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 Determine whether this operation needs a physical present user.
71 @param[in] VariableName Name of the Variable.
72 @param[in] VendorGuid GUID of the Variable.
74 @retval TRUE This variable is protected, only a physical present user could set this variable.
75 @retval FALSE This variable is not protected.
79 NeedPhysicallyPresent(
80 IN CHAR16
*VariableName
,
81 IN EFI_GUID
*VendorGuid
84 if ((CompareGuid (VendorGuid
, &gEfiSecureBootEnableDisableGuid
) && (StrCmp (VariableName
, EFI_SECURE_BOOT_ENABLE_NAME
) == 0))
85 || (CompareGuid (VendorGuid
, &gEfiCustomModeEnableGuid
) && (StrCmp (VariableName
, EFI_CUSTOM_MODE_NAME
) == 0))) {
93 Determine whether the platform is operating in Custom Secure Boot mode.
95 @retval TRUE The platform is operating in Custom mode.
96 @retval FALSE The platform is operating in Standard mode.
104 VARIABLE_POINTER_TRACK Variable
;
106 FindVariable (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
107 if (Variable
.CurrPtr
!= NULL
&& *(GetVariableDataPtr (Variable
.CurrPtr
)) == CUSTOM_SECURE_BOOT_MODE
) {
116 Internal function to delete a Variable given its name and GUID, no authentication
119 @param[in] VariableName Name of the Variable.
120 @param[in] VendorGuid GUID of the Variable.
122 @retval EFI_SUCCESS Variable deleted successfully.
123 @retval Others The driver failded to start the device.
128 IN CHAR16
*VariableName
,
129 IN EFI_GUID
*VendorGuid
133 VARIABLE_POINTER_TRACK Variable
;
135 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
136 if (EFI_ERROR (Status
)) {
140 ASSERT (Variable
.CurrPtr
!= NULL
);
141 return UpdateVariable (VariableName
, VendorGuid
, NULL
, 0, 0, 0, 0, &Variable
, NULL
);
145 Initializes for authenticated varibale service.
147 @retval EFI_SUCCESS Function successfully executed.
148 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resources.
152 AutenticatedVariableServiceInitialize (
157 VARIABLE_POINTER_TRACK Variable
;
158 VARIABLE_POINTER_TRACK PkVariable
;
164 UINT8 SecureBootMode
;
165 UINT8 SecureBootEnable
;
169 // Initialize hash context.
171 CtxSize
= Sha256GetContextSize ();
172 mHashCtx
= AllocateRuntimePool (CtxSize
);
173 if (mHashCtx
== NULL
) {
174 return EFI_OUT_OF_RESOURCES
;
178 // Reserved runtime buffer for "Append" operation in virtual mode.
180 mStorageArea
= AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize
));
181 if (mStorageArea
== NULL
) {
182 return EFI_OUT_OF_RESOURCES
;
186 // Prepare runtime buffer for serialized data of time-based authenticated
187 // Variable, i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data).
189 mSerializationRuntimeBuffer
= AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize
) + sizeof (EFI_GUID
) + sizeof (UINT32
) + sizeof (EFI_TIME
));
190 if (mSerializationRuntimeBuffer
== NULL
) {
191 return EFI_OUT_OF_RESOURCES
;
195 // Check "AuthVarKeyDatabase" variable's existence.
196 // If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
198 Status
= FindVariable (
200 &gEfiAuthenticatedVariableGuid
,
202 &mVariableModuleGlobal
->VariableGlobal
,
206 if (Variable
.CurrPtr
== NULL
) {
207 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
210 Status
= UpdateVariable (
212 &gEfiAuthenticatedVariableGuid
,
221 if (EFI_ERROR (Status
)) {
226 // Load database in global variable for cache.
228 DataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
229 Data
= GetVariableDataPtr (Variable
.CurrPtr
);
230 ASSERT ((DataSize
!= 0) && (Data
!= NULL
));
231 CopyMem (mPubKeyStore
, (UINT8
*) Data
, DataSize
);
232 mPubKeyNumber
= (UINT32
) (DataSize
/ EFI_CERT_TYPE_RSA2048_SIZE
);
235 FindVariable (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
, &PkVariable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
236 if (PkVariable
.CurrPtr
== NULL
) {
237 DEBUG ((EFI_D_INFO
, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME
));
239 DEBUG ((EFI_D_INFO
, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME
));
243 // Check "SetupMode" variable's existence.
244 // If it doesn't exist, check PK database's existence to determine the value.
245 // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
247 Status
= FindVariable (
249 &gEfiGlobalVariableGuid
,
251 &mVariableModuleGlobal
->VariableGlobal
,
255 if (Variable
.CurrPtr
== NULL
) {
256 if (PkVariable
.CurrPtr
== NULL
) {
257 mPlatformMode
= SETUP_MODE
;
259 mPlatformMode
= USER_MODE
;
262 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
263 Status
= UpdateVariable (
265 &gEfiGlobalVariableGuid
,
274 if (EFI_ERROR (Status
)) {
278 mPlatformMode
= *(GetVariableDataPtr (Variable
.CurrPtr
));
281 // Check "SignatureSupport" variable's existence.
282 // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
284 Status
= FindVariable (
285 EFI_SIGNATURE_SUPPORT_NAME
,
286 &gEfiGlobalVariableGuid
,
288 &mVariableModuleGlobal
->VariableGlobal
,
292 if (Variable
.CurrPtr
== NULL
) {
293 VarAttr
= EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
294 Status
= UpdateVariable (
295 EFI_SIGNATURE_SUPPORT_NAME
,
296 &gEfiGlobalVariableGuid
,
298 sizeof(mSignatureSupport
),
308 // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.
309 // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
310 // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.
312 SecureBootEnable
= SECURE_BOOT_MODE_DISABLE
;
313 FindVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
314 if (Variable
.CurrPtr
!= NULL
) {
315 SecureBootEnable
= *(GetVariableDataPtr (Variable
.CurrPtr
));
316 } else if (mPlatformMode
== USER_MODE
) {
318 // "SecureBootEnable" not exist, initialize it in USER_MODE.
320 SecureBootEnable
= SECURE_BOOT_MODE_ENABLE
;
321 Status
= UpdateVariable (
322 EFI_SECURE_BOOT_ENABLE_NAME
,
323 &gEfiSecureBootEnableDisableGuid
,
326 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
332 if (EFI_ERROR (Status
)) {
337 if (SecureBootEnable
== SECURE_BOOT_ENABLE
&& mPlatformMode
== USER_MODE
) {
338 SecureBootMode
= SECURE_BOOT_MODE_ENABLE
;
340 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
342 FindVariable (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
343 Status
= UpdateVariable (
344 EFI_SECURE_BOOT_MODE_NAME
,
345 &gEfiGlobalVariableGuid
,
348 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
,
354 if (EFI_ERROR (Status
)) {
358 DEBUG ((EFI_D_INFO
, "Variable %s is %x\n", EFI_SETUP_MODE_NAME
, mPlatformMode
));
359 DEBUG ((EFI_D_INFO
, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME
, SecureBootMode
));
360 DEBUG ((EFI_D_INFO
, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME
, SecureBootEnable
));
363 // Check "CustomMode" variable's existence.
365 FindVariable (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
, FALSE
);
366 if (Variable
.CurrPtr
!= NULL
) {
367 CustomMode
= *(GetVariableDataPtr (Variable
.CurrPtr
));
370 // "CustomMode" not exist, initialize it in STANDARD_SECURE_BOOT_MODE.
372 CustomMode
= STANDARD_SECURE_BOOT_MODE
;
373 Status
= UpdateVariable (
374 EFI_CUSTOM_MODE_NAME
,
375 &gEfiCustomModeEnableGuid
,
378 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
384 if (EFI_ERROR (Status
)) {
389 DEBUG ((EFI_D_INFO
, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME
, CustomMode
));
395 Add public key in store and return its index.
397 @param[in] PubKey Input pointer to Public Key data
399 @return Index of new added item
410 VARIABLE_POINTER_TRACK Variable
;
413 if (PubKey
== NULL
) {
417 Status
= FindVariable (
419 &gEfiAuthenticatedVariableGuid
,
421 &mVariableModuleGlobal
->VariableGlobal
,
424 ASSERT_EFI_ERROR (Status
);
426 // Check whether the public key entry does exist.
429 for (Ptr
= mPubKeyStore
, Index
= 1; Index
<= mPubKeyNumber
; Index
++) {
430 if (CompareMem (Ptr
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
434 Ptr
+= EFI_CERT_TYPE_RSA2048_SIZE
;
439 // Add public key in database.
441 if (mPubKeyNumber
== MAX_KEY_NUM
) {
443 // Notes: Database is full, need enhancement here, currently just return 0.
448 CopyMem (mPubKeyStore
+ mPubKeyNumber
* EFI_CERT_TYPE_RSA2048_SIZE
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
449 Index
= ++mPubKeyNumber
;
451 // Update public key database variable.
453 Status
= UpdateVariable (
455 &gEfiAuthenticatedVariableGuid
,
457 mPubKeyNumber
* EFI_CERT_TYPE_RSA2048_SIZE
,
458 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
,
464 ASSERT_EFI_ERROR (Status
);
471 Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256_GUID type.
472 Follow the steps in UEFI2.2.
474 @param[in] Data Pointer to data with AuthInfo.
475 @param[in] DataSize Size of Data.
476 @param[in] PubKey Public key used for verification.
478 @retval EFI_INVALID_PARAMETER Invalid parameter.
479 @retval EFI_SECURITY_VIOLATION If authentication failed.
480 @retval EFI_SUCCESS Authentication successful.
484 VerifyCounterBasedPayload (
491 EFI_VARIABLE_AUTHENTICATION
*CertData
;
492 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
493 UINT8 Digest
[SHA256_DIGEST_SIZE
];
500 if (Data
== NULL
|| PubKey
== NULL
) {
501 return EFI_INVALID_PARAMETER
;
504 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
505 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
508 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
509 // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256_GUID.
511 if ((CertData
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) ||
512 !CompareGuid (&CertData
->AuthInfo
.CertType
, &gEfiCertTypeRsa2048Sha256Guid
)
515 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
517 return EFI_SECURITY_VIOLATION
;
520 // Hash data payload with SHA256.
522 ZeroMem (Digest
, SHA256_DIGEST_SIZE
);
523 Status
= Sha256Init (mHashCtx
);
527 Status
= Sha256Update (mHashCtx
, Data
+ AUTHINFO_SIZE
, (UINTN
) (DataSize
- AUTHINFO_SIZE
));
532 // Hash Monotonic Count.
534 Status
= Sha256Update (mHashCtx
, &CertData
->MonotonicCount
, sizeof (UINT64
));
538 Status
= Sha256Final (mHashCtx
, Digest
);
543 // Generate & Initialize RSA Context.
546 ASSERT (Rsa
!= NULL
);
548 // Set RSA Key Components.
549 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
551 Status
= RsaSetKey (Rsa
, RsaKeyN
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
555 Status
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
560 // Verify the signature.
562 Status
= RsaPkcs1Verify (
566 CertBlock
->Signature
,
567 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
577 return EFI_SECURITY_VIOLATION
;
582 Update platform mode.
584 @param[in] Mode SETUP_MODE or USER_MODE.
586 @return EFI_INVALID_PARAMETER Invalid parameter.
587 @return EFI_SUCCESS Update platform mode successfully.
596 VARIABLE_POINTER_TRACK Variable
;
598 UINT8 SecureBootMode
;
599 UINT8 SecureBootEnable
;
600 UINTN VariableDataSize
;
602 Status
= FindVariable (
604 &gEfiGlobalVariableGuid
,
606 &mVariableModuleGlobal
->VariableGlobal
,
609 if (EFI_ERROR (Status
)) {
613 mPlatformMode
= Mode
;
614 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
615 Status
= UpdateVariable (
617 &gEfiGlobalVariableGuid
,
626 if (EFI_ERROR (Status
)) {
632 // SecureBoot Variable indicates whether the platform firmware is operating
633 // in Secure boot mode (1) or not (0), so we should not change SecureBoot
634 // Variable in runtime.
640 // Check "SecureBoot" variable's existence.
641 // If it doesn't exist, firmware has no capability to perform driver signing verification,
642 // then set "SecureBoot" to 0.
644 Status
= FindVariable (
645 EFI_SECURE_BOOT_MODE_NAME
,
646 &gEfiGlobalVariableGuid
,
648 &mVariableModuleGlobal
->VariableGlobal
,
652 // If "SecureBoot" variable exists, then check "SetupMode" variable update.
653 // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1.
654 // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0.
656 if (Variable
.CurrPtr
== NULL
) {
657 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
659 if (mPlatformMode
== USER_MODE
) {
660 SecureBootMode
= SECURE_BOOT_MODE_ENABLE
;
661 } else if (mPlatformMode
== SETUP_MODE
) {
662 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
664 return EFI_NOT_FOUND
;
668 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
669 Status
= UpdateVariable (
670 EFI_SECURE_BOOT_MODE_NAME
,
671 &gEfiGlobalVariableGuid
,
680 if (EFI_ERROR (Status
)) {
685 // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature.
687 Status
= FindVariable (
688 EFI_SECURE_BOOT_ENABLE_NAME
,
689 &gEfiSecureBootEnableDisableGuid
,
691 &mVariableModuleGlobal
->VariableGlobal
,
695 if (SecureBootMode
== SECURE_BOOT_MODE_ENABLE
) {
697 // Create the "SecureBootEnable" variable as secure boot is enabled.
699 SecureBootEnable
= SECURE_BOOT_ENABLE
;
700 VariableDataSize
= sizeof (SecureBootEnable
);
703 // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot"
704 // variable is not in secure boot state.
706 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
709 SecureBootEnable
= SECURE_BOOT_DISABLE
;
710 VariableDataSize
= 0;
713 Status
= UpdateVariable (
714 EFI_SECURE_BOOT_ENABLE_NAME
,
715 &gEfiSecureBootEnableDisableGuid
,
718 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
728 Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK variable.
730 @param[in] VariableName Name of Variable to be check.
731 @param[in] VendorGuid Variable vendor GUID.
732 @param[in] Data Point to the variable data to be checked.
733 @param[in] DataSize Size of Data.
735 @return EFI_INVALID_PARAMETER Invalid signature list format.
736 @return EFI_SUCCESS Passed signature list format check successfully.
740 CheckSignatureListFormat(
741 IN CHAR16
*VariableName
,
742 IN EFI_GUID
*VendorGuid
,
747 EFI_SIGNATURE_LIST
*SigList
;
757 ASSERT (VariableName
!= NULL
&& VendorGuid
!= NULL
&& Data
!= NULL
);
759 if (CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
) && (StrCmp (VariableName
, EFI_PLATFORM_KEY_NAME
) == 0)){
761 } else if (CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
) && (StrCmp (VariableName
, EFI_KEY_EXCHANGE_KEY_NAME
) == 0)) {
768 SigList
= (EFI_SIGNATURE_LIST
*) Data
;
769 SigDataSize
= DataSize
;
772 // Walk throuth the input signature list and check the data format.
773 // If any signature is incorrectly formed, the whole check will fail.
775 while ((SigDataSize
> 0) && (SigDataSize
>= SigList
->SignatureListSize
)) {
776 for (Index
= 0; Index
< (sizeof (mSupportSigItem
) / sizeof (EFI_SIGNATURE_ITEM
)); Index
++ ) {
777 if (CompareGuid (&SigList
->SignatureType
, &mSupportSigItem
[Index
].SigType
)) {
779 // The value of SignatureSize should always be 16 (size of SignatureOwner
780 // component) add the data length according to signature type.
782 if (mSupportSigItem
[Index
].SigDataSize
!= ((UINT32
) ~0) &&
783 (SigList
->SignatureSize
- sizeof (EFI_GUID
)) != mSupportSigItem
[Index
].SigDataSize
) {
784 return EFI_INVALID_PARAMETER
;
786 if (mSupportSigItem
[Index
].SigHeaderSize
!= ((UINTN
) ~0) &&
787 SigList
->SignatureHeaderSize
!= mSupportSigItem
[Index
].SigHeaderSize
) {
788 return EFI_INVALID_PARAMETER
;
794 if (Index
== (sizeof (mSupportSigItem
) / sizeof (EFI_SIGNATURE_ITEM
))) {
796 // Undefined signature type.
798 return EFI_INVALID_PARAMETER
;
801 if ((SigList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - SigList
->SignatureHeaderSize
) % SigList
->SignatureSize
!= 0) {
802 return EFI_INVALID_PARAMETER
;
804 SigCount
+= (SigList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - SigList
->SignatureHeaderSize
) / SigList
->SignatureSize
;
806 SigDataSize
-= SigList
->SignatureListSize
;
807 SigList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) SigList
+ SigList
->SignatureListSize
);
810 if (((UINTN
) SigList
- (UINTN
) Data
) != DataSize
) {
811 return EFI_INVALID_PARAMETER
;
814 if (IsPk
&& SigCount
> 1) {
815 return EFI_INVALID_PARAMETER
;
822 Process variable with platform key for verification.
824 @param[in] VariableName Name of Variable to be found.
825 @param[in] VendorGuid Variable vendor GUID.
826 @param[in] Data Data pointer.
827 @param[in] DataSize Size of Data found. If size is less than the
828 data, this value contains the required size.
829 @param[in] Variable The variable information which is used to keep track of variable usage.
830 @param[in] Attributes Attribute value of the variable
831 @param[in] IsPk Indicate whether it is to process pk.
833 @return EFI_INVALID_PARAMETER Invalid parameter.
834 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
835 check carried out by the firmware.
836 @return EFI_SUCCESS Variable passed validation successfully.
841 IN CHAR16
*VariableName
,
842 IN EFI_GUID
*VendorGuid
,
845 IN VARIABLE_POINTER_TRACK
*Variable
,
846 IN UINT32 Attributes OPTIONAL
,
851 VARIABLE_POINTER_TRACK PkVariable
;
852 EFI_SIGNATURE_LIST
*OldPkList
;
853 EFI_SIGNATURE_DATA
*OldPkData
;
854 EFI_VARIABLE_AUTHENTICATION
*CertData
;
859 UINT64 MonotonicCount
;
862 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
864 // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
866 return EFI_INVALID_PARAMETER
;
869 if (mPlatformMode
== USER_MODE
&& !(InCustomMode() && UserPhysicalPresent())) {
871 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
873 // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute means time-based X509 Cert PK.
876 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
878 // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute means counter-based RSA-2048 Cert PK.
882 return EFI_INVALID_PARAMETER
;
887 // Verify against X509 Cert PK.
890 Status
= VerifyTimeBasedPayload (VariableName
, VendorGuid
, Data
, DataSize
, Variable
, Attributes
, TRUE
, &Del
);
891 if (!EFI_ERROR (Status
)) {
893 // If delete PK in user mode, need change to setup mode.
896 Status
= UpdatePlatformMode (SETUP_MODE
);
902 // Verify against RSA2048 Cert PK.
904 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
905 if ((Variable
->CurrPtr
!= NULL
) && (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
)) {
907 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
909 return EFI_SECURITY_VIOLATION
;
912 // Get platform key from variable.
914 Status
= FindVariable (
915 EFI_PLATFORM_KEY_NAME
,
916 &gEfiGlobalVariableGuid
,
918 &mVariableModuleGlobal
->VariableGlobal
,
921 ASSERT_EFI_ERROR (Status
);
923 OldPkList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (PkVariable
.CurrPtr
);
924 OldPkData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) OldPkList
+ sizeof (EFI_SIGNATURE_LIST
) + OldPkList
->SignatureHeaderSize
);
925 Status
= VerifyCounterBasedPayload (Data
, DataSize
, OldPkData
->SignatureData
);
926 if (!EFI_ERROR (Status
)) {
927 Status
= CheckSignatureListFormat(
930 (UINT8
*)Data
+ AUTHINFO_SIZE
,
931 DataSize
- AUTHINFO_SIZE
);
932 if (EFI_ERROR (Status
)) {
936 Status
= UpdateVariable (
939 (UINT8
*)Data
+ AUTHINFO_SIZE
,
940 DataSize
- AUTHINFO_SIZE
,
943 CertData
->MonotonicCount
,
948 if (!EFI_ERROR (Status
)) {
950 // If delete PK in user mode, need change to setup mode.
952 if ((DataSize
== AUTHINFO_SIZE
) && IsPk
) {
953 Status
= UpdatePlatformMode (SETUP_MODE
);
960 // Process PK or KEK in Setup mode or Custom Secure Boot mode.
962 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
964 // Time-based Authentication descriptor.
967 TimeStamp
= &((EFI_VARIABLE_AUTHENTICATION_2
*) Data
)->TimeStamp
;
968 Payload
= (UINT8
*) Data
+ AUTHINFO2_SIZE (Data
);
969 PayloadSize
= DataSize
- AUTHINFO2_SIZE (Data
);
970 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
972 // Counter-based Authentication descriptor.
974 MonotonicCount
= ((EFI_VARIABLE_AUTHENTICATION
*) Data
)->MonotonicCount
;
976 Payload
= (UINT8
*) Data
+ AUTHINFO_SIZE
;
977 PayloadSize
= DataSize
- AUTHINFO_SIZE
;
980 // No Authentication descriptor.
985 PayloadSize
= DataSize
;
988 Status
= CheckSignatureListFormat(VariableName
, VendorGuid
, Payload
, PayloadSize
);
989 if (EFI_ERROR (Status
)) {
993 Status
= UpdateVariable (
1006 if (PayloadSize
!= 0) {
1008 // If enroll PK in setup mode, need change to user mode.
1010 Status
= UpdatePlatformMode (USER_MODE
);
1013 // If delete PK in custom mode, need change to setup mode.
1015 UpdatePlatformMode (SETUP_MODE
);
1024 Process variable with key exchange key for verification.
1026 @param[in] VariableName Name of Variable to be found.
1027 @param[in] VendorGuid Variable vendor GUID.
1028 @param[in] Data Data pointer.
1029 @param[in] DataSize Size of Data found. If size is less than the
1030 data, this value contains the required size.
1031 @param[in] Variable The variable information which is used to keep track of variable usage.
1032 @param[in] Attributes Attribute value of the variable.
1034 @return EFI_INVALID_PARAMETER Invalid parameter.
1035 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation
1036 check carried out by the firmware.
1037 @return EFI_SUCCESS Variable pass validation successfully.
1042 IN CHAR16
*VariableName
,
1043 IN EFI_GUID
*VendorGuid
,
1046 IN VARIABLE_POINTER_TRACK
*Variable
,
1047 IN UINT32 Attributes OPTIONAL
1051 VARIABLE_POINTER_TRACK KekVariable
;
1052 EFI_SIGNATURE_LIST
*KekList
;
1053 EFI_SIGNATURE_DATA
*KekItem
;
1055 EFI_VARIABLE_AUTHENTICATION
*CertData
;
1056 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
1062 UINT64 MonotonicCount
;
1063 EFI_TIME
*TimeStamp
;
1065 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
1067 // DB and DBX should set EFI_VARIABLE_NON_VOLATILE attribute.
1069 return EFI_INVALID_PARAMETER
;
1072 Status
= EFI_SUCCESS
;
1073 if (mPlatformMode
== USER_MODE
&& !(InCustomMode() && UserPhysicalPresent())) {
1074 if (((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) == 0) &&
1075 ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) == 0)){
1077 // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS or
1078 // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute.
1080 return EFI_INVALID_PARAMETER
;
1083 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1085 // Time-based, verify against X509 Cert KEK.
1087 return VerifyTimeBasedPayload (VariableName
, VendorGuid
, Data
, DataSize
, Variable
, Attributes
, FALSE
, NULL
);
1088 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1090 // Counter-based, verify against RSA2048 Cert KEK.
1092 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
1093 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
1094 if ((Variable
->CurrPtr
!= NULL
) && (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
)) {
1096 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1098 return EFI_SECURITY_VIOLATION
;
1101 // Get KEK database from variable.
1103 Status
= FindVariable (
1104 EFI_KEY_EXCHANGE_KEY_NAME
,
1105 &gEfiGlobalVariableGuid
,
1107 &mVariableModuleGlobal
->VariableGlobal
,
1110 ASSERT_EFI_ERROR (Status
);
1112 KekDataSize
= KekVariable
.CurrPtr
->DataSize
;
1113 KekList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (KekVariable
.CurrPtr
);
1116 // Enumerate all Kek items in this list to verify the variable certificate data.
1117 // If anyone is authenticated successfully, it means the variable is correct!
1120 while ((KekDataSize
> 0) && (KekDataSize
>= KekList
->SignatureListSize
)) {
1121 if (CompareGuid (&KekList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1122 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekList
+ sizeof (EFI_SIGNATURE_LIST
) + KekList
->SignatureHeaderSize
);
1123 KekCount
= (KekList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - KekList
->SignatureHeaderSize
) / KekList
->SignatureSize
;
1124 for (Index
= 0; Index
< KekCount
; Index
++) {
1125 if (CompareMem (KekItem
->SignatureData
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
1129 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekItem
+ KekList
->SignatureSize
);
1132 KekDataSize
-= KekList
->SignatureListSize
;
1133 KekList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) KekList
+ KekList
->SignatureListSize
);
1137 return EFI_SECURITY_VIOLATION
;
1140 Status
= VerifyCounterBasedPayload (Data
, DataSize
, CertBlock
->PublicKey
);
1141 if (!EFI_ERROR (Status
)) {
1142 Status
= UpdateVariable (
1145 (UINT8
*)Data
+ AUTHINFO_SIZE
,
1146 DataSize
- AUTHINFO_SIZE
,
1149 CertData
->MonotonicCount
,
1157 // If in setup mode or custom secure boot mode, no authentication needed.
1159 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1161 // Time-based Authentication descriptor.
1164 TimeStamp
= &((EFI_VARIABLE_AUTHENTICATION_2
*) Data
)->TimeStamp
;
1165 Payload
= (UINT8
*) Data
+ AUTHINFO2_SIZE (Data
);
1166 PayloadSize
= DataSize
- AUTHINFO2_SIZE (Data
);
1167 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1169 // Counter-based Authentication descriptor.
1171 MonotonicCount
= ((EFI_VARIABLE_AUTHENTICATION
*) Data
)->MonotonicCount
;
1173 Payload
= (UINT8
*) Data
+ AUTHINFO_SIZE
;
1174 PayloadSize
= DataSize
- AUTHINFO_SIZE
;
1177 // No Authentication descriptor.
1182 PayloadSize
= DataSize
;
1185 Status
= UpdateVariable (
1202 Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
1204 @param[in] VariableName Name of Variable to be found.
1205 @param[in] VendorGuid Variable vendor GUID.
1207 @param[in] Data Data pointer.
1208 @param[in] DataSize Size of Data found. If size is less than the
1209 data, this value contains the required size.
1210 @param[in] Variable The variable information which is used to keep track of variable usage.
1211 @param[in] Attributes Attribute value of the variable.
1213 @return EFI_INVALID_PARAMETER Invalid parameter.
1214 @return EFI_WRITE_PROTECTED Variable is write-protected and needs authentication with
1215 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
1216 @return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
1217 set, but the AuthInfo does NOT pass the validation
1218 check carried out by the firmware.
1219 @return EFI_SUCCESS Variable is not write-protected or pass validation successfully.
1224 IN CHAR16
*VariableName
,
1225 IN EFI_GUID
*VendorGuid
,
1228 IN VARIABLE_POINTER_TRACK
*Variable
,
1229 IN UINT32 Attributes
1234 BOOLEAN IsFirstTime
;
1236 EFI_VARIABLE_AUTHENTICATION
*CertData
;
1237 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
1239 UINT64 MonotonicCount
;
1247 if (NeedPhysicallyPresent(VariableName
, VendorGuid
) && !UserPhysicalPresent()) {
1249 // This variable is protected, only physical present user could modify its value.
1251 return EFI_SECURITY_VIOLATION
;
1255 // Process Time-based Authenticated variable.
1257 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1258 return VerifyTimeBasedPayload (VariableName
, VendorGuid
, Data
, DataSize
, Variable
, Attributes
, FALSE
, NULL
);
1262 // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.
1264 if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1266 // Determine current operation type.
1268 if (DataSize
== AUTHINFO_SIZE
) {
1272 // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
1274 if (Variable
->CurrPtr
== NULL
) {
1276 } else if ((Variable
->CurrPtr
->Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) == 0) {
1279 KeyIndex
= Variable
->CurrPtr
->PubKeyIndex
;
1280 IsFirstTime
= FALSE
;
1282 } else if ((Variable
->CurrPtr
!= NULL
) &&
1283 (Variable
->CurrPtr
->Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0
1286 // If the variable is already write-protected, it always needs authentication before update.
1288 return EFI_WRITE_PROTECTED
;
1291 // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.
1292 // That means it is not authenticated variable, just update variable as usual.
1294 Status
= UpdateVariable (VariableName
, VendorGuid
, Data
, DataSize
, Attributes
, 0, 0, Variable
, NULL
);
1299 // Get PubKey and check Monotonic Count value corresponding to the variable.
1301 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
1302 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
1303 PubKey
= CertBlock
->PublicKey
;
1306 // Update Monotonic Count value.
1308 MonotonicCount
= CertData
->MonotonicCount
;
1312 // Check input PubKey.
1314 if (CompareMem (PubKey
, mPubKeyStore
+ (KeyIndex
- 1) * EFI_CERT_TYPE_RSA2048_SIZE
, EFI_CERT_TYPE_RSA2048_SIZE
) != 0) {
1315 return EFI_SECURITY_VIOLATION
;
1318 // Compare the current monotonic count and ensure that it is greater than the last SetVariable
1319 // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.
1321 if (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
) {
1323 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1325 return EFI_SECURITY_VIOLATION
;
1329 // Verify the certificate in Data payload.
1331 Status
= VerifyCounterBasedPayload (Data
, DataSize
, PubKey
);
1332 if (EFI_ERROR (Status
)) {
1337 // Now, the signature has been verified!
1339 if (IsFirstTime
&& !IsDeletion
) {
1341 // Update public key database variable if need.
1343 KeyIndex
= AddPubKeyInStore (PubKey
);
1347 // Verification pass.
1349 return UpdateVariable (VariableName
, VendorGuid
, (UINT8
*)Data
+ AUTHINFO_SIZE
, DataSize
- AUTHINFO_SIZE
, Attributes
, KeyIndex
, MonotonicCount
, Variable
, NULL
);
1353 Merge two buffers which formatted as EFI_SIGNATURE_LIST. Only the new EFI_SIGNATURE_DATA
1354 will be appended to the original EFI_SIGNATURE_LIST, duplicate EFI_SIGNATURE_DATA
1357 @param[in, out] Data Pointer to original EFI_SIGNATURE_LIST.
1358 @param[in] DataSize Size of Data buffer.
1359 @param[in] NewData Pointer to new EFI_SIGNATURE_LIST to be appended.
1360 @param[in] NewDataSize Size of NewData buffer.
1362 @return Size of the merged buffer.
1366 AppendSignatureList (
1370 IN UINTN NewDataSize
1373 EFI_SIGNATURE_LIST
*CertList
;
1374 EFI_SIGNATURE_DATA
*Cert
;
1376 EFI_SIGNATURE_LIST
*NewCertList
;
1377 EFI_SIGNATURE_DATA
*NewCert
;
1384 UINTN SignatureListSize
;
1387 Tail
= (UINT8
*) Data
+ DataSize
;
1389 NewCertList
= (EFI_SIGNATURE_LIST
*) NewData
;
1390 while ((NewDataSize
> 0) && (NewDataSize
>= NewCertList
->SignatureListSize
)) {
1391 NewCert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) NewCertList
+ sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
);
1392 NewCertCount
= (NewCertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - NewCertList
->SignatureHeaderSize
) / NewCertList
->SignatureSize
;
1395 for (Index
= 0; Index
< NewCertCount
; Index
++) {
1399 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1400 while ((Size
> 0) && (Size
>= CertList
->SignatureListSize
)) {
1401 if (CompareGuid (&CertList
->SignatureType
, &NewCertList
->SignatureType
) &&
1402 (CertList
->SignatureSize
== NewCertList
->SignatureSize
)) {
1403 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1404 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1405 for (Index2
= 0; Index2
< CertCount
; Index2
++) {
1407 // Iterate each Signature Data in this Signature List.
1409 if (CompareMem (NewCert
, Cert
, CertList
->SignatureSize
) == 0) {
1413 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1420 Size
-= CertList
->SignatureListSize
;
1421 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1426 // New EFI_SIGNATURE_DATA, append it.
1428 if (CopiedCount
== 0) {
1430 // Copy EFI_SIGNATURE_LIST header for only once.
1432 CopyMem (Tail
, NewCertList
, sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
);
1433 Tail
= Tail
+ sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
;
1436 CopyMem (Tail
, NewCert
, NewCertList
->SignatureSize
);
1437 Tail
+= NewCertList
->SignatureSize
;
1441 NewCert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) NewCert
+ NewCertList
->SignatureSize
);
1445 // Update SignatureListSize in newly appended EFI_SIGNATURE_LIST.
1447 if (CopiedCount
!= 0) {
1448 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
+ (CopiedCount
* NewCertList
->SignatureSize
);
1449 CertList
= (EFI_SIGNATURE_LIST
*) (Tail
- SignatureListSize
);
1450 CertList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1453 NewDataSize
-= NewCertList
->SignatureListSize
;
1454 NewCertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) NewCertList
+ NewCertList
->SignatureListSize
);
1457 return (Tail
- (UINT8
*) Data
);
1461 Compare two EFI_TIME data.
1464 @param FirstTime A pointer to the first EFI_TIME data.
1465 @param SecondTime A pointer to the second EFI_TIME data.
1467 @retval TRUE The FirstTime is not later than the SecondTime.
1468 @retval FALSE The FirstTime is later than the SecondTime.
1473 IN EFI_TIME
*FirstTime
,
1474 IN EFI_TIME
*SecondTime
1477 if (FirstTime
->Year
!= SecondTime
->Year
) {
1478 return (BOOLEAN
) (FirstTime
->Year
< SecondTime
->Year
);
1479 } else if (FirstTime
->Month
!= SecondTime
->Month
) {
1480 return (BOOLEAN
) (FirstTime
->Month
< SecondTime
->Month
);
1481 } else if (FirstTime
->Day
!= SecondTime
->Day
) {
1482 return (BOOLEAN
) (FirstTime
->Day
< SecondTime
->Day
);
1483 } else if (FirstTime
->Hour
!= SecondTime
->Hour
) {
1484 return (BOOLEAN
) (FirstTime
->Hour
< SecondTime
->Hour
);
1485 } else if (FirstTime
->Minute
!= SecondTime
->Minute
) {
1486 return (BOOLEAN
) (FirstTime
->Minute
< FirstTime
->Minute
);
1489 return (BOOLEAN
) (FirstTime
->Second
<= SecondTime
->Second
);
1493 Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
1495 @param[in] VariableName Name of Variable to be found.
1496 @param[in] VendorGuid Variable vendor GUID.
1497 @param[in] Data Data pointer.
1498 @param[in] DataSize Size of Data found. If size is less than the
1499 data, this value contains the required size.
1500 @param[in] Variable The variable information which is used to keep track of variable usage.
1501 @param[in] Attributes Attribute value of the variable.
1502 @param[in] Pk Verify against PK or KEK database.
1503 @param[out] VarDel Delete the variable or not.
1505 @retval EFI_INVALID_PARAMETER Invalid parameter.
1506 @retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
1507 check carried out by the firmware.
1508 @retval EFI_OUT_OF_RESOURCES Failed to process variable due to lack
1510 @retval EFI_SUCCESS Variable pass validation successfully.
1514 VerifyTimeBasedPayload (
1515 IN CHAR16
*VariableName
,
1516 IN EFI_GUID
*VendorGuid
,
1519 IN VARIABLE_POINTER_TRACK
*Variable
,
1520 IN UINT32 Attributes
,
1536 BOOLEAN VerifyStatus
;
1538 EFI_SIGNATURE_LIST
*CertList
;
1539 EFI_SIGNATURE_DATA
*Cert
;
1540 VARIABLE_POINTER_TRACK KekVariable
;
1541 EFI_VARIABLE_AUTHENTICATION_2
*CertData
;
1544 VARIABLE_POINTER_TRACK PkVariable
;
1549 VerifyStatus
= FALSE
;
1555 // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
1556 // set, then the Data buffer shall begin with an instance of a complete (and serialized)
1557 // EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new
1558 // variable value and DataSize shall reflect the combined size of the descriptor and the new
1559 // variable value. The authentication descriptor is not part of the variable data and is not
1560 // returned by subsequent calls to GetVariable().
1562 CertData
= (EFI_VARIABLE_AUTHENTICATION_2
*) Data
;
1565 // Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components of the
1566 // TimeStamp value are set to zero.
1568 if ((CertData
->TimeStamp
.Pad1
!= 0) ||
1569 (CertData
->TimeStamp
.Nanosecond
!= 0) ||
1570 (CertData
->TimeStamp
.TimeZone
!= 0) ||
1571 (CertData
->TimeStamp
.Daylight
!= 0) ||
1572 (CertData
->TimeStamp
.Pad2
!= 0)) {
1573 return EFI_SECURITY_VIOLATION
;
1576 if ((Variable
->CurrPtr
!= NULL
) && ((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0)) {
1577 if (CompareTimeStamp (&CertData
->TimeStamp
, &Variable
->CurrPtr
->TimeStamp
)) {
1579 // TimeStamp check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1581 return EFI_SECURITY_VIOLATION
;
1586 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
1587 // Cert type should be EFI_CERT_TYPE_PKCS7_GUID.
1589 if ((CertData
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) ||
1590 !CompareGuid (&CertData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
)) {
1592 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
1594 return EFI_SECURITY_VIOLATION
;
1598 // Find out Pkcs7 SignedData which follows the EFI_VARIABLE_AUTHENTICATION_2 descriptor.
1599 // AuthInfo.Hdr.dwLength is the length of the entire certificate, including the length of the header.
1601 SigData
= CertData
->AuthInfo
.CertData
;
1602 SigDataSize
= CertData
->AuthInfo
.Hdr
.dwLength
- (UINT32
) (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
));
1605 // Find out the new data payload which follows Pkcs7 SignedData directly.
1607 PayloadPtr
= SigData
+ SigDataSize
;
1608 PayloadSize
= DataSize
- OFFSET_OF_AUTHINFO2_CERT_DATA
- (UINTN
) SigDataSize
;
1611 // Construct a buffer to fill with (VariableName, VendorGuid, Attributes, TimeStamp, Data).
1613 NewDataSize
= PayloadSize
+ sizeof (EFI_TIME
) + sizeof (UINT32
) +
1614 sizeof (EFI_GUID
) + StrSize (VariableName
) - sizeof (CHAR16
);
1615 NewData
= mSerializationRuntimeBuffer
;
1618 Length
= StrLen (VariableName
) * sizeof (CHAR16
);
1619 CopyMem (Buffer
, VariableName
, Length
);
1622 Length
= sizeof (EFI_GUID
);
1623 CopyMem (Buffer
, VendorGuid
, Length
);
1626 Length
= sizeof (UINT32
);
1627 CopyMem (Buffer
, &Attr
, Length
);
1630 Length
= sizeof (EFI_TIME
);
1631 CopyMem (Buffer
, &CertData
->TimeStamp
, Length
);
1634 CopyMem (Buffer
, PayloadPtr
, PayloadSize
);
1638 // Get platform key from variable.
1640 Status
= FindVariable (
1641 EFI_PLATFORM_KEY_NAME
,
1642 &gEfiGlobalVariableGuid
,
1644 &mVariableModuleGlobal
->VariableGlobal
,
1647 if (EFI_ERROR (Status
)) {
1651 CertList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (PkVariable
.CurrPtr
);
1652 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1653 RootCert
= Cert
->SignatureData
;
1654 RootCertSize
= CertList
->SignatureSize
;
1658 // Verify Pkcs7 SignedData via Pkcs7Verify library.
1660 VerifyStatus
= Pkcs7Verify (
1672 // Get KEK database from variable.
1674 Status
= FindVariable (
1675 EFI_KEY_EXCHANGE_KEY_NAME
,
1676 &gEfiGlobalVariableGuid
,
1678 &mVariableModuleGlobal
->VariableGlobal
,
1681 if (EFI_ERROR (Status
)) {
1686 // Ready to verify Pkcs7 SignedData. Go through KEK Signature Database to find out X.509 CertList.
1688 KekDataSize
= KekVariable
.CurrPtr
->DataSize
;
1689 CertList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (KekVariable
.CurrPtr
);
1690 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1691 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1692 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1693 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1694 for (Index
= 0; Index
< CertCount
; Index
++) {
1696 // Iterate each Signature Data Node within this CertList for a verify
1698 RootCert
= Cert
->SignatureData
;
1699 RootCertSize
= CertList
->SignatureSize
;
1702 // Verify Pkcs7 SignedData via Pkcs7Verify library.
1704 VerifyStatus
= Pkcs7Verify (
1715 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1718 KekDataSize
-= CertList
->SignatureListSize
;
1719 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1725 if (!VerifyStatus
) {
1726 return EFI_SECURITY_VIOLATION
;
1729 Status
= CheckSignatureListFormat(VariableName
, VendorGuid
, PayloadPtr
, PayloadSize
);
1730 if (EFI_ERROR (Status
)) {
1734 if ((PayloadSize
== 0) && (VarDel
!= NULL
)) {
1739 // Final step: Update/Append Variable if it pass Pkcs7Verify
1741 return UpdateVariable (
1750 &CertData
->TimeStamp