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
[SIGSUPPORT_NUM
] = {EFI_CERT_RSA2048_SHA256_GUID
, EFI_CERT_RSA2048_SHA1_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 Internal function to delete a Variable given its name and GUID, no authentication
55 @param[in] VariableName Name of the Variable.
56 @param[in] VendorGuid GUID of the Variable.
58 @retval EFI_SUCCESS Variable deleted successfully.
59 @retval Others The driver failded to start the device.
64 IN CHAR16
*VariableName
,
65 IN EFI_GUID
*VendorGuid
69 VARIABLE_POINTER_TRACK Variable
;
71 Status
= FindVariable (VariableName
, VendorGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
72 if (EFI_ERROR (Status
)) {
76 ASSERT (Variable
.CurrPtr
!= NULL
);
77 return UpdateVariable (VariableName
, VendorGuid
, NULL
, 0, 0, 0, 0, &Variable
, NULL
);
81 Initializes for authenticated varibale service.
83 @retval EFI_SUCCESS Function successfully executed.
84 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resources.
88 AutenticatedVariableServiceInitialize (
93 VARIABLE_POINTER_TRACK Variable
;
100 UINT8 SecureBootEnable
;
103 // Initialize hash context.
105 CtxSize
= Sha256GetContextSize ();
106 mHashCtx
= AllocateRuntimePool (CtxSize
);
107 if (mHashCtx
== NULL
) {
108 return EFI_OUT_OF_RESOURCES
;
112 // Reserved runtime buffer for "Append" operation in virtual mode.
114 mStorageArea
= AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize
));
115 if (mStorageArea
== NULL
) {
116 return EFI_OUT_OF_RESOURCES
;
120 // Prepare runtime buffer for serialized data of time-based authenticated
121 // Variable, i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data).
123 mSerializationRuntimeBuffer
= AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize
) + sizeof (EFI_GUID
) + sizeof (UINT32
) + sizeof (EFI_TIME
));
124 if (mSerializationRuntimeBuffer
== NULL
) {
125 return EFI_OUT_OF_RESOURCES
;
129 // Check "AuthVarKeyDatabase" variable's existence.
130 // If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
132 Status
= FindVariable (
134 &gEfiAuthenticatedVariableGuid
,
136 &mVariableModuleGlobal
->VariableGlobal
139 if (Variable
.CurrPtr
== NULL
) {
140 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
143 Status
= UpdateVariable (
145 &gEfiAuthenticatedVariableGuid
,
154 if (EFI_ERROR (Status
)) {
159 // Load database in global variable for cache.
161 DataSize
= DataSizeOfVariable (Variable
.CurrPtr
);
162 Data
= GetVariableDataPtr (Variable
.CurrPtr
);
163 ASSERT ((DataSize
!= 0) && (Data
!= NULL
));
164 CopyMem (mPubKeyStore
, (UINT8
*) Data
, DataSize
);
165 mPubKeyNumber
= (UINT32
) (DataSize
/ EFI_CERT_TYPE_RSA2048_SIZE
);
168 // Check "SetupMode" variable's existence.
169 // If it doesn't exist, check PK database's existence to determine the value.
170 // Then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
172 Status
= FindVariable (
174 &gEfiGlobalVariableGuid
,
176 &mVariableModuleGlobal
->VariableGlobal
179 if (Variable
.CurrPtr
== NULL
) {
180 Status
= FindVariable (
181 EFI_PLATFORM_KEY_NAME
,
182 &gEfiGlobalVariableGuid
,
184 &mVariableModuleGlobal
->VariableGlobal
186 if (Variable
.CurrPtr
== NULL
) {
187 mPlatformMode
= SETUP_MODE
;
189 mPlatformMode
= USER_MODE
;
192 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
193 Status
= UpdateVariable (
195 &gEfiGlobalVariableGuid
,
204 if (EFI_ERROR (Status
)) {
208 mPlatformMode
= *(GetVariableDataPtr (Variable
.CurrPtr
));
211 // Check "SignatureSupport" variable's existence.
212 // If it doesn't exist, then create a new one with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
214 Status
= FindVariable (
215 EFI_SIGNATURE_SUPPORT_NAME
,
216 &gEfiGlobalVariableGuid
,
218 &mVariableModuleGlobal
->VariableGlobal
221 if (Variable
.CurrPtr
== NULL
) {
222 VarAttr
= EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
223 Status
= UpdateVariable (
224 EFI_SIGNATURE_SUPPORT_NAME
,
225 &gEfiGlobalVariableGuid
,
227 SIGSUPPORT_NUM
* sizeof(EFI_GUID
),
237 // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.
238 // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
239 // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.
241 SecureBootEnable
= SECURE_BOOT_MODE_DISABLE
;
242 FindVariable (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
243 if (Variable
.CurrPtr
!= NULL
) {
244 SecureBootEnable
= *(GetVariableDataPtr (Variable
.CurrPtr
));
245 } else if (mPlatformMode
== USER_MODE
) {
247 // "SecureBootEnable" not exist, initialize it in USER_MODE.
249 SecureBootEnable
= SECURE_BOOT_MODE_ENABLE
;
250 Status
= UpdateVariable (
251 EFI_SECURE_BOOT_ENABLE_NAME
,
252 &gEfiSecureBootEnableDisableGuid
,
255 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
261 if (EFI_ERROR (Status
)) {
266 if (SecureBootEnable
== SECURE_BOOT_ENABLE
&& mPlatformMode
== USER_MODE
) {
267 SecureBootMode
= SECURE_BOOT_MODE_ENABLE
;
269 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
271 FindVariable (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, &Variable
, &mVariableModuleGlobal
->VariableGlobal
);
272 Status
= UpdateVariable (
273 EFI_SECURE_BOOT_MODE_NAME
,
274 &gEfiGlobalVariableGuid
,
277 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
,
283 if (EFI_ERROR (Status
)) {
288 // Detect whether a secure platform-specific method to clear PK(Platform Key)
289 // is configured by platform owner. This method is provided for users force to clear PK
290 // in case incorrect enrollment mis-haps.
292 if (ForceClearPK ()) {
296 Status
= DeleteVariable (EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
);
297 if (EFI_ERROR (Status
)) {
302 // 2. Update "SetupMode" variable to SETUP_MODE.
304 UpdatePlatformMode (SETUP_MODE
);
307 // 3. Clear KEK, DB and DBX.
309 DeleteVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
);
310 DeleteVariable (EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
);
311 DeleteVariable (EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
);
318 Add public key in store and return its index.
320 @param[in] PubKey Input pointer to Public Key data
322 @return Index of new added item
333 VARIABLE_POINTER_TRACK Variable
;
336 if (PubKey
== NULL
) {
340 Status
= FindVariable (
342 &gEfiAuthenticatedVariableGuid
,
344 &mVariableModuleGlobal
->VariableGlobal
346 ASSERT_EFI_ERROR (Status
);
348 // Check whether the public key entry does exist.
351 for (Ptr
= mPubKeyStore
, Index
= 1; Index
<= mPubKeyNumber
; Index
++) {
352 if (CompareMem (Ptr
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
356 Ptr
+= EFI_CERT_TYPE_RSA2048_SIZE
;
361 // Add public key in database.
363 if (mPubKeyNumber
== MAX_KEY_NUM
) {
365 // Notes: Database is full, need enhancement here, currently just return 0.
370 CopyMem (mPubKeyStore
+ mPubKeyNumber
* EFI_CERT_TYPE_RSA2048_SIZE
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
371 Index
= ++mPubKeyNumber
;
373 // Update public key database variable.
375 Status
= UpdateVariable (
377 &gEfiAuthenticatedVariableGuid
,
379 mPubKeyNumber
* EFI_CERT_TYPE_RSA2048_SIZE
,
380 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
,
386 ASSERT_EFI_ERROR (Status
);
393 Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256 type.
394 Follow the steps in UEFI2.2.
396 @param[in] Data Pointer to data with AuthInfo.
397 @param[in] DataSize Size of Data.
398 @param[in] PubKey Public key used for verification.
400 @retval EFI_INVALID_PARAMETER Invalid parameter.
401 @retval EFI_SECURITY_VIOLATION If authentication failed.
402 @retval EFI_SUCCESS Authentication successful.
406 VerifyCounterBasedPayload (
413 EFI_VARIABLE_AUTHENTICATION
*CertData
;
414 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
415 UINT8 Digest
[SHA256_DIGEST_SIZE
];
422 if (Data
== NULL
|| PubKey
== NULL
) {
423 return EFI_INVALID_PARAMETER
;
426 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
427 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
430 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
431 // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256.
433 if ((CertData
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) ||
434 !CompareGuid (&CertData
->AuthInfo
.CertType
, &gEfiCertRsa2048Sha256Guid
)
437 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
439 return EFI_SECURITY_VIOLATION
;
442 // Hash data payload with SHA256.
444 ZeroMem (Digest
, SHA256_DIGEST_SIZE
);
445 Status
= Sha256Init (mHashCtx
);
449 Status
= Sha256Update (mHashCtx
, Data
+ AUTHINFO_SIZE
, (UINTN
) (DataSize
- AUTHINFO_SIZE
));
454 // Hash Monotonic Count.
456 Status
= Sha256Update (mHashCtx
, &CertData
->MonotonicCount
, sizeof (UINT64
));
460 Status
= Sha256Final (mHashCtx
, Digest
);
465 // Generate & Initialize RSA Context.
468 ASSERT (Rsa
!= NULL
);
470 // Set RSA Key Components.
471 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
473 Status
= RsaSetKey (Rsa
, RsaKeyN
, PubKey
, EFI_CERT_TYPE_RSA2048_SIZE
);
477 Status
= RsaSetKey (Rsa
, RsaKeyE
, mRsaE
, sizeof (mRsaE
));
482 // Verify the signature.
484 Status
= RsaPkcs1Verify (
488 CertBlock
->Signature
,
489 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
499 return EFI_SECURITY_VIOLATION
;
504 Update platform mode.
506 @param[in] Mode SETUP_MODE or USER_MODE.
508 @return EFI_INVALID_PARAMETER Invalid parameter.
509 @return EFI_SUCCESS Update platform mode successfully.
518 VARIABLE_POINTER_TRACK Variable
;
520 UINT8 SecureBootMode
;
521 UINT8 SecureBootEnable
;
522 UINTN VariableDataSize
;
524 Status
= FindVariable (
526 &gEfiGlobalVariableGuid
,
528 &mVariableModuleGlobal
->VariableGlobal
530 if (EFI_ERROR (Status
)) {
534 mPlatformMode
= Mode
;
535 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
536 Status
= UpdateVariable (
538 &gEfiGlobalVariableGuid
,
547 if (EFI_ERROR (Status
)) {
553 // SecureBoot Variable indicates whether the platform firmware is operating
554 // in Secure boot mode (1) or not (0), so we should not change SecureBoot
555 // Variable in runtime.
561 // Check "SecureBoot" variable's existence.
562 // If it doesn't exist, firmware has no capability to perform driver signing verification,
563 // then set "SecureBoot" to 0.
565 Status
= FindVariable (
566 EFI_SECURE_BOOT_MODE_NAME
,
567 &gEfiGlobalVariableGuid
,
569 &mVariableModuleGlobal
->VariableGlobal
572 // If "SecureBoot" variable exists, then check "SetupMode" variable update.
573 // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1.
574 // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0.
576 if (Variable
.CurrPtr
== NULL
) {
577 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
579 if (mPlatformMode
== USER_MODE
) {
580 SecureBootMode
= SECURE_BOOT_MODE_ENABLE
;
581 } else if (mPlatformMode
== SETUP_MODE
) {
582 SecureBootMode
= SECURE_BOOT_MODE_DISABLE
;
584 return EFI_NOT_FOUND
;
588 VarAttr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
;
589 Status
= UpdateVariable (
590 EFI_SECURE_BOOT_MODE_NAME
,
591 &gEfiGlobalVariableGuid
,
600 if (EFI_ERROR (Status
)) {
605 // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature.
607 Status
= FindVariable (
608 EFI_SECURE_BOOT_ENABLE_NAME
,
609 &gEfiSecureBootEnableDisableGuid
,
611 &mVariableModuleGlobal
->VariableGlobal
614 if (SecureBootMode
== SECURE_BOOT_MODE_ENABLE
) {
616 // Create the "SecureBootEnable" variable as secure boot is enabled.
618 SecureBootEnable
= SECURE_BOOT_ENABLE
;
619 VariableDataSize
= sizeof (SecureBootEnable
);
622 // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot"
623 // variable is not in secure boot state.
625 if (Variable
.CurrPtr
== NULL
|| EFI_ERROR (Status
)) {
628 SecureBootEnable
= SECURE_BOOT_DISABLE
;
629 VariableDataSize
= 0;
632 Status
= UpdateVariable (
633 EFI_SECURE_BOOT_ENABLE_NAME
,
634 &gEfiSecureBootEnableDisableGuid
,
637 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
647 Process variable with platform key for verification.
649 @param[in] VariableName Name of Variable to be found.
650 @param[in] VendorGuid Variable vendor GUID.
651 @param[in] Data Data pointer.
652 @param[in] DataSize Size of Data found. If size is less than the
653 data, this value contains the required size.
654 @param[in] Variable The variable information which is used to keep track of variable usage.
655 @param[in] Attributes Attribute value of the variable
656 @param[in] IsPk Indicate whether it is to process pk.
658 @return EFI_INVALID_PARAMETER Invalid parameter.
659 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
660 check carried out by the firmware.
661 @return EFI_SUCCESS Variable passed validation successfully.
666 IN CHAR16
*VariableName
,
667 IN EFI_GUID
*VendorGuid
,
670 IN VARIABLE_POINTER_TRACK
*Variable
,
671 IN UINT32 Attributes OPTIONAL
,
676 VARIABLE_POINTER_TRACK PkVariable
;
677 EFI_SIGNATURE_LIST
*OldPkList
;
678 EFI_SIGNATURE_DATA
*OldPkData
;
679 EFI_VARIABLE_AUTHENTICATION
*CertData
;
684 UINT64 MonotonicCount
;
687 if ((Attributes
& EFI_VARIABLE_NON_VOLATILE
) == 0) {
689 // PK and KEK should set EFI_VARIABLE_NON_VOLATILE attribute.
691 return EFI_INVALID_PARAMETER
;
694 if (mPlatformMode
== USER_MODE
) {
696 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
698 // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute means time-based X509 Cert PK.
701 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
703 // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute means counter-based RSA-2048 Cert PK.
707 return EFI_INVALID_PARAMETER
;
712 // Verify against X509 Cert PK.
715 Status
= VerifyTimeBasedPayload (VariableName
, VendorGuid
, Data
, DataSize
, Variable
, Attributes
, TRUE
, &Del
);
716 if (!EFI_ERROR (Status
)) {
718 // If delete PK in user mode, need change to setup mode.
721 Status
= UpdatePlatformMode (SETUP_MODE
);
727 // Verify against RSA2048 Cert PK.
729 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
730 if ((Variable
->CurrPtr
!= NULL
) && (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
)) {
732 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
734 return EFI_SECURITY_VIOLATION
;
737 // Get platform key from variable.
739 Status
= FindVariable (
740 EFI_PLATFORM_KEY_NAME
,
741 &gEfiGlobalVariableGuid
,
743 &mVariableModuleGlobal
->VariableGlobal
745 ASSERT_EFI_ERROR (Status
);
747 OldPkList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (PkVariable
.CurrPtr
);
748 OldPkData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) OldPkList
+ sizeof (EFI_SIGNATURE_LIST
) + OldPkList
->SignatureHeaderSize
);
749 Status
= VerifyCounterBasedPayload (Data
, DataSize
, OldPkData
->SignatureData
);
750 if (!EFI_ERROR (Status
)) {
751 Status
= UpdateVariable (
754 (UINT8
*)Data
+ AUTHINFO_SIZE
,
755 DataSize
- AUTHINFO_SIZE
,
758 CertData
->MonotonicCount
,
763 if (!EFI_ERROR (Status
)) {
765 // If delete PK in user mode, need change to setup mode.
767 if ((DataSize
== AUTHINFO_SIZE
) && IsPk
) {
768 Status
= UpdatePlatformMode (SETUP_MODE
);
775 // Process PK or KEK in Setup mode.
777 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
779 // Time-based Authentication descriptor.
782 TimeStamp
= &((EFI_VARIABLE_AUTHENTICATION_2
*) Data
)->TimeStamp
;
783 Payload
= (UINT8
*) Data
+ AUTHINFO2_SIZE (Data
);
784 PayloadSize
= DataSize
- AUTHINFO2_SIZE (Data
);
785 } else if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
787 // Counter-based Authentication descriptor.
789 MonotonicCount
= ((EFI_VARIABLE_AUTHENTICATION
*) Data
)->MonotonicCount
;
791 Payload
= (UINT8
*) Data
+ AUTHINFO_SIZE
;
792 PayloadSize
= DataSize
- AUTHINFO_SIZE
;
795 // No Authentication descriptor.
800 PayloadSize
= DataSize
;
803 Status
= UpdateVariable (
815 // If enroll PK in setup mode, need change to user mode.
817 if ((DataSize
!= 0) && IsPk
) {
818 Status
= UpdatePlatformMode (USER_MODE
);
826 Process variable with key exchange key for verification.
828 @param[in] VariableName Name of Variable to be found.
829 @param[in] VendorGuid Variable vendor GUID.
830 @param[in] Data Data pointer.
831 @param[in] DataSize Size of Data found. If size is less than the
832 data, this value contains the required size.
833 @param[in] Variable The variable information which is used to keep track of variable usage.
834 @param[in] Attributes Attribute value of the variable.
836 @return EFI_INVALID_PARAMETER Invalid parameter.
837 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation
838 check carried out by the firmware.
839 @return EFI_SUCCESS Variable pass validation successfully.
844 IN CHAR16
*VariableName
,
845 IN EFI_GUID
*VendorGuid
,
848 IN VARIABLE_POINTER_TRACK
*Variable
,
849 IN UINT32 Attributes OPTIONAL
853 VARIABLE_POINTER_TRACK KekVariable
;
854 EFI_SIGNATURE_LIST
*KekList
;
855 EFI_SIGNATURE_DATA
*KekItem
;
857 EFI_VARIABLE_AUTHENTICATION
*CertData
;
858 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
864 UINT64 MonotonicCount
;
866 if (mPlatformMode
== USER_MODE
) {
867 if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) == 0) {
869 // In user mode, should set EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute.
871 return EFI_INVALID_PARAMETER
;
874 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
875 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
876 if ((Variable
->CurrPtr
!= NULL
) && (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
)) {
878 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
880 return EFI_SECURITY_VIOLATION
;
883 // Get KEK database from variable.
885 Status
= FindVariable (
886 EFI_KEY_EXCHANGE_KEY_NAME
,
887 &gEfiGlobalVariableGuid
,
889 &mVariableModuleGlobal
->VariableGlobal
891 ASSERT_EFI_ERROR (Status
);
893 KekDataSize
= KekVariable
.CurrPtr
->DataSize
;
894 KekList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (KekVariable
.CurrPtr
);
897 // Enumerate all Kek items in this list to verify the variable certificate data.
898 // If anyone is authenticated successfully, it means the variable is correct!
901 while ((KekDataSize
> 0) && (KekDataSize
>= KekList
->SignatureListSize
)) {
902 if (CompareGuid (&KekList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
903 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekList
+ sizeof (EFI_SIGNATURE_LIST
) + KekList
->SignatureHeaderSize
);
904 KekCount
= (KekList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - KekList
->SignatureHeaderSize
) / KekList
->SignatureSize
;
905 for (Index
= 0; Index
< KekCount
; Index
++) {
906 if (CompareMem (KekItem
->SignatureData
, CertBlock
->PublicKey
, EFI_CERT_TYPE_RSA2048_SIZE
) == 0) {
910 KekItem
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekItem
+ KekList
->SignatureSize
);
913 KekDataSize
-= KekList
->SignatureListSize
;
914 KekList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) KekList
+ KekList
->SignatureListSize
);
918 return EFI_SECURITY_VIOLATION
;
921 Status
= VerifyCounterBasedPayload (Data
, DataSize
, CertBlock
->PublicKey
);
922 if (!EFI_ERROR (Status
)) {
923 Status
= UpdateVariable (
926 (UINT8
*)Data
+ AUTHINFO_SIZE
,
927 DataSize
- AUTHINFO_SIZE
,
930 CertData
->MonotonicCount
,
937 // If in setup mode, no authentication needed.
939 if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
941 // Counter-based Authentication descriptor.
943 MonotonicCount
= ((EFI_VARIABLE_AUTHENTICATION
*) Data
)->MonotonicCount
;
944 Payload
= (UINT8
*) Data
+ AUTHINFO_SIZE
;
945 PayloadSize
= DataSize
- AUTHINFO_SIZE
;
948 // No Authentication descriptor.
952 PayloadSize
= DataSize
;
955 Status
= UpdateVariable (
972 Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
974 @param[in] VariableName Name of Variable to be found.
975 @param[in] VendorGuid Variable vendor GUID.
977 @param[in] Data Data pointer.
978 @param[in] DataSize Size of Data found. If size is less than the
979 data, this value contains the required size.
980 @param[in] Variable The variable information which is used to keep track of variable usage.
981 @param[in] Attributes Attribute value of the variable.
983 @return EFI_INVALID_PARAMETER Invalid parameter.
984 @return EFI_WRITE_PROTECTED Variable is write-protected and needs authentication with
985 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
986 @return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
987 set, but the AuthInfo does NOT pass the validation
988 check carried out by the firmware.
989 @return EFI_SUCCESS Variable is not write-protected or pass validation successfully.
994 IN CHAR16
*VariableName
,
995 IN EFI_GUID
*VendorGuid
,
998 IN VARIABLE_POINTER_TRACK
*Variable
,
1004 BOOLEAN IsFirstTime
;
1006 EFI_VARIABLE_AUTHENTICATION
*CertData
;
1007 EFI_CERT_BLOCK_RSA_2048_SHA256
*CertBlock
;
1009 UINT64 MonotonicCount
;
1018 // Process Time-based Authenticated variable.
1020 if ((Attributes
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1021 return VerifyTimeBasedPayload (VariableName
, VendorGuid
, Data
, DataSize
, Variable
, Attributes
, FALSE
, NULL
);
1025 // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.
1027 if ((Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1029 // Determine current operation type.
1031 if (DataSize
== AUTHINFO_SIZE
) {
1035 // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
1037 if (Variable
->CurrPtr
== NULL
) {
1039 } else if ((Variable
->CurrPtr
->Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) == 0) {
1042 KeyIndex
= Variable
->CurrPtr
->PubKeyIndex
;
1043 IsFirstTime
= FALSE
;
1045 } else if ((Variable
->CurrPtr
!= NULL
) &&
1046 (Variable
->CurrPtr
->Attributes
& EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
) != 0
1049 // If the variable is already write-protected, it always needs authentication before update.
1051 return EFI_WRITE_PROTECTED
;
1054 // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.
1055 // That means it is not authenticated variable, just update variable as usual.
1057 Status
= UpdateVariable (VariableName
, VendorGuid
, Data
, DataSize
, Attributes
, 0, 0, Variable
, NULL
);
1062 // Get PubKey and check Monotonic Count value corresponding to the variable.
1064 CertData
= (EFI_VARIABLE_AUTHENTICATION
*) Data
;
1065 CertBlock
= (EFI_CERT_BLOCK_RSA_2048_SHA256
*) (CertData
->AuthInfo
.CertData
);
1066 PubKey
= CertBlock
->PublicKey
;
1069 // Update Monotonic Count value.
1071 MonotonicCount
= CertData
->MonotonicCount
;
1075 // Check input PubKey.
1077 if (CompareMem (PubKey
, mPubKeyStore
+ (KeyIndex
- 1) * EFI_CERT_TYPE_RSA2048_SIZE
, EFI_CERT_TYPE_RSA2048_SIZE
) != 0) {
1078 return EFI_SECURITY_VIOLATION
;
1081 // Compare the current monotonic count and ensure that it is greater than the last SetVariable
1082 // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.
1084 if (CertData
->MonotonicCount
<= Variable
->CurrPtr
->MonotonicCount
) {
1086 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1088 return EFI_SECURITY_VIOLATION
;
1092 // Verify the certificate in Data payload.
1094 Status
= VerifyCounterBasedPayload (Data
, DataSize
, PubKey
);
1095 if (EFI_ERROR (Status
)) {
1100 // Now, the signature has been verified!
1102 if (IsFirstTime
&& !IsDeletion
) {
1104 // Update public key database variable if need.
1106 KeyIndex
= AddPubKeyInStore (PubKey
);
1110 // Verification pass.
1112 return UpdateVariable (VariableName
, VendorGuid
, (UINT8
*)Data
+ AUTHINFO_SIZE
, DataSize
- AUTHINFO_SIZE
, Attributes
, KeyIndex
, MonotonicCount
, Variable
, NULL
);
1116 Merge two buffers which formatted as EFI_SIGNATURE_LIST. Only the new EFI_SIGNATURE_DATA
1117 will be appended to the original EFI_SIGNATURE_LIST, duplicate EFI_SIGNATURE_DATA
1120 @param[in, out] Data Pointer to original EFI_SIGNATURE_LIST.
1121 @param[in] DataSize Size of Data buffer.
1122 @param[in] NewData Pointer to new EFI_SIGNATURE_LIST to be appended.
1123 @param[in] NewDataSize Size of NewData buffer.
1125 @return Size of the merged buffer.
1129 AppendSignatureList (
1133 IN UINTN NewDataSize
1136 EFI_SIGNATURE_LIST
*CertList
;
1137 EFI_SIGNATURE_DATA
*Cert
;
1139 EFI_SIGNATURE_LIST
*NewCertList
;
1140 EFI_SIGNATURE_DATA
*NewCert
;
1147 UINTN SignatureListSize
;
1150 Tail
= (UINT8
*) Data
+ DataSize
;
1152 NewCertList
= (EFI_SIGNATURE_LIST
*) NewData
;
1153 while ((NewDataSize
> 0) && (NewDataSize
>= NewCertList
->SignatureListSize
)) {
1154 NewCert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) NewCertList
+ sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
);
1155 NewCertCount
= (NewCertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - NewCertList
->SignatureHeaderSize
) / NewCertList
->SignatureSize
;
1158 for (Index
= 0; Index
< NewCertCount
; Index
++) {
1162 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1163 while ((Size
> 0) && (Size
>= CertList
->SignatureListSize
)) {
1164 if (CompareGuid (&CertList
->SignatureType
, &NewCertList
->SignatureType
) &&
1165 (CertList
->SignatureSize
== NewCertList
->SignatureSize
)) {
1166 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1167 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1168 for (Index2
= 0; Index2
< CertCount
; Index2
++) {
1170 // Iterate each Signature Data in this Signature List.
1172 if (CompareMem (NewCert
, Cert
, CertList
->SignatureSize
) == 0) {
1176 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1183 Size
-= CertList
->SignatureListSize
;
1184 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1189 // New EFI_SIGNATURE_DATA, append it.
1191 if (CopiedCount
== 0) {
1193 // Copy EFI_SIGNATURE_LIST header for only once.
1195 CopyMem (Tail
, NewCertList
, sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
);
1196 Tail
= Tail
+ sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
;
1199 CopyMem (Tail
, NewCert
, NewCertList
->SignatureSize
);
1200 Tail
+= NewCertList
->SignatureSize
;
1204 NewCert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) NewCert
+ NewCertList
->SignatureSize
);
1208 // Update SignatureListSize in newly appended EFI_SIGNATURE_LIST.
1210 if (CopiedCount
!= 0) {
1211 SignatureListSize
= sizeof (EFI_SIGNATURE_LIST
) + NewCertList
->SignatureHeaderSize
+ (CopiedCount
* NewCertList
->SignatureSize
);
1212 CertList
= (EFI_SIGNATURE_LIST
*) (Tail
- SignatureListSize
);
1213 CertList
->SignatureListSize
= (UINT32
) SignatureListSize
;
1216 NewDataSize
-= NewCertList
->SignatureListSize
;
1217 NewCertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) NewCertList
+ NewCertList
->SignatureListSize
);
1220 return (Tail
- (UINT8
*) Data
);
1224 Compare two EFI_TIME data.
1227 @param FirstTime A pointer to the first EFI_TIME data.
1228 @param SecondTime A pointer to the second EFI_TIME data.
1230 @retval TRUE The FirstTime is not later than the SecondTime.
1231 @retval FALSE The FirstTime is later than the SecondTime.
1236 IN EFI_TIME
*FirstTime
,
1237 IN EFI_TIME
*SecondTime
1240 if (FirstTime
->Year
!= SecondTime
->Year
) {
1241 return (BOOLEAN
) (FirstTime
->Year
< SecondTime
->Year
);
1242 } else if (FirstTime
->Month
!= SecondTime
->Month
) {
1243 return (BOOLEAN
) (FirstTime
->Month
< SecondTime
->Month
);
1244 } else if (FirstTime
->Day
!= SecondTime
->Day
) {
1245 return (BOOLEAN
) (FirstTime
->Day
< SecondTime
->Day
);
1246 } else if (FirstTime
->Hour
!= SecondTime
->Hour
) {
1247 return (BOOLEAN
) (FirstTime
->Hour
< SecondTime
->Hour
);
1248 } else if (FirstTime
->Minute
!= SecondTime
->Minute
) {
1249 return (BOOLEAN
) (FirstTime
->Minute
< FirstTime
->Minute
);
1252 return (BOOLEAN
) (FirstTime
->Second
<= SecondTime
->Second
);
1256 Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
1258 @param[in] VariableName Name of Variable to be found.
1259 @param[in] VendorGuid Variable vendor GUID.
1260 @param[in] Data Data pointer.
1261 @param[in] DataSize Size of Data found. If size is less than the
1262 data, this value contains the required size.
1263 @param[in] Variable The variable information which is used to keep track of variable usage.
1264 @param[in] Attributes Attribute value of the variable.
1265 @param[in] Pk Verify against PK or KEK database.
1266 @param[out] VarDel Delete the variable or not.
1268 @retval EFI_INVALID_PARAMETER Invalid parameter.
1269 @retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
1270 check carried out by the firmware.
1271 @retval EFI_OUT_OF_RESOURCES Failed to process variable due to lack
1273 @retval EFI_SUCCESS Variable pass validation successfully.
1277 VerifyTimeBasedPayload (
1278 IN CHAR16
*VariableName
,
1279 IN EFI_GUID
*VendorGuid
,
1282 IN VARIABLE_POINTER_TRACK
*Variable
,
1283 IN UINT32 Attributes
,
1299 BOOLEAN VerifyStatus
;
1301 EFI_SIGNATURE_LIST
*CertList
;
1302 EFI_SIGNATURE_DATA
*Cert
;
1303 VARIABLE_POINTER_TRACK KekVariable
;
1304 EFI_VARIABLE_AUTHENTICATION_2
*CertData
;
1307 VARIABLE_POINTER_TRACK PkVariable
;
1312 VerifyStatus
= FALSE
;
1318 // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
1319 // set, then the Data buffer shall begin with an instance of a complete (and serialized)
1320 // EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new
1321 // variable value and DataSize shall reflect the combined size of the descriptor and the new
1322 // variable value. The authentication descriptor is not part of the variable data and is not
1323 // returned by subsequent calls to GetVariable().
1325 CertData
= (EFI_VARIABLE_AUTHENTICATION_2
*) Data
;
1328 // Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components of the
1329 // TimeStamp value are set to zero.
1331 if ((CertData
->TimeStamp
.Pad1
!= 0) ||
1332 (CertData
->TimeStamp
.Nanosecond
!= 0) ||
1333 (CertData
->TimeStamp
.TimeZone
!= 0) ||
1334 (CertData
->TimeStamp
.Daylight
!= 0) ||
1335 (CertData
->TimeStamp
.Pad2
!= 0)) {
1336 return EFI_INVALID_PARAMETER
;
1339 if ((Variable
->CurrPtr
!= NULL
) && ((Attributes
& EFI_VARIABLE_APPEND_WRITE
) == 0)) {
1340 if (CompareTimeStamp (&CertData
->TimeStamp
, &Variable
->CurrPtr
->TimeStamp
)) {
1342 // TimeStamp check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1344 return EFI_SECURITY_VIOLATION
;
1349 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
1350 // Cert type should be EFI_CERT_TYPE_PKCS7_GUID.
1352 if ((CertData
->AuthInfo
.Hdr
.wCertificateType
!= WIN_CERT_TYPE_EFI_GUID
) ||
1353 !CompareGuid (&CertData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
)) {
1355 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
1357 return EFI_SECURITY_VIOLATION
;
1361 // Find out Pkcs7 SignedData which follows the EFI_VARIABLE_AUTHENTICATION_2 descriptor.
1362 // AuthInfo.Hdr.dwLength is the length of the entire certificate, including the length of the header.
1364 SigData
= CertData
->AuthInfo
.CertData
;
1365 SigDataSize
= CertData
->AuthInfo
.Hdr
.dwLength
- (UINT32
) (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
));
1368 // Find out the new data payload which follows Pkcs7 SignedData directly.
1370 PayloadPtr
= SigData
+ SigDataSize
;
1371 PayloadSize
= DataSize
- OFFSET_OF_AUTHINFO2_CERT_DATA
- (UINTN
) SigDataSize
;
1374 // Construct a buffer to fill with (VariableName, VendorGuid, Attributes, TimeStamp, Data).
1376 NewDataSize
= PayloadSize
+ sizeof (EFI_TIME
) + sizeof (UINT32
) +
1377 sizeof (EFI_GUID
) + StrSize (VariableName
) - sizeof (CHAR16
);
1378 NewData
= mSerializationRuntimeBuffer
;
1381 Length
= StrLen (VariableName
) * sizeof (CHAR16
);
1382 CopyMem (Buffer
, VariableName
, Length
);
1385 Length
= sizeof (EFI_GUID
);
1386 CopyMem (Buffer
, VendorGuid
, Length
);
1389 Length
= sizeof (UINT32
);
1390 CopyMem (Buffer
, &Attr
, Length
);
1393 Length
= sizeof (EFI_TIME
);
1394 CopyMem (Buffer
, &CertData
->TimeStamp
, Length
);
1397 CopyMem (Buffer
, PayloadPtr
, PayloadSize
);
1401 // Get platform key from variable.
1403 Status
= FindVariable (
1404 EFI_PLATFORM_KEY_NAME
,
1405 &gEfiGlobalVariableGuid
,
1407 &mVariableModuleGlobal
->VariableGlobal
1409 if (EFI_ERROR (Status
)) {
1413 CertList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (PkVariable
.CurrPtr
);
1414 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1415 RootCert
= Cert
->SignatureData
;
1416 RootCertSize
= CertList
->SignatureSize
;
1420 // Verify Pkcs7 SignedData via Pkcs7Verify library.
1422 VerifyStatus
= Pkcs7Verify (
1434 // Get KEK database from variable.
1436 Status
= FindVariable (
1437 EFI_KEY_EXCHANGE_KEY_NAME
,
1438 &gEfiGlobalVariableGuid
,
1440 &mVariableModuleGlobal
->VariableGlobal
1442 if (EFI_ERROR (Status
)) {
1447 // Ready to verify Pkcs7 SignedData. Go through KEK Signature Database to find out X.509 CertList.
1449 KekDataSize
= KekVariable
.CurrPtr
->DataSize
;
1450 CertList
= (EFI_SIGNATURE_LIST
*) GetVariableDataPtr (KekVariable
.CurrPtr
);
1451 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1452 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1453 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1454 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1455 for (Index
= 0; Index
< CertCount
; Index
++) {
1457 // Iterate each Signature Data Node within this CertList for a verify
1459 RootCert
= Cert
->SignatureData
;
1460 RootCertSize
= CertList
->SignatureSize
;
1463 // Verify Pkcs7 SignedData via Pkcs7Verify library.
1465 VerifyStatus
= Pkcs7Verify (
1476 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1479 KekDataSize
-= CertList
->SignatureListSize
;
1480 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1486 if (!VerifyStatus
) {
1487 return EFI_SECURITY_VIOLATION
;
1490 if ((PayloadSize
== 0) && (VarDel
!= NULL
)) {
1495 // Final step: Update/Append Variable if it pass Pkcs7Verify
1497 return UpdateVariable (
1506 &CertData
->TimeStamp