]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/VariableAuthenticated/RuntimeDxe/AuthService.c
Add comments to clarify mPubKeyStore buffer MemCopy. There is no memory overflow...
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / RuntimeDxe / AuthService.c
1 /** @file
2 Implement authentication services for the authenticated variable
3 service in UEFI2.2.
4
5 Caution: This module requires additional review when modified.
6 This driver will have external input - variable data. It may be input in SMM mode.
7 This external input must be validated carefully to avoid security issue like
8 buffer overflow, integer overflow.
9 Variable attribute should also be checked to avoid authentication bypass.
10 The whole SMM authentication variable design relies on the integrity of flash part and SMM.
11 which is assumed to be protected by platform. All variable code and metadata in flash/SMM Memory
12 may not be modified without authorization. If platform fails to protect these resources,
13 the authentication service provided in this driver will be broken, and the behavior is undefined.
14
15 ProcessVarWithPk(), ProcessVarWithKek() and ProcessVariable() are the function to do
16 variable authentication.
17
18 VerifyTimeBasedPayload() and VerifyCounterBasedPayload() are sub function to do verification.
19 They will do basic validation for authentication data structure, then call crypto library
20 to verify the signature.
21
22 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
23 This program and the accompanying materials
24 are licensed and made available under the terms and conditions of the BSD License
25 which accompanies this distribution. The full text of the license may be found at
26 http://opensource.org/licenses/bsd-license.php
27
28 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
29 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30
31 **/
32
33 #include "Variable.h"
34 #include "AuthService.h"
35
36 ///
37 /// Global database array for scratch
38 ///
39 UINT8 *mPubKeyStore;
40 UINT32 mPubKeyNumber;
41 UINT32 mMaxKeyNumber;
42 UINT32 mMaxKeyDbSize;
43 UINT8 *mCertDbStore;
44 UINT32 mMaxCertDbSize;
45 UINT32 mPlatformMode;
46 UINT8 mVendorKeyState;
47
48 EFI_GUID mSignatureSupport[] = {EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID};
49 //
50 // Public Exponent of RSA Key.
51 //
52 CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 };
53 //
54 // Hash context pointer
55 //
56 VOID *mHashCtx = NULL;
57
58 //
59 // The serialization of the values of the VariableName, VendorGuid and Attributes
60 // parameters of the SetVariable() call and the TimeStamp component of the
61 // EFI_VARIABLE_AUTHENTICATION_2 descriptor followed by the variable's new value
62 // i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data)
63 //
64 UINT8 *mSerializationRuntimeBuffer = NULL;
65
66 //
67 // Requirement for different signature type which have been defined in UEFI spec.
68 // These data are used to peform SignatureList format check while setting PK/KEK variable.
69 //
70 EFI_SIGNATURE_ITEM mSupportSigItem[] = {
71 //{SigType, SigHeaderSize, SigDataSize }
72 {EFI_CERT_SHA256_GUID, 0, 32 },
73 {EFI_CERT_RSA2048_GUID, 0, 256 },
74 {EFI_CERT_RSA2048_SHA256_GUID, 0, 256 },
75 {EFI_CERT_SHA1_GUID, 0, 20 },
76 {EFI_CERT_RSA2048_SHA1_GUID, 0, 256 },
77 {EFI_CERT_X509_GUID, 0, ((UINT32) ~0)},
78 {EFI_CERT_SHA224_GUID, 0, 28 },
79 {EFI_CERT_SHA384_GUID, 0, 48 },
80 {EFI_CERT_SHA512_GUID, 0, 64 }
81 };
82
83 /**
84 Determine whether this operation needs a physical present user.
85
86 @param[in] VariableName Name of the Variable.
87 @param[in] VendorGuid GUID of the Variable.
88
89 @retval TRUE This variable is protected, only a physical present user could set this variable.
90 @retval FALSE This variable is not protected.
91
92 **/
93 BOOLEAN
94 NeedPhysicallyPresent(
95 IN CHAR16 *VariableName,
96 IN EFI_GUID *VendorGuid
97 )
98 {
99 if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))
100 || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {
101 return TRUE;
102 }
103
104 return FALSE;
105 }
106
107 /**
108 Determine whether the platform is operating in Custom Secure Boot mode.
109
110 @retval TRUE The platform is operating in Custom mode.
111 @retval FALSE The platform is operating in Standard mode.
112
113 **/
114 BOOLEAN
115 InCustomMode (
116 VOID
117 )
118 {
119 VARIABLE_POINTER_TRACK Variable;
120
121 FindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
122 if (Variable.CurrPtr != NULL && *(GetVariableDataPtr (Variable.CurrPtr)) == CUSTOM_SECURE_BOOT_MODE) {
123 return TRUE;
124 }
125
126 return FALSE;
127 }
128
129
130 /**
131 Internal function to delete a Variable given its name and GUID, no authentication
132 required.
133
134 @param[in] VariableName Name of the Variable.
135 @param[in] VendorGuid GUID of the Variable.
136
137 @retval EFI_SUCCESS Variable deleted successfully.
138 @retval Others The driver failded to start the device.
139
140 **/
141 EFI_STATUS
142 DeleteVariable (
143 IN CHAR16 *VariableName,
144 IN EFI_GUID *VendorGuid
145 )
146 {
147 EFI_STATUS Status;
148 VARIABLE_POINTER_TRACK Variable;
149
150 Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
151 if (EFI_ERROR (Status)) {
152 return EFI_SUCCESS;
153 }
154
155 ASSERT (Variable.CurrPtr != NULL);
156 return UpdateVariable (VariableName, VendorGuid, NULL, 0, 0, 0, 0, &Variable, NULL);
157 }
158
159 /**
160 Initializes for authenticated varibale service.
161
162 @retval EFI_SUCCESS Function successfully executed.
163 @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resources.
164
165 **/
166 EFI_STATUS
167 AutenticatedVariableServiceInitialize (
168 VOID
169 )
170 {
171 EFI_STATUS Status;
172 VARIABLE_POINTER_TRACK Variable;
173 VARIABLE_POINTER_TRACK PkVariable;
174 UINT8 VarValue;
175 UINT32 VarAttr;
176 UINT8 *Data;
177 UINTN DataSize;
178 UINTN CtxSize;
179 UINT8 SecureBootMode;
180 UINT8 SecureBootEnable;
181 UINT8 CustomMode;
182 UINT32 ListSize;
183
184 //
185 // Initialize hash context.
186 //
187 CtxSize = Sha256GetContextSize ();
188 mHashCtx = AllocateRuntimePool (CtxSize);
189 if (mHashCtx == NULL) {
190 return EFI_OUT_OF_RESOURCES;
191 }
192
193 //
194 // Reserve runtime buffer for public key database. The size excludes variable header and name size.
195 //
196 mMaxKeyDbSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - sizeof (AUTHVAR_KEYDB_NAME);
197 mMaxKeyNumber = mMaxKeyDbSize / EFI_CERT_TYPE_RSA2048_SIZE;
198 mPubKeyStore = AllocateRuntimePool (mMaxKeyDbSize);
199 if (mPubKeyStore == NULL) {
200 return EFI_OUT_OF_RESOURCES;
201 }
202
203 //
204 // Reserve runtime buffer for certificate database. The size excludes variable header and name size.
205 //
206 mMaxCertDbSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - sizeof (EFI_CERT_DB_NAME);
207 mCertDbStore = AllocateRuntimePool (mMaxCertDbSize);
208 if (mCertDbStore == NULL) {
209 return EFI_OUT_OF_RESOURCES;
210 }
211
212 //
213 // Prepare runtime buffer for serialized data of time-based authenticated
214 // Variable, i.e. (VariableName, VendorGuid, Attributes, TimeStamp, Data).
215 //
216 mSerializationRuntimeBuffer = AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize) + sizeof (EFI_GUID) + sizeof (UINT32) + sizeof (EFI_TIME));
217 if (mSerializationRuntimeBuffer == NULL) {
218 return EFI_OUT_OF_RESOURCES;
219 }
220
221 //
222 // Check "AuthVarKeyDatabase" variable's existence.
223 // If it doesn't exist, create a new one with initial value of 0 and EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
224 //
225 Status = FindVariable (
226 AUTHVAR_KEYDB_NAME,
227 &gEfiAuthenticatedVariableGuid,
228 &Variable,
229 &mVariableModuleGlobal->VariableGlobal,
230 FALSE
231 );
232
233 if (Variable.CurrPtr == NULL) {
234 VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
235 VarValue = 0;
236 mPubKeyNumber = 0;
237 Status = UpdateVariable (
238 AUTHVAR_KEYDB_NAME,
239 &gEfiAuthenticatedVariableGuid,
240 &VarValue,
241 sizeof(UINT8),
242 VarAttr,
243 0,
244 0,
245 &Variable,
246 NULL
247 );
248 if (EFI_ERROR (Status)) {
249 return Status;
250 }
251 } else {
252 //
253 // Load database in global variable for cache.
254 //
255 DataSize = DataSizeOfVariable (Variable.CurrPtr);
256 Data = GetVariableDataPtr (Variable.CurrPtr);
257 ASSERT ((DataSize != 0) && (Data != NULL));
258 //
259 // "AuthVarKeyDatabase" is an internal variable. Its DataSize is always ensured not to exceed mPubKeyStore buffer size(See definition before)
260 // Therefore, there is no memory overflow in underlying CopyMem.
261 //
262 CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);
263 mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
264 }
265
266 FindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, &PkVariable, &mVariableModuleGlobal->VariableGlobal, FALSE);
267 if (PkVariable.CurrPtr == NULL) {
268 DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME));
269 } else {
270 DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME));
271 }
272
273 //
274 // Create "SetupMode" variable with BS+RT attribute set.
275 //
276 FindVariable (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
277 if (PkVariable.CurrPtr == NULL) {
278 mPlatformMode = SETUP_MODE;
279 } else {
280 mPlatformMode = USER_MODE;
281 }
282 Status = UpdateVariable (
283 EFI_SETUP_MODE_NAME,
284 &gEfiGlobalVariableGuid,
285 &mPlatformMode,
286 sizeof(UINT8),
287 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
288 0,
289 0,
290 &Variable,
291 NULL
292 );
293 if (EFI_ERROR (Status)) {
294 return Status;
295 }
296
297 //
298 // Create "SignatureSupport" variable with BS+RT attribute set.
299 //
300 FindVariable (EFI_SIGNATURE_SUPPORT_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
301 Status = UpdateVariable (
302 EFI_SIGNATURE_SUPPORT_NAME,
303 &gEfiGlobalVariableGuid,
304 mSignatureSupport,
305 sizeof(mSignatureSupport),
306 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
307 0,
308 0,
309 &Variable,
310 NULL
311 );
312 if (EFI_ERROR (Status)) {
313 return Status;
314 }
315
316 //
317 // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.
318 // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
319 // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.
320 //
321 SecureBootEnable = SECURE_BOOT_DISABLE;
322 FindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
323 if (Variable.CurrPtr != NULL) {
324 SecureBootEnable = *(GetVariableDataPtr (Variable.CurrPtr));
325 } else if (mPlatformMode == USER_MODE) {
326 //
327 // "SecureBootEnable" not exist, initialize it in USER_MODE.
328 //
329 SecureBootEnable = SECURE_BOOT_ENABLE;
330 Status = UpdateVariable (
331 EFI_SECURE_BOOT_ENABLE_NAME,
332 &gEfiSecureBootEnableDisableGuid,
333 &SecureBootEnable,
334 sizeof (UINT8),
335 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
336 0,
337 0,
338 &Variable,
339 NULL
340 );
341 if (EFI_ERROR (Status)) {
342 return Status;
343 }
344 }
345
346 //
347 // Create "SecureBoot" variable with BS+RT attribute set.
348 //
349 if (SecureBootEnable == SECURE_BOOT_ENABLE && mPlatformMode == USER_MODE) {
350 SecureBootMode = SECURE_BOOT_MODE_ENABLE;
351 } else {
352 SecureBootMode = SECURE_BOOT_MODE_DISABLE;
353 }
354 FindVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
355 Status = UpdateVariable (
356 EFI_SECURE_BOOT_MODE_NAME,
357 &gEfiGlobalVariableGuid,
358 &SecureBootMode,
359 sizeof (UINT8),
360 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
361 0,
362 0,
363 &Variable,
364 NULL
365 );
366 if (EFI_ERROR (Status)) {
367 return Status;
368 }
369
370 DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SETUP_MODE_NAME, mPlatformMode));
371 DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBootMode));
372 DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable));
373
374 //
375 // Initialize "CustomMode" in STANDARD_SECURE_BOOT_MODE state.
376 //
377 FindVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
378 CustomMode = STANDARD_SECURE_BOOT_MODE;
379 Status = UpdateVariable (
380 EFI_CUSTOM_MODE_NAME,
381 &gEfiCustomModeEnableGuid,
382 &CustomMode,
383 sizeof (UINT8),
384 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
385 0,
386 0,
387 &Variable,
388 NULL
389 );
390 if (EFI_ERROR (Status)) {
391 return Status;
392 }
393
394 DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, CustomMode));
395
396 //
397 // Check "certdb" variable's existence.
398 // If it doesn't exist, then create a new one with
399 // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
400 //
401 Status = FindVariable (
402 EFI_CERT_DB_NAME,
403 &gEfiCertDbGuid,
404 &Variable,
405 &mVariableModuleGlobal->VariableGlobal,
406 FALSE
407 );
408
409 if (Variable.CurrPtr == NULL) {
410 VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
411 ListSize = sizeof (UINT32);
412 Status = UpdateVariable (
413 EFI_CERT_DB_NAME,
414 &gEfiCertDbGuid,
415 &ListSize,
416 sizeof (UINT32),
417 VarAttr,
418 0,
419 0,
420 &Variable,
421 NULL
422 );
423 if (EFI_ERROR (Status)) {
424 return Status;
425 }
426 }
427
428 //
429 // Check "VendorKeysNv" variable's existence and create "VendorKeys" variable accordingly.
430 //
431 FindVariable (EFI_VENDOR_KEYS_NV_VARIABLE_NAME, &gEfiVendorKeysNvGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
432 if (Variable.CurrPtr != NULL) {
433 mVendorKeyState = *(GetVariableDataPtr (Variable.CurrPtr));
434 } else {
435 //
436 // "VendorKeysNv" not exist, initialize it in VENDOR_KEYS_VALID state.
437 //
438 mVendorKeyState = VENDOR_KEYS_VALID;
439 Status = UpdateVariable (
440 EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
441 &gEfiVendorKeysNvGuid,
442 &mVendorKeyState,
443 sizeof (UINT8),
444 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
445 0,
446 0,
447 &Variable,
448 NULL
449 );
450 if (EFI_ERROR (Status)) {
451 return Status;
452 }
453 }
454
455 //
456 // Create "VendorKeys" variable with BS+RT attribute set.
457 //
458 FindVariable (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
459 Status = UpdateVariable (
460 EFI_VENDOR_KEYS_VARIABLE_NAME,
461 &gEfiGlobalVariableGuid,
462 &mVendorKeyState,
463 sizeof (UINT8),
464 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
465 0,
466 0,
467 &Variable,
468 NULL
469 );
470 if (EFI_ERROR (Status)) {
471 return Status;
472 }
473
474 DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_VENDOR_KEYS_VARIABLE_NAME, mVendorKeyState));
475
476 return Status;
477 }
478
479 /**
480 Add public key in store and return its index.
481
482 @param[in] PubKey Input pointer to Public Key data
483 @param[in] VariableDataEntry The variable data entry
484
485 @return Index of new added item
486
487 **/
488 UINT32
489 AddPubKeyInStore (
490 IN UINT8 *PubKey,
491 IN VARIABLE_ENTRY_CONSISTENCY *VariableDataEntry
492 )
493 {
494 EFI_STATUS Status;
495 BOOLEAN IsFound;
496 UINT32 Index;
497 VARIABLE_POINTER_TRACK Variable;
498 UINT8 *Ptr;
499 UINT8 *Data;
500 UINTN DataSize;
501 VARIABLE_ENTRY_CONSISTENCY PublicKeyEntry;
502 UINT32 Attributes;
503
504 if (PubKey == NULL) {
505 return 0;
506 }
507
508 Status = FindVariable (
509 AUTHVAR_KEYDB_NAME,
510 &gEfiAuthenticatedVariableGuid,
511 &Variable,
512 &mVariableModuleGlobal->VariableGlobal,
513 FALSE
514 );
515 if (EFI_ERROR (Status)) {
516 DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = %r\n", Status));
517 return 0;
518 }
519
520 //
521 // Check whether the public key entry does exist.
522 //
523 IsFound = FALSE;
524 for (Ptr = mPubKeyStore, Index = 1; Index <= mPubKeyNumber; Index++) {
525 if (CompareMem (Ptr, PubKey, EFI_CERT_TYPE_RSA2048_SIZE) == 0) {
526 IsFound = TRUE;
527 break;
528 }
529 Ptr += EFI_CERT_TYPE_RSA2048_SIZE;
530 }
531
532 if (!IsFound) {
533 //
534 // Add public key in database.
535 //
536 if (mPubKeyNumber == mMaxKeyNumber) {
537 //
538 // Public key dadatase is full, try to reclaim invalid key.
539 //
540 if (AtRuntime ()) {
541 //
542 // NV storage can't reclaim at runtime.
543 //
544 return 0;
545 }
546
547 Status = Reclaim (
548 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
549 &mVariableModuleGlobal->NonVolatileLastVariableOffset,
550 FALSE,
551 NULL,
552 NULL,
553 0,
554 TRUE
555 );
556 if (EFI_ERROR (Status)) {
557 return 0;
558 }
559
560 Status = FindVariable (
561 AUTHVAR_KEYDB_NAME,
562 &gEfiAuthenticatedVariableGuid,
563 &Variable,
564 &mVariableModuleGlobal->VariableGlobal,
565 FALSE
566 );
567 if (EFI_ERROR (Status)) {
568 DEBUG ((EFI_D_ERROR, "Get public key database variable failure, Status = %r\n", Status));
569 return 0;
570 }
571
572 DataSize = DataSizeOfVariable (Variable.CurrPtr);
573 Data = GetVariableDataPtr (Variable.CurrPtr);
574 ASSERT ((DataSize != 0) && (Data != NULL));
575 //
576 // "AuthVarKeyDatabase" is an internal used variable. Its DataSize is always ensured not to exceed mPubKeyStore buffer size(See definition before)
577 // Therefore, there is no memory overflow in underlying CopyMem.
578 //
579 CopyMem (mPubKeyStore, (UINT8 *) Data, DataSize);
580 mPubKeyNumber = (UINT32) (DataSize / EFI_CERT_TYPE_RSA2048_SIZE);
581
582 if (mPubKeyNumber == mMaxKeyNumber) {
583 return 0;
584 }
585 }
586
587 //
588 // Check the variable space for both public key and variable data.
589 //
590 PublicKeyEntry.VariableSize = (mPubKeyNumber + 1) * EFI_CERT_TYPE_RSA2048_SIZE;
591 PublicKeyEntry.Guid = &gEfiAuthenticatedVariableGuid;
592 PublicKeyEntry.Name = AUTHVAR_KEYDB_NAME;
593 Attributes = VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS;
594
595 if (!CheckRemainingSpaceForConsistency (Attributes, &PublicKeyEntry, VariableDataEntry, NULL)) {
596 //
597 // No enough variable space.
598 //
599 return 0;
600 }
601
602 CopyMem (mPubKeyStore + mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
603 Index = ++mPubKeyNumber;
604 //
605 // Update public key database variable.
606 //
607 Status = UpdateVariable (
608 AUTHVAR_KEYDB_NAME,
609 &gEfiAuthenticatedVariableGuid,
610 mPubKeyStore,
611 mPubKeyNumber * EFI_CERT_TYPE_RSA2048_SIZE,
612 Attributes,
613 0,
614 0,
615 &Variable,
616 NULL
617 );
618 if (EFI_ERROR (Status)) {
619 DEBUG ((EFI_D_ERROR, "Update public key database variable failure, Status = %r\n", Status));
620 return 0;
621 }
622 }
623
624 return Index;
625 }
626
627 /**
628 Verify data payload with AuthInfo in EFI_CERT_TYPE_RSA2048_SHA256_GUID type.
629 Follow the steps in UEFI2.2.
630
631 Caution: This function may receive untrusted input.
632 This function may be invoked in SMM mode, and datasize and data are external input.
633 This function will do basic validation, before parse the data.
634 This function will parse the authentication carefully to avoid security issues, like
635 buffer overflow, integer overflow.
636
637 @param[in] Data Pointer to data with AuthInfo.
638 @param[in] DataSize Size of Data.
639 @param[in] PubKey Public key used for verification.
640
641 @retval EFI_INVALID_PARAMETER Invalid parameter.
642 @retval EFI_SECURITY_VIOLATION If authentication failed.
643 @retval EFI_SUCCESS Authentication successful.
644
645 **/
646 EFI_STATUS
647 VerifyCounterBasedPayload (
648 IN UINT8 *Data,
649 IN UINTN DataSize,
650 IN UINT8 *PubKey
651 )
652 {
653 BOOLEAN Status;
654 EFI_VARIABLE_AUTHENTICATION *CertData;
655 EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
656 UINT8 Digest[SHA256_DIGEST_SIZE];
657 VOID *Rsa;
658 UINTN PayloadSize;
659
660 PayloadSize = DataSize - AUTHINFO_SIZE;
661 Rsa = NULL;
662 CertData = NULL;
663 CertBlock = NULL;
664
665 if (Data == NULL || PubKey == NULL) {
666 return EFI_INVALID_PARAMETER;
667 }
668
669 CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
670 CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
671
672 //
673 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
674 // Cert type should be EFI_CERT_TYPE_RSA2048_SHA256_GUID.
675 //
676 if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
677 !CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertTypeRsa2048Sha256Guid)
678 ) {
679 //
680 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
681 //
682 return EFI_SECURITY_VIOLATION;
683 }
684 //
685 // Hash data payload with SHA256.
686 //
687 ZeroMem (Digest, SHA256_DIGEST_SIZE);
688 Status = Sha256Init (mHashCtx);
689 if (!Status) {
690 goto Done;
691 }
692 Status = Sha256Update (mHashCtx, Data + AUTHINFO_SIZE, PayloadSize);
693 if (!Status) {
694 goto Done;
695 }
696 //
697 // Hash Size.
698 //
699 Status = Sha256Update (mHashCtx, &PayloadSize, sizeof (UINTN));
700 if (!Status) {
701 goto Done;
702 }
703 //
704 // Hash Monotonic Count.
705 //
706 Status = Sha256Update (mHashCtx, &CertData->MonotonicCount, sizeof (UINT64));
707 if (!Status) {
708 goto Done;
709 }
710 Status = Sha256Final (mHashCtx, Digest);
711 if (!Status) {
712 goto Done;
713 }
714 //
715 // Generate & Initialize RSA Context.
716 //
717 Rsa = RsaNew ();
718 ASSERT (Rsa != NULL);
719 //
720 // Set RSA Key Components.
721 // NOTE: Only N and E are needed to be set as RSA public key for signature verification.
722 //
723 Status = RsaSetKey (Rsa, RsaKeyN, PubKey, EFI_CERT_TYPE_RSA2048_SIZE);
724 if (!Status) {
725 goto Done;
726 }
727 Status = RsaSetKey (Rsa, RsaKeyE, mRsaE, sizeof (mRsaE));
728 if (!Status) {
729 goto Done;
730 }
731 //
732 // Verify the signature.
733 //
734 Status = RsaPkcs1Verify (
735 Rsa,
736 Digest,
737 SHA256_DIGEST_SIZE,
738 CertBlock->Signature,
739 EFI_CERT_TYPE_RSA2048_SHA256_SIZE
740 );
741
742 Done:
743 if (Rsa != NULL) {
744 RsaFree (Rsa);
745 }
746 if (Status) {
747 return EFI_SUCCESS;
748 } else {
749 return EFI_SECURITY_VIOLATION;
750 }
751 }
752
753 /**
754 Update platform mode.
755
756 @param[in] Mode SETUP_MODE or USER_MODE.
757
758 @return EFI_INVALID_PARAMETER Invalid parameter.
759 @return EFI_SUCCESS Update platform mode successfully.
760
761 **/
762 EFI_STATUS
763 UpdatePlatformMode (
764 IN UINT32 Mode
765 )
766 {
767 EFI_STATUS Status;
768 VARIABLE_POINTER_TRACK Variable;
769 UINT8 SecureBootMode;
770 UINT8 SecureBootEnable;
771 UINTN VariableDataSize;
772
773 Status = FindVariable (
774 EFI_SETUP_MODE_NAME,
775 &gEfiGlobalVariableGuid,
776 &Variable,
777 &mVariableModuleGlobal->VariableGlobal,
778 FALSE
779 );
780 if (EFI_ERROR (Status)) {
781 return Status;
782 }
783
784 //
785 // Update the value of SetupMode variable by a simple mem copy, this could avoid possible
786 // variable storage reclaim at runtime.
787 //
788 mPlatformMode = (UINT8) Mode;
789 CopyMem (GetVariableDataPtr (Variable.CurrPtr), &mPlatformMode, sizeof(UINT8));
790
791 if (AtRuntime ()) {
792 //
793 // SecureBoot Variable indicates whether the platform firmware is operating
794 // in Secure boot mode (1) or not (0), so we should not change SecureBoot
795 // Variable in runtime.
796 //
797 return Status;
798 }
799
800 //
801 // Check "SecureBoot" variable's existence.
802 // If it doesn't exist, firmware has no capability to perform driver signing verification,
803 // then set "SecureBoot" to 0.
804 //
805 Status = FindVariable (
806 EFI_SECURE_BOOT_MODE_NAME,
807 &gEfiGlobalVariableGuid,
808 &Variable,
809 &mVariableModuleGlobal->VariableGlobal,
810 FALSE
811 );
812 //
813 // If "SecureBoot" variable exists, then check "SetupMode" variable update.
814 // If "SetupMode" variable is USER_MODE, "SecureBoot" variable is set to 1.
815 // If "SetupMode" variable is SETUP_MODE, "SecureBoot" variable is set to 0.
816 //
817 if (Variable.CurrPtr == NULL) {
818 SecureBootMode = SECURE_BOOT_MODE_DISABLE;
819 } else {
820 if (mPlatformMode == USER_MODE) {
821 SecureBootMode = SECURE_BOOT_MODE_ENABLE;
822 } else if (mPlatformMode == SETUP_MODE) {
823 SecureBootMode = SECURE_BOOT_MODE_DISABLE;
824 } else {
825 return EFI_NOT_FOUND;
826 }
827 }
828
829 Status = UpdateVariable (
830 EFI_SECURE_BOOT_MODE_NAME,
831 &gEfiGlobalVariableGuid,
832 &SecureBootMode,
833 sizeof(UINT8),
834 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
835 0,
836 0,
837 &Variable,
838 NULL
839 );
840 if (EFI_ERROR (Status)) {
841 return Status;
842 }
843
844 //
845 // Check "SecureBootEnable" variable's existence. It can enable/disable secure boot feature.
846 //
847 Status = FindVariable (
848 EFI_SECURE_BOOT_ENABLE_NAME,
849 &gEfiSecureBootEnableDisableGuid,
850 &Variable,
851 &mVariableModuleGlobal->VariableGlobal,
852 FALSE
853 );
854
855 if (SecureBootMode == SECURE_BOOT_MODE_ENABLE) {
856 //
857 // Create the "SecureBootEnable" variable as secure boot is enabled.
858 //
859 SecureBootEnable = SECURE_BOOT_ENABLE;
860 VariableDataSize = sizeof (SecureBootEnable);
861 } else {
862 //
863 // Delete the "SecureBootEnable" variable if this variable exist as "SecureBoot"
864 // variable is not in secure boot state.
865 //
866 if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
867 return EFI_SUCCESS;
868 }
869 SecureBootEnable = SECURE_BOOT_DISABLE;
870 VariableDataSize = 0;
871 }
872
873 Status = UpdateVariable (
874 EFI_SECURE_BOOT_ENABLE_NAME,
875 &gEfiSecureBootEnableDisableGuid,
876 &SecureBootEnable,
877 VariableDataSize,
878 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
879 0,
880 0,
881 &Variable,
882 NULL
883 );
884 return Status;
885 }
886
887 /**
888 Check input data form to make sure it is a valid EFI_SIGNATURE_LIST for PK/KEK/db/dbx variable.
889
890 @param[in] VariableName Name of Variable to be check.
891 @param[in] VendorGuid Variable vendor GUID.
892 @param[in] Data Point to the variable data to be checked.
893 @param[in] DataSize Size of Data.
894
895 @return EFI_INVALID_PARAMETER Invalid signature list format.
896 @return EFI_SUCCESS Passed signature list format check successfully.
897
898 **/
899 EFI_STATUS
900 CheckSignatureListFormat(
901 IN CHAR16 *VariableName,
902 IN EFI_GUID *VendorGuid,
903 IN VOID *Data,
904 IN UINTN DataSize
905 )
906 {
907 EFI_SIGNATURE_LIST *SigList;
908 UINTN SigDataSize;
909 UINT32 Index;
910 UINT32 SigCount;
911 BOOLEAN IsPk;
912 VOID *RsaContext;
913 EFI_SIGNATURE_DATA *CertData;
914 UINTN CertLen;
915
916 if (DataSize == 0) {
917 return EFI_SUCCESS;
918 }
919
920 ASSERT (VariableName != NULL && VendorGuid != NULL && Data != NULL);
921
922 if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0)){
923 IsPk = TRUE;
924 } else if ((CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0) ||
925 (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
926 (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0 || StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))){
927 IsPk = FALSE;
928 } else {
929 return EFI_SUCCESS;
930 }
931
932 SigCount = 0;
933 SigList = (EFI_SIGNATURE_LIST *) Data;
934 SigDataSize = DataSize;
935 RsaContext = NULL;
936
937 //
938 // Walk throuth the input signature list and check the data format.
939 // If any signature is incorrectly formed, the whole check will fail.
940 //
941 while ((SigDataSize > 0) && (SigDataSize >= SigList->SignatureListSize)) {
942 for (Index = 0; Index < (sizeof (mSupportSigItem) / sizeof (EFI_SIGNATURE_ITEM)); Index++ ) {
943 if (CompareGuid (&SigList->SignatureType, &mSupportSigItem[Index].SigType)) {
944 //
945 // The value of SignatureSize should always be 16 (size of SignatureOwner
946 // component) add the data length according to signature type.
947 //
948 if (mSupportSigItem[Index].SigDataSize != ((UINT32) ~0) &&
949 (SigList->SignatureSize - sizeof (EFI_GUID)) != mSupportSigItem[Index].SigDataSize) {
950 return EFI_INVALID_PARAMETER;
951 }
952 if (mSupportSigItem[Index].SigHeaderSize != ((UINTN) ~0) &&
953 SigList->SignatureHeaderSize != mSupportSigItem[Index].SigHeaderSize) {
954 return EFI_INVALID_PARAMETER;
955 }
956 break;
957 }
958 }
959
960 if (Index == (sizeof (mSupportSigItem) / sizeof (EFI_SIGNATURE_ITEM))) {
961 //
962 // Undefined signature type.
963 //
964 return EFI_INVALID_PARAMETER;
965 }
966
967 if (CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {
968 //
969 // Try to retrieve the RSA public key from the X.509 certificate.
970 // If this operation fails, it's not a valid certificate.
971 //
972 RsaContext = RsaNew ();
973 if (RsaContext == NULL) {
974 return EFI_INVALID_PARAMETER;
975 }
976 CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize);
977 CertLen = SigList->SignatureSize - sizeof (EFI_GUID);
978 if (!RsaGetPublicKeyFromX509 (CertData->SignatureData, CertLen, &RsaContext)) {
979 RsaFree (RsaContext);
980 return EFI_INVALID_PARAMETER;
981 }
982 RsaFree (RsaContext);
983 }
984
985 if ((SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) % SigList->SignatureSize != 0) {
986 return EFI_INVALID_PARAMETER;
987 }
988 SigCount += (SigList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - SigList->SignatureHeaderSize) / SigList->SignatureSize;
989
990 SigDataSize -= SigList->SignatureListSize;
991 SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize);
992 }
993
994 if (((UINTN) SigList - (UINTN) Data) != DataSize) {
995 return EFI_INVALID_PARAMETER;
996 }
997
998 if (IsPk && SigCount > 1) {
999 return EFI_INVALID_PARAMETER;
1000 }
1001
1002 return EFI_SUCCESS;
1003 }
1004
1005 /**
1006 Update "VendorKeys" variable to record the out of band secure boot key modification.
1007
1008 @return EFI_SUCCESS Variable is updated successfully.
1009 @return Others Failed to update variable.
1010
1011 **/
1012 EFI_STATUS
1013 VendorKeyIsModified (
1014 VOID
1015 )
1016 {
1017 EFI_STATUS Status;
1018 VARIABLE_POINTER_TRACK Variable;
1019
1020 if (mVendorKeyState == VENDOR_KEYS_MODIFIED) {
1021 return EFI_SUCCESS;
1022 }
1023 mVendorKeyState = VENDOR_KEYS_MODIFIED;
1024
1025 FindVariable (EFI_VENDOR_KEYS_NV_VARIABLE_NAME, &gEfiVendorKeysNvGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
1026 Status = UpdateVariable (
1027 EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
1028 &gEfiVendorKeysNvGuid,
1029 &mVendorKeyState,
1030 sizeof (UINT8),
1031 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
1032 0,
1033 0,
1034 &Variable,
1035 NULL
1036 );
1037 if (EFI_ERROR (Status)) {
1038 return Status;
1039 }
1040
1041 FindVariable (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
1042 return UpdateVariable (
1043 EFI_VENDOR_KEYS_VARIABLE_NAME,
1044 &gEfiGlobalVariableGuid,
1045 &mVendorKeyState,
1046 sizeof (UINT8),
1047 EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1048 0,
1049 0,
1050 &Variable,
1051 NULL
1052 );
1053 }
1054
1055 /**
1056 Process variable with platform key for verification.
1057
1058 Caution: This function may receive untrusted input.
1059 This function may be invoked in SMM mode, and datasize and data are external input.
1060 This function will do basic validation, before parse the data.
1061 This function will parse the authentication carefully to avoid security issues, like
1062 buffer overflow, integer overflow.
1063 This function will check attribute carefully to avoid authentication bypass.
1064
1065 @param[in] VariableName Name of Variable to be found.
1066 @param[in] VendorGuid Variable vendor GUID.
1067 @param[in] Data Data pointer.
1068 @param[in] DataSize Size of Data found. If size is less than the
1069 data, this value contains the required size.
1070 @param[in] Variable The variable information which is used to keep track of variable usage.
1071 @param[in] Attributes Attribute value of the variable
1072 @param[in] IsPk Indicate whether it is to process pk.
1073
1074 @return EFI_INVALID_PARAMETER Invalid parameter.
1075 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation.
1076 check carried out by the firmware.
1077 @return EFI_SUCCESS Variable passed validation successfully.
1078
1079 **/
1080 EFI_STATUS
1081 ProcessVarWithPk (
1082 IN CHAR16 *VariableName,
1083 IN EFI_GUID *VendorGuid,
1084 IN VOID *Data,
1085 IN UINTN DataSize,
1086 IN VARIABLE_POINTER_TRACK *Variable,
1087 IN UINT32 Attributes OPTIONAL,
1088 IN BOOLEAN IsPk
1089 )
1090 {
1091 EFI_STATUS Status;
1092 BOOLEAN Del;
1093 UINT8 *Payload;
1094 UINTN PayloadSize;
1095
1096 if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||
1097 (Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {
1098 //
1099 // PK, KEK and db/dbx should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
1100 // authenticated variable.
1101 //
1102 return EFI_INVALID_PARAMETER;
1103 }
1104
1105 Del = FALSE;
1106 if ((InCustomMode() && UserPhysicalPresent()) || (mPlatformMode == SETUP_MODE && !IsPk)) {
1107 Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);
1108 PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
1109 if (PayloadSize == 0) {
1110 Del = TRUE;
1111 }
1112
1113 Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);
1114 if (EFI_ERROR (Status)) {
1115 return Status;
1116 }
1117
1118 Status = UpdateVariable (
1119 VariableName,
1120 VendorGuid,
1121 Payload,
1122 PayloadSize,
1123 Attributes,
1124 0,
1125 0,
1126 Variable,
1127 &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp
1128 );
1129 if (EFI_ERROR(Status)) {
1130 return Status;
1131 }
1132
1133 if ((mPlatformMode != SETUP_MODE) || IsPk) {
1134 Status = VendorKeyIsModified ();
1135 }
1136 } else if (mPlatformMode == USER_MODE) {
1137 //
1138 // Verify against X509 Cert in PK database.
1139 //
1140 Status = VerifyTimeBasedPayload (
1141 VariableName,
1142 VendorGuid,
1143 Data,
1144 DataSize,
1145 Variable,
1146 Attributes,
1147 AuthVarTypePk,
1148 &Del
1149 );
1150 } else {
1151 //
1152 // Verify against the certificate in data payload.
1153 //
1154 Status = VerifyTimeBasedPayload (
1155 VariableName,
1156 VendorGuid,
1157 Data,
1158 DataSize,
1159 Variable,
1160 Attributes,
1161 AuthVarTypePayload,
1162 &Del
1163 );
1164 }
1165
1166 if (!EFI_ERROR(Status) && IsPk) {
1167 if (mPlatformMode == SETUP_MODE && !Del) {
1168 //
1169 // If enroll PK in setup mode, need change to user mode.
1170 //
1171 Status = UpdatePlatformMode (USER_MODE);
1172 } else if (mPlatformMode == USER_MODE && Del){
1173 //
1174 // If delete PK in user mode, need change to setup mode.
1175 //
1176 Status = UpdatePlatformMode (SETUP_MODE);
1177 }
1178 }
1179
1180 return Status;
1181 }
1182
1183 /**
1184 Process variable with key exchange key for verification.
1185
1186 Caution: This function may receive untrusted input.
1187 This function may be invoked in SMM mode, and datasize and data are external input.
1188 This function will do basic validation, before parse the data.
1189 This function will parse the authentication carefully to avoid security issues, like
1190 buffer overflow, integer overflow.
1191 This function will check attribute carefully to avoid authentication bypass.
1192
1193 @param[in] VariableName Name of Variable to be found.
1194 @param[in] VendorGuid Variable vendor GUID.
1195 @param[in] Data Data pointer.
1196 @param[in] DataSize Size of Data found. If size is less than the
1197 data, this value contains the required size.
1198 @param[in] Variable The variable information which is used to keep track of variable usage.
1199 @param[in] Attributes Attribute value of the variable.
1200
1201 @return EFI_INVALID_PARAMETER Invalid parameter.
1202 @return EFI_SECURITY_VIOLATION The variable does NOT pass the validation
1203 check carried out by the firmware.
1204 @return EFI_SUCCESS Variable pass validation successfully.
1205
1206 **/
1207 EFI_STATUS
1208 ProcessVarWithKek (
1209 IN CHAR16 *VariableName,
1210 IN EFI_GUID *VendorGuid,
1211 IN VOID *Data,
1212 IN UINTN DataSize,
1213 IN VARIABLE_POINTER_TRACK *Variable,
1214 IN UINT32 Attributes OPTIONAL
1215 )
1216 {
1217 EFI_STATUS Status;
1218 UINT8 *Payload;
1219 UINTN PayloadSize;
1220
1221 if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0 ||
1222 (Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == 0) {
1223 //
1224 // DB and DBX should set EFI_VARIABLE_NON_VOLATILE attribute and should be a time-based
1225 // authenticated variable.
1226 //
1227 return EFI_INVALID_PARAMETER;
1228 }
1229
1230 Status = EFI_SUCCESS;
1231 if (mPlatformMode == USER_MODE && !(InCustomMode() && UserPhysicalPresent())) {
1232 //
1233 // Time-based, verify against X509 Cert KEK.
1234 //
1235 return VerifyTimeBasedPayload (
1236 VariableName,
1237 VendorGuid,
1238 Data,
1239 DataSize,
1240 Variable,
1241 Attributes,
1242 AuthVarTypeKek,
1243 NULL
1244 );
1245 } else {
1246 //
1247 // If in setup mode or custom secure boot mode, no authentication needed.
1248 //
1249 Payload = (UINT8 *) Data + AUTHINFO2_SIZE (Data);
1250 PayloadSize = DataSize - AUTHINFO2_SIZE (Data);
1251
1252 Status = CheckSignatureListFormat(VariableName, VendorGuid, Payload, PayloadSize);
1253 if (EFI_ERROR (Status)) {
1254 return Status;
1255 }
1256
1257 Status = UpdateVariable (
1258 VariableName,
1259 VendorGuid,
1260 Payload,
1261 PayloadSize,
1262 Attributes,
1263 0,
1264 0,
1265 Variable,
1266 &((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->TimeStamp
1267 );
1268 if (EFI_ERROR (Status)) {
1269 return Status;
1270 }
1271
1272 if (mPlatformMode != SETUP_MODE) {
1273 Status = VendorKeyIsModified ();
1274 }
1275 }
1276
1277 return Status;
1278 }
1279
1280 /**
1281 Process variable with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS/EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
1282
1283 Caution: This function may receive untrusted input.
1284 This function may be invoked in SMM mode, and datasize and data are external input.
1285 This function will do basic validation, before parse the data.
1286 This function will parse the authentication carefully to avoid security issues, like
1287 buffer overflow, integer overflow.
1288 This function will check attribute carefully to avoid authentication bypass.
1289
1290 @param[in] VariableName Name of Variable to be found.
1291 @param[in] VendorGuid Variable vendor GUID.
1292
1293 @param[in] Data Data pointer.
1294 @param[in] DataSize Size of Data found. If size is less than the
1295 data, this value contains the required size.
1296 @param[in] Variable The variable information which is used to keep track of variable usage.
1297 @param[in] Attributes Attribute value of the variable.
1298
1299 @return EFI_INVALID_PARAMETER Invalid parameter.
1300 @return EFI_WRITE_PROTECTED Variable is write-protected and needs authentication with
1301 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
1302 @return EFI_OUT_OF_RESOURCES The Database to save the public key is full.
1303 @return EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
1304 set, but the AuthInfo does NOT pass the validation
1305 check carried out by the firmware.
1306 @return EFI_SUCCESS Variable is not write-protected or pass validation successfully.
1307
1308 **/
1309 EFI_STATUS
1310 ProcessVariable (
1311 IN CHAR16 *VariableName,
1312 IN EFI_GUID *VendorGuid,
1313 IN VOID *Data,
1314 IN UINTN DataSize,
1315 IN VARIABLE_POINTER_TRACK *Variable,
1316 IN UINT32 Attributes
1317 )
1318 {
1319 EFI_STATUS Status;
1320 BOOLEAN IsDeletion;
1321 BOOLEAN IsFirstTime;
1322 UINT8 *PubKey;
1323 EFI_VARIABLE_AUTHENTICATION *CertData;
1324 EFI_CERT_BLOCK_RSA_2048_SHA256 *CertBlock;
1325 UINT32 KeyIndex;
1326 UINT64 MonotonicCount;
1327 VARIABLE_ENTRY_CONSISTENCY VariableDataEntry;
1328
1329 KeyIndex = 0;
1330 CertData = NULL;
1331 CertBlock = NULL;
1332 PubKey = NULL;
1333 IsDeletion = FALSE;
1334
1335 if (NeedPhysicallyPresent(VariableName, VendorGuid) && !UserPhysicalPresent()) {
1336 //
1337 // This variable is protected, only physical present user could modify its value.
1338 //
1339 return EFI_SECURITY_VIOLATION;
1340 }
1341
1342 //
1343 // A time-based authenticated variable and a count-based authenticated variable
1344 // can't be updated by each other.
1345 //
1346 if (Variable->CurrPtr != NULL) {
1347 if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) &&
1348 ((Variable->CurrPtr->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0)) {
1349 return EFI_SECURITY_VIOLATION;
1350 }
1351
1352 if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&
1353 ((Variable->CurrPtr->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0)) {
1354 return EFI_SECURITY_VIOLATION;
1355 }
1356 }
1357
1358 //
1359 // Process Time-based Authenticated variable.
1360 //
1361 if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
1362 return VerifyTimeBasedPayload (
1363 VariableName,
1364 VendorGuid,
1365 Data,
1366 DataSize,
1367 Variable,
1368 Attributes,
1369 AuthVarTypePriv,
1370 NULL
1371 );
1372 }
1373
1374 //
1375 // Determine if first time SetVariable with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS.
1376 //
1377 if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
1378 //
1379 // Determine current operation type.
1380 //
1381 if (DataSize == AUTHINFO_SIZE) {
1382 IsDeletion = TRUE;
1383 }
1384 //
1385 // Determine whether this is the first time with EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS set.
1386 //
1387 if (Variable->CurrPtr == NULL) {
1388 IsFirstTime = TRUE;
1389 } else if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == 0) {
1390 IsFirstTime = TRUE;
1391 } else {
1392 KeyIndex = Variable->CurrPtr->PubKeyIndex;
1393 IsFirstTime = FALSE;
1394 }
1395 } else if ((Variable->CurrPtr != NULL) &&
1396 ((Variable->CurrPtr->Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) != 0)
1397 ) {
1398 //
1399 // If the variable is already write-protected, it always needs authentication before update.
1400 //
1401 return EFI_WRITE_PROTECTED;
1402 } else {
1403 //
1404 // If without EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, set and attributes collision.
1405 // That means it is not authenticated variable, just update variable as usual.
1406 //
1407 Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, Variable, NULL);
1408 return Status;
1409 }
1410
1411 //
1412 // Get PubKey and check Monotonic Count value corresponding to the variable.
1413 //
1414 CertData = (EFI_VARIABLE_AUTHENTICATION *) Data;
1415 CertBlock = (EFI_CERT_BLOCK_RSA_2048_SHA256 *) (CertData->AuthInfo.CertData);
1416 PubKey = CertBlock->PublicKey;
1417
1418 //
1419 // Update Monotonic Count value.
1420 //
1421 MonotonicCount = CertData->MonotonicCount;
1422
1423 if (!IsFirstTime) {
1424 //
1425 // 2 cases need to check here
1426 // 1. Internal PubKey variable. PubKeyIndex is always 0
1427 // 2. Other counter-based AuthVariable. Check input PubKey.
1428 //
1429 if (KeyIndex == 0 || CompareMem (PubKey, mPubKeyStore + (KeyIndex - 1) * EFI_CERT_TYPE_RSA2048_SIZE, EFI_CERT_TYPE_RSA2048_SIZE) != 0) {
1430 return EFI_SECURITY_VIOLATION;
1431 }
1432 //
1433 // Compare the current monotonic count and ensure that it is greater than the last SetVariable
1434 // operation with the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS attribute set.
1435 //
1436 if (CertData->MonotonicCount <= Variable->CurrPtr->MonotonicCount) {
1437 //
1438 // Monotonic count check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
1439 //
1440 return EFI_SECURITY_VIOLATION;
1441 }
1442 }
1443 //
1444 // Verify the certificate in Data payload.
1445 //
1446 Status = VerifyCounterBasedPayload (Data, DataSize, PubKey);
1447 if (EFI_ERROR (Status)) {
1448 return Status;
1449 }
1450
1451 //
1452 // Now, the signature has been verified!
1453 //
1454 if (IsFirstTime && !IsDeletion) {
1455 VariableDataEntry.VariableSize = DataSize - AUTHINFO_SIZE;
1456 VariableDataEntry.Guid = VendorGuid;
1457 VariableDataEntry.Name = VariableName;
1458
1459 //
1460 // Update public key database variable if need.
1461 //
1462 KeyIndex = AddPubKeyInStore (PubKey, &VariableDataEntry);
1463 if (KeyIndex == 0) {
1464 return EFI_OUT_OF_RESOURCES;
1465 }
1466 }
1467
1468 //
1469 // Verification pass.
1470 //
1471 return UpdateVariable (VariableName, VendorGuid, (UINT8*)Data + AUTHINFO_SIZE, DataSize - AUTHINFO_SIZE, Attributes, KeyIndex, MonotonicCount, Variable, NULL);
1472 }
1473
1474 /**
1475 Merge two buffers which formatted as EFI_SIGNATURE_LIST. Only the new EFI_SIGNATURE_DATA
1476 will be appended to the original EFI_SIGNATURE_LIST, duplicate EFI_SIGNATURE_DATA
1477 will be ignored.
1478
1479 @param[in, out] Data Pointer to original EFI_SIGNATURE_LIST.
1480 @param[in] DataSize Size of Data buffer.
1481 @param[in] FreeBufSize Size of free data buffer
1482 @param[in] NewData Pointer to new EFI_SIGNATURE_LIST to be appended.
1483 @param[in] NewDataSize Size of NewData buffer.
1484 @param[out] MergedBufSize Size of the merged buffer
1485
1486 @return EFI_BUFFER_TOO_SMALL if input Data buffer overflowed
1487
1488 **/
1489 EFI_STATUS
1490 AppendSignatureList (
1491 IN OUT VOID *Data,
1492 IN UINTN DataSize,
1493 IN UINTN FreeBufSize,
1494 IN VOID *NewData,
1495 IN UINTN NewDataSize,
1496 OUT UINTN *MergedBufSize
1497 )
1498 {
1499 EFI_SIGNATURE_LIST *CertList;
1500 EFI_SIGNATURE_DATA *Cert;
1501 UINTN CertCount;
1502 EFI_SIGNATURE_LIST *NewCertList;
1503 EFI_SIGNATURE_DATA *NewCert;
1504 UINTN NewCertCount;
1505 UINTN Index;
1506 UINTN Index2;
1507 UINTN Size;
1508 UINT8 *Tail;
1509 UINTN CopiedCount;
1510 UINTN SignatureListSize;
1511 BOOLEAN IsNewCert;
1512
1513 Tail = (UINT8 *) Data + DataSize;
1514
1515 NewCertList = (EFI_SIGNATURE_LIST *) NewData;
1516 while ((NewDataSize > 0) && (NewDataSize >= NewCertList->SignatureListSize)) {
1517 NewCert = (EFI_SIGNATURE_DATA *) ((UINT8 *) NewCertList + sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize);
1518 NewCertCount = (NewCertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - NewCertList->SignatureHeaderSize) / NewCertList->SignatureSize;
1519
1520 CopiedCount = 0;
1521 for (Index = 0; Index < NewCertCount; Index++) {
1522 IsNewCert = TRUE;
1523
1524 Size = DataSize;
1525 CertList = (EFI_SIGNATURE_LIST *) Data;
1526 while ((Size > 0) && (Size >= CertList->SignatureListSize)) {
1527 if (CompareGuid (&CertList->SignatureType, &NewCertList->SignatureType) &&
1528 (CertList->SignatureSize == NewCertList->SignatureSize)) {
1529 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
1530 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
1531 for (Index2 = 0; Index2 < CertCount; Index2++) {
1532 //
1533 // Iterate each Signature Data in this Signature List.
1534 //
1535 if (CompareMem (NewCert, Cert, CertList->SignatureSize) == 0) {
1536 IsNewCert = FALSE;
1537 break;
1538 }
1539 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
1540 }
1541 }
1542
1543 if (!IsNewCert) {
1544 break;
1545 }
1546 Size -= CertList->SignatureListSize;
1547 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
1548 }
1549
1550 if (IsNewCert) {
1551 //
1552 // New EFI_SIGNATURE_DATA, append it.
1553 //
1554 if (CopiedCount == 0) {
1555 if (FreeBufSize < sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize) {
1556 return EFI_BUFFER_TOO_SMALL;
1557 }
1558
1559 //
1560 // Copy EFI_SIGNATURE_LIST header for only once.
1561 //
1562
1563 CopyMem (Tail, NewCertList, sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize);
1564 Tail = Tail + sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize;
1565 FreeBufSize -= sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize;
1566 }
1567
1568 if (FreeBufSize < NewCertList->SignatureSize) {
1569 return EFI_BUFFER_TOO_SMALL;
1570 }
1571 CopyMem (Tail, NewCert, NewCertList->SignatureSize);
1572 Tail += NewCertList->SignatureSize;
1573 FreeBufSize -= NewCertList->SignatureSize;
1574 CopiedCount++;
1575 }
1576
1577 NewCert = (EFI_SIGNATURE_DATA *) ((UINT8 *) NewCert + NewCertList->SignatureSize);
1578 }
1579
1580 //
1581 // Update SignatureListSize in newly appended EFI_SIGNATURE_LIST.
1582 //
1583 if (CopiedCount != 0) {
1584 SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize + (CopiedCount * NewCertList->SignatureSize);
1585 CertList = (EFI_SIGNATURE_LIST *) (Tail - SignatureListSize);
1586 CertList->SignatureListSize = (UINT32) SignatureListSize;
1587 }
1588
1589 NewDataSize -= NewCertList->SignatureListSize;
1590 NewCertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) NewCertList + NewCertList->SignatureListSize);
1591 }
1592
1593 *MergedBufSize = (Tail - (UINT8 *) Data);
1594 return EFI_SUCCESS;
1595 }
1596
1597 /**
1598 Compare two EFI_TIME data.
1599
1600
1601 @param FirstTime A pointer to the first EFI_TIME data.
1602 @param SecondTime A pointer to the second EFI_TIME data.
1603
1604 @retval TRUE The FirstTime is not later than the SecondTime.
1605 @retval FALSE The FirstTime is later than the SecondTime.
1606
1607 **/
1608 BOOLEAN
1609 CompareTimeStamp (
1610 IN EFI_TIME *FirstTime,
1611 IN EFI_TIME *SecondTime
1612 )
1613 {
1614 if (FirstTime->Year != SecondTime->Year) {
1615 return (BOOLEAN) (FirstTime->Year < SecondTime->Year);
1616 } else if (FirstTime->Month != SecondTime->Month) {
1617 return (BOOLEAN) (FirstTime->Month < SecondTime->Month);
1618 } else if (FirstTime->Day != SecondTime->Day) {
1619 return (BOOLEAN) (FirstTime->Day < SecondTime->Day);
1620 } else if (FirstTime->Hour != SecondTime->Hour) {
1621 return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
1622 } else if (FirstTime->Minute != SecondTime->Minute) {
1623 return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute);
1624 }
1625
1626 return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);
1627 }
1628
1629 /**
1630 Find matching signer's certificates for common authenticated variable
1631 by corresponding VariableName and VendorGuid from "certdb".
1632
1633 The data format of "certdb":
1634 //
1635 // UINT32 CertDbListSize;
1636 // /// AUTH_CERT_DB_DATA Certs1[];
1637 // /// AUTH_CERT_DB_DATA Certs2[];
1638 // /// ...
1639 // /// AUTH_CERT_DB_DATA Certsn[];
1640 //
1641
1642 @param[in] VariableName Name of authenticated Variable.
1643 @param[in] VendorGuid Vendor GUID of authenticated Variable.
1644 @param[in] Data Pointer to variable "certdb".
1645 @param[in] DataSize Size of variable "certdb".
1646 @param[out] CertOffset Offset of matching CertData, from starting of Data.
1647 @param[out] CertDataSize Length of CertData in bytes.
1648 @param[out] CertNodeOffset Offset of matching AUTH_CERT_DB_DATA , from
1649 starting of Data.
1650 @param[out] CertNodeSize Length of AUTH_CERT_DB_DATA in bytes.
1651
1652 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1653 @retval EFI_NOT_FOUND Fail to find matching certs.
1654 @retval EFI_SUCCESS Find matching certs and output parameters.
1655
1656 **/
1657 EFI_STATUS
1658 FindCertsFromDb (
1659 IN CHAR16 *VariableName,
1660 IN EFI_GUID *VendorGuid,
1661 IN UINT8 *Data,
1662 IN UINTN DataSize,
1663 OUT UINT32 *CertOffset, OPTIONAL
1664 OUT UINT32 *CertDataSize, OPTIONAL
1665 OUT UINT32 *CertNodeOffset,OPTIONAL
1666 OUT UINT32 *CertNodeSize OPTIONAL
1667 )
1668 {
1669 UINT32 Offset;
1670 AUTH_CERT_DB_DATA *Ptr;
1671 UINT32 CertSize;
1672 UINT32 NameSize;
1673 UINT32 NodeSize;
1674 UINT32 CertDbListSize;
1675
1676 if ((VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) {
1677 return EFI_INVALID_PARAMETER;
1678 }
1679
1680 //
1681 // Check whether DataSize matches recorded CertDbListSize.
1682 //
1683 if (DataSize < sizeof (UINT32)) {
1684 return EFI_INVALID_PARAMETER;
1685 }
1686
1687 CertDbListSize = ReadUnaligned32 ((UINT32 *) Data);
1688
1689 if (CertDbListSize != (UINT32) DataSize) {
1690 return EFI_INVALID_PARAMETER;
1691 }
1692
1693 Offset = sizeof (UINT32);
1694
1695 //
1696 // Get corresponding certificates by VendorGuid and VariableName.
1697 //
1698 while (Offset < (UINT32) DataSize) {
1699 Ptr = (AUTH_CERT_DB_DATA *) (Data + Offset);
1700 //
1701 // Check whether VendorGuid matches.
1702 //
1703 if (CompareGuid (&Ptr->VendorGuid, VendorGuid)) {
1704 NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize);
1705 NameSize = ReadUnaligned32 (&Ptr->NameSize);
1706 CertSize = ReadUnaligned32 (&Ptr->CertDataSize);
1707
1708 if (NodeSize != sizeof (EFI_GUID) + sizeof (UINT32) * 3 + CertSize +
1709 sizeof (CHAR16) * NameSize) {
1710 return EFI_INVALID_PARAMETER;
1711 }
1712
1713 Offset = Offset + sizeof (EFI_GUID) + sizeof (UINT32) * 3;
1714 //
1715 // Check whether VariableName matches.
1716 //
1717 if ((NameSize == StrLen (VariableName)) &&
1718 (CompareMem (Data + Offset, VariableName, NameSize * sizeof (CHAR16)) == 0)) {
1719 Offset = Offset + NameSize * sizeof (CHAR16);
1720
1721 if (CertOffset != NULL) {
1722 *CertOffset = Offset;
1723 }
1724
1725 if (CertDataSize != NULL) {
1726 *CertDataSize = CertSize;
1727 }
1728
1729 if (CertNodeOffset != NULL) {
1730 *CertNodeOffset = (UINT32) ((UINT8 *) Ptr - Data);
1731 }
1732
1733 if (CertNodeSize != NULL) {
1734 *CertNodeSize = NodeSize;
1735 }
1736
1737 return EFI_SUCCESS;
1738 } else {
1739 Offset = Offset + NameSize * sizeof (CHAR16) + CertSize;
1740 }
1741 } else {
1742 NodeSize = ReadUnaligned32 (&Ptr->CertNodeSize);
1743 Offset = Offset + NodeSize;
1744 }
1745 }
1746
1747 return EFI_NOT_FOUND;
1748 }
1749
1750 /**
1751 Retrieve signer's certificates for common authenticated variable
1752 by corresponding VariableName and VendorGuid from "certdb".
1753
1754 @param[in] VariableName Name of authenticated Variable.
1755 @param[in] VendorGuid Vendor GUID of authenticated Variable.
1756 @param[out] CertData Pointer to signer's certificates.
1757 @param[out] CertDataSize Length of CertData in bytes.
1758
1759 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1760 @retval EFI_NOT_FOUND Fail to find "certdb" or matching certs.
1761 @retval EFI_SUCCESS Get signer's certificates successfully.
1762
1763 **/
1764 EFI_STATUS
1765 GetCertsFromDb (
1766 IN CHAR16 *VariableName,
1767 IN EFI_GUID *VendorGuid,
1768 OUT UINT8 **CertData,
1769 OUT UINT32 *CertDataSize
1770 )
1771 {
1772 VARIABLE_POINTER_TRACK CertDbVariable;
1773 EFI_STATUS Status;
1774 UINT8 *Data;
1775 UINTN DataSize;
1776 UINT32 CertOffset;
1777
1778 if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL) || (CertDataSize == NULL)) {
1779 return EFI_INVALID_PARAMETER;
1780 }
1781
1782 //
1783 // Get variable "certdb".
1784 //
1785 Status = FindVariable (
1786 EFI_CERT_DB_NAME,
1787 &gEfiCertDbGuid,
1788 &CertDbVariable,
1789 &mVariableModuleGlobal->VariableGlobal,
1790 FALSE
1791 );
1792 if (EFI_ERROR (Status)) {
1793 return Status;
1794 }
1795
1796 DataSize = DataSizeOfVariable (CertDbVariable.CurrPtr);
1797 Data = GetVariableDataPtr (CertDbVariable.CurrPtr);
1798 if ((DataSize == 0) || (Data == NULL)) {
1799 ASSERT (FALSE);
1800 return EFI_NOT_FOUND;
1801 }
1802
1803 Status = FindCertsFromDb (
1804 VariableName,
1805 VendorGuid,
1806 Data,
1807 DataSize,
1808 &CertOffset,
1809 CertDataSize,
1810 NULL,
1811 NULL
1812 );
1813
1814 if (EFI_ERROR (Status)) {
1815 return Status;
1816 }
1817
1818 *CertData = Data + CertOffset;
1819 return EFI_SUCCESS;
1820 }
1821
1822 /**
1823 Delete matching signer's certificates when deleting common authenticated
1824 variable by corresponding VariableName and VendorGuid from "certdb".
1825
1826 @param[in] VariableName Name of authenticated Variable.
1827 @param[in] VendorGuid Vendor GUID of authenticated Variable.
1828
1829 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1830 @retval EFI_NOT_FOUND Fail to find "certdb" or matching certs.
1831 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
1832 @retval EFI_SUCCESS The operation is completed successfully.
1833
1834 **/
1835 EFI_STATUS
1836 DeleteCertsFromDb (
1837 IN CHAR16 *VariableName,
1838 IN EFI_GUID *VendorGuid
1839 )
1840 {
1841 VARIABLE_POINTER_TRACK CertDbVariable;
1842 EFI_STATUS Status;
1843 UINT8 *Data;
1844 UINTN DataSize;
1845 UINT32 VarAttr;
1846 UINT32 CertNodeOffset;
1847 UINT32 CertNodeSize;
1848 UINT8 *NewCertDb;
1849 UINT32 NewCertDbSize;
1850
1851 if ((VariableName == NULL) || (VendorGuid == NULL)) {
1852 return EFI_INVALID_PARAMETER;
1853 }
1854
1855 //
1856 // Get variable "certdb".
1857 //
1858 Status = FindVariable (
1859 EFI_CERT_DB_NAME,
1860 &gEfiCertDbGuid,
1861 &CertDbVariable,
1862 &mVariableModuleGlobal->VariableGlobal,
1863 FALSE
1864 );
1865 if (EFI_ERROR (Status)) {
1866 return Status;
1867 }
1868
1869 DataSize = DataSizeOfVariable (CertDbVariable.CurrPtr);
1870 Data = GetVariableDataPtr (CertDbVariable.CurrPtr);
1871 if ((DataSize == 0) || (Data == NULL)) {
1872 ASSERT (FALSE);
1873 return EFI_NOT_FOUND;
1874 }
1875
1876 if (DataSize == sizeof (UINT32)) {
1877 //
1878 // There is no certs in certdb.
1879 //
1880 return EFI_SUCCESS;
1881 }
1882
1883 //
1884 // Get corresponding cert node from certdb.
1885 //
1886 Status = FindCertsFromDb (
1887 VariableName,
1888 VendorGuid,
1889 Data,
1890 DataSize,
1891 NULL,
1892 NULL,
1893 &CertNodeOffset,
1894 &CertNodeSize
1895 );
1896
1897 if (EFI_ERROR (Status)) {
1898 return Status;
1899 }
1900
1901 if (DataSize < (CertNodeOffset + CertNodeSize)) {
1902 return EFI_NOT_FOUND;
1903 }
1904
1905 //
1906 // Construct new data content of variable "certdb".
1907 //
1908 NewCertDbSize = (UINT32) DataSize - CertNodeSize;
1909 NewCertDb = (UINT8*) mCertDbStore;
1910
1911 //
1912 // Copy the DB entries before deleting node.
1913 //
1914 CopyMem (NewCertDb, Data, CertNodeOffset);
1915 //
1916 // Update CertDbListSize.
1917 //
1918 CopyMem (NewCertDb, &NewCertDbSize, sizeof (UINT32));
1919 //
1920 // Copy the DB entries after deleting node.
1921 //
1922 if (DataSize > (CertNodeOffset + CertNodeSize)) {
1923 CopyMem (
1924 NewCertDb + CertNodeOffset,
1925 Data + CertNodeOffset + CertNodeSize,
1926 DataSize - CertNodeOffset - CertNodeSize
1927 );
1928 }
1929
1930 //
1931 // Set "certdb".
1932 //
1933 VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
1934 Status = UpdateVariable (
1935 EFI_CERT_DB_NAME,
1936 &gEfiCertDbGuid,
1937 NewCertDb,
1938 NewCertDbSize,
1939 VarAttr,
1940 0,
1941 0,
1942 &CertDbVariable,
1943 NULL
1944 );
1945
1946 return Status;
1947 }
1948
1949 /**
1950 Insert signer's certificates for common authenticated variable with VariableName
1951 and VendorGuid in AUTH_CERT_DB_DATA to "certdb".
1952
1953 @param[in] VariableName Name of authenticated Variable.
1954 @param[in] VendorGuid Vendor GUID of authenticated Variable.
1955 @param[in] CertData Pointer to signer's certificates.
1956 @param[in] CertDataSize Length of CertData in bytes.
1957
1958 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1959 @retval EFI_ACCESS_DENIED An AUTH_CERT_DB_DATA entry with same VariableName
1960 and VendorGuid already exists.
1961 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
1962 @retval EFI_SUCCESS Insert an AUTH_CERT_DB_DATA entry to "certdb"
1963
1964 **/
1965 EFI_STATUS
1966 InsertCertsToDb (
1967 IN CHAR16 *VariableName,
1968 IN EFI_GUID *VendorGuid,
1969 IN UINT8 *CertData,
1970 IN UINTN CertDataSize
1971 )
1972 {
1973 VARIABLE_POINTER_TRACK CertDbVariable;
1974 EFI_STATUS Status;
1975 UINT8 *Data;
1976 UINTN DataSize;
1977 UINT32 VarAttr;
1978 UINT8 *NewCertDb;
1979 UINT32 NewCertDbSize;
1980 UINT32 CertNodeSize;
1981 UINT32 NameSize;
1982 AUTH_CERT_DB_DATA *Ptr;
1983
1984 if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL)) {
1985 return EFI_INVALID_PARAMETER;
1986 }
1987
1988 //
1989 // Get variable "certdb".
1990 //
1991 Status = FindVariable (
1992 EFI_CERT_DB_NAME,
1993 &gEfiCertDbGuid,
1994 &CertDbVariable,
1995 &mVariableModuleGlobal->VariableGlobal,
1996 FALSE
1997 );
1998 if (EFI_ERROR (Status)) {
1999 return Status;
2000 }
2001
2002 DataSize = DataSizeOfVariable (CertDbVariable.CurrPtr);
2003 Data = GetVariableDataPtr (CertDbVariable.CurrPtr);
2004 if ((DataSize == 0) || (Data == NULL)) {
2005 ASSERT (FALSE);
2006 return EFI_NOT_FOUND;
2007 }
2008
2009 //
2010 // Find whether matching cert node already exists in "certdb".
2011 // If yes return error.
2012 //
2013 Status = FindCertsFromDb (
2014 VariableName,
2015 VendorGuid,
2016 Data,
2017 DataSize,
2018 NULL,
2019 NULL,
2020 NULL,
2021 NULL
2022 );
2023
2024 if (!EFI_ERROR (Status)) {
2025 ASSERT (FALSE);
2026 return EFI_ACCESS_DENIED;
2027 }
2028
2029 //
2030 // Construct new data content of variable "certdb".
2031 //
2032 NameSize = (UINT32) StrLen (VariableName);
2033 CertNodeSize = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16);
2034 NewCertDbSize = (UINT32) DataSize + CertNodeSize;
2035 if (NewCertDbSize > mMaxCertDbSize) {
2036 return EFI_OUT_OF_RESOURCES;
2037 }
2038 NewCertDb = (UINT8*) mCertDbStore;
2039
2040 //
2041 // Copy the DB entries before deleting node.
2042 //
2043 CopyMem (NewCertDb, Data, DataSize);
2044 //
2045 // Update CertDbListSize.
2046 //
2047 CopyMem (NewCertDb, &NewCertDbSize, sizeof (UINT32));
2048 //
2049 // Construct new cert node.
2050 //
2051 Ptr = (AUTH_CERT_DB_DATA *) (NewCertDb + DataSize);
2052 CopyGuid (&Ptr->VendorGuid, VendorGuid);
2053 CopyMem (&Ptr->CertNodeSize, &CertNodeSize, sizeof (UINT32));
2054 CopyMem (&Ptr->NameSize, &NameSize, sizeof (UINT32));
2055 CopyMem (&Ptr->CertDataSize, &CertDataSize, sizeof (UINT32));
2056
2057 CopyMem (
2058 (UINT8 *) Ptr + sizeof (AUTH_CERT_DB_DATA),
2059 VariableName,
2060 NameSize * sizeof (CHAR16)
2061 );
2062
2063 CopyMem (
2064 (UINT8 *) Ptr + sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16),
2065 CertData,
2066 CertDataSize
2067 );
2068
2069 //
2070 // Set "certdb".
2071 //
2072 VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
2073 Status = UpdateVariable (
2074 EFI_CERT_DB_NAME,
2075 &gEfiCertDbGuid,
2076 NewCertDb,
2077 NewCertDbSize,
2078 VarAttr,
2079 0,
2080 0,
2081 &CertDbVariable,
2082 NULL
2083 );
2084
2085 return Status;
2086 }
2087
2088 /**
2089 Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
2090
2091 Caution: This function may receive untrusted input.
2092 This function may be invoked in SMM mode, and datasize and data are external input.
2093 This function will do basic validation, before parse the data.
2094 This function will parse the authentication carefully to avoid security issues, like
2095 buffer overflow, integer overflow.
2096
2097 @param[in] VariableName Name of Variable to be found.
2098 @param[in] VendorGuid Variable vendor GUID.
2099 @param[in] Data Data pointer.
2100 @param[in] DataSize Size of Data found. If size is less than the
2101 data, this value contains the required size.
2102 @param[in] Variable The variable information which is used to keep track of variable usage.
2103 @param[in] Attributes Attribute value of the variable.
2104 @param[in] AuthVarType Verify against PK, KEK database, private database or certificate in data payload.
2105 @param[out] VarDel Delete the variable or not.
2106
2107 @retval EFI_INVALID_PARAMETER Invalid parameter.
2108 @retval EFI_SECURITY_VIOLATION The variable does NOT pass the validation
2109 check carried out by the firmware.
2110 @retval EFI_OUT_OF_RESOURCES Failed to process variable due to lack
2111 of resources.
2112 @retval EFI_SUCCESS Variable pass validation successfully.
2113
2114 **/
2115 EFI_STATUS
2116 VerifyTimeBasedPayload (
2117 IN CHAR16 *VariableName,
2118 IN EFI_GUID *VendorGuid,
2119 IN VOID *Data,
2120 IN UINTN DataSize,
2121 IN VARIABLE_POINTER_TRACK *Variable,
2122 IN UINT32 Attributes,
2123 IN AUTHVAR_TYPE AuthVarType,
2124 OUT BOOLEAN *VarDel
2125 )
2126 {
2127 UINT8 *RootCert;
2128 UINT8 *SigData;
2129 UINT8 *PayloadPtr;
2130 UINTN RootCertSize;
2131 UINTN Index;
2132 UINTN CertCount;
2133 UINTN PayloadSize;
2134 UINT32 Attr;
2135 UINT32 SigDataSize;
2136 UINT32 KekDataSize;
2137 BOOLEAN VerifyStatus;
2138 EFI_STATUS Status;
2139 EFI_SIGNATURE_LIST *CertList;
2140 EFI_SIGNATURE_DATA *Cert;
2141 VARIABLE_POINTER_TRACK KekVariable;
2142 EFI_VARIABLE_AUTHENTICATION_2 *CertData;
2143 UINT8 *NewData;
2144 UINTN NewDataSize;
2145 VARIABLE_POINTER_TRACK PkVariable;
2146 UINT8 *Buffer;
2147 UINTN Length;
2148 UINT8 *SignerCerts;
2149 UINT8 *WrapSigData;
2150 UINTN CertStackSize;
2151 UINT8 *CertsInCertDb;
2152 UINT32 CertsSizeinDb;
2153
2154 VerifyStatus = FALSE;
2155 CertData = NULL;
2156 NewData = NULL;
2157 Attr = Attributes;
2158 WrapSigData = NULL;
2159 SignerCerts = NULL;
2160 RootCert = NULL;
2161 CertsInCertDb = NULL;
2162
2163 //
2164 // When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
2165 // set, then the Data buffer shall begin with an instance of a complete (and serialized)
2166 // EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new
2167 // variable value and DataSize shall reflect the combined size of the descriptor and the new
2168 // variable value. The authentication descriptor is not part of the variable data and is not
2169 // returned by subsequent calls to GetVariable().
2170 //
2171 CertData = (EFI_VARIABLE_AUTHENTICATION_2 *) Data;
2172
2173 //
2174 // Verify that Pad1, Nanosecond, TimeZone, Daylight and Pad2 components of the
2175 // TimeStamp value are set to zero.
2176 //
2177 if ((CertData->TimeStamp.Pad1 != 0) ||
2178 (CertData->TimeStamp.Nanosecond != 0) ||
2179 (CertData->TimeStamp.TimeZone != 0) ||
2180 (CertData->TimeStamp.Daylight != 0) ||
2181 (CertData->TimeStamp.Pad2 != 0)) {
2182 return EFI_SECURITY_VIOLATION;
2183 }
2184
2185 if ((Variable->CurrPtr != NULL) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
2186 if (CompareTimeStamp (&CertData->TimeStamp, &Variable->CurrPtr->TimeStamp)) {
2187 //
2188 // TimeStamp check fail, suspicious replay attack, return EFI_SECURITY_VIOLATION.
2189 //
2190 return EFI_SECURITY_VIOLATION;
2191 }
2192 }
2193
2194 //
2195 // wCertificateType should be WIN_CERT_TYPE_EFI_GUID.
2196 // Cert type should be EFI_CERT_TYPE_PKCS7_GUID.
2197 //
2198 if ((CertData->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) ||
2199 !CompareGuid (&CertData->AuthInfo.CertType, &gEfiCertPkcs7Guid)) {
2200 //
2201 // Invalid AuthInfo type, return EFI_SECURITY_VIOLATION.
2202 //
2203 return EFI_SECURITY_VIOLATION;
2204 }
2205
2206 //
2207 // Find out Pkcs7 SignedData which follows the EFI_VARIABLE_AUTHENTICATION_2 descriptor.
2208 // AuthInfo.Hdr.dwLength is the length of the entire certificate, including the length of the header.
2209 //
2210 SigData = CertData->AuthInfo.CertData;
2211 SigDataSize = CertData->AuthInfo.Hdr.dwLength - (UINT32) (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData));
2212
2213 //
2214 // Find out the new data payload which follows Pkcs7 SignedData directly.
2215 //
2216 PayloadPtr = SigData + SigDataSize;
2217 PayloadSize = DataSize - OFFSET_OF_AUTHINFO2_CERT_DATA - (UINTN) SigDataSize;
2218
2219 //
2220 // Construct a buffer to fill with (VariableName, VendorGuid, Attributes, TimeStamp, Data).
2221 //
2222 NewDataSize = PayloadSize + sizeof (EFI_TIME) + sizeof (UINT32) +
2223 sizeof (EFI_GUID) + StrSize (VariableName) - sizeof (CHAR16);
2224 NewData = mSerializationRuntimeBuffer;
2225
2226 Buffer = NewData;
2227 Length = StrLen (VariableName) * sizeof (CHAR16);
2228 CopyMem (Buffer, VariableName, Length);
2229 Buffer += Length;
2230
2231 Length = sizeof (EFI_GUID);
2232 CopyMem (Buffer, VendorGuid, Length);
2233 Buffer += Length;
2234
2235 Length = sizeof (UINT32);
2236 CopyMem (Buffer, &Attr, Length);
2237 Buffer += Length;
2238
2239 Length = sizeof (EFI_TIME);
2240 CopyMem (Buffer, &CertData->TimeStamp, Length);
2241 Buffer += Length;
2242
2243 CopyMem (Buffer, PayloadPtr, PayloadSize);
2244
2245 if (AuthVarType == AuthVarTypePk) {
2246 //
2247 // Verify that the signature has been made with the current Platform Key (no chaining for PK).
2248 // First, get signer's certificates from SignedData.
2249 //
2250 VerifyStatus = Pkcs7GetSigners (
2251 SigData,
2252 SigDataSize,
2253 &SignerCerts,
2254 &CertStackSize,
2255 &RootCert,
2256 &RootCertSize
2257 );
2258 if (!VerifyStatus) {
2259 goto Exit;
2260 }
2261
2262 //
2263 // Second, get the current platform key from variable. Check whether it's identical with signer's certificates
2264 // in SignedData. If not, return error immediately.
2265 //
2266 Status = FindVariable (
2267 EFI_PLATFORM_KEY_NAME,
2268 &gEfiGlobalVariableGuid,
2269 &PkVariable,
2270 &mVariableModuleGlobal->VariableGlobal,
2271 FALSE
2272 );
2273 if (EFI_ERROR (Status)) {
2274 VerifyStatus = FALSE;
2275 goto Exit;
2276 }
2277 CertList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (PkVariable.CurrPtr);
2278 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2279 if ((RootCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||
2280 (CompareMem (Cert->SignatureData, RootCert, RootCertSize) != 0)) {
2281 VerifyStatus = FALSE;
2282 goto Exit;
2283 }
2284
2285 //
2286 // Verify Pkcs7 SignedData via Pkcs7Verify library.
2287 //
2288 VerifyStatus = Pkcs7Verify (
2289 SigData,
2290 SigDataSize,
2291 RootCert,
2292 RootCertSize,
2293 NewData,
2294 NewDataSize
2295 );
2296
2297 } else if (AuthVarType == AuthVarTypeKek) {
2298
2299 //
2300 // Get KEK database from variable.
2301 //
2302 Status = FindVariable (
2303 EFI_KEY_EXCHANGE_KEY_NAME,
2304 &gEfiGlobalVariableGuid,
2305 &KekVariable,
2306 &mVariableModuleGlobal->VariableGlobal,
2307 FALSE
2308 );
2309 if (EFI_ERROR (Status)) {
2310 return Status;
2311 }
2312
2313 //
2314 // Ready to verify Pkcs7 SignedData. Go through KEK Signature Database to find out X.509 CertList.
2315 //
2316 KekDataSize = KekVariable.CurrPtr->DataSize;
2317 CertList = (EFI_SIGNATURE_LIST *) GetVariableDataPtr (KekVariable.CurrPtr);
2318 while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) {
2319 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
2320 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2321 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
2322 for (Index = 0; Index < CertCount; Index++) {
2323 //
2324 // Iterate each Signature Data Node within this CertList for a verify
2325 //
2326 RootCert = Cert->SignatureData;
2327 RootCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);
2328
2329 //
2330 // Verify Pkcs7 SignedData via Pkcs7Verify library.
2331 //
2332 VerifyStatus = Pkcs7Verify (
2333 SigData,
2334 SigDataSize,
2335 RootCert,
2336 RootCertSize,
2337 NewData,
2338 NewDataSize
2339 );
2340 if (VerifyStatus) {
2341 goto Exit;
2342 }
2343 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
2344 }
2345 }
2346 KekDataSize -= CertList->SignatureListSize;
2347 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
2348 }
2349 } else if (AuthVarType == AuthVarTypePriv) {
2350
2351 //
2352 // Process common authenticated variable except PK/KEK/DB/DBX.
2353 // Get signer's certificates from SignedData.
2354 //
2355 VerifyStatus = Pkcs7GetSigners (
2356 SigData,
2357 SigDataSize,
2358 &SignerCerts,
2359 &CertStackSize,
2360 &RootCert,
2361 &RootCertSize
2362 );
2363 if (!VerifyStatus) {
2364 goto Exit;
2365 }
2366
2367 //
2368 // Get previously stored signer's certificates from certdb for existing
2369 // variable. Check whether they are identical with signer's certificates
2370 // in SignedData. If not, return error immediately.
2371 //
2372 if ((Variable->CurrPtr != NULL)) {
2373 VerifyStatus = FALSE;
2374
2375 Status = GetCertsFromDb (VariableName, VendorGuid, &CertsInCertDb, &CertsSizeinDb);
2376 if (EFI_ERROR (Status)) {
2377 goto Exit;
2378 }
2379
2380 if ((CertStackSize != CertsSizeinDb) ||
2381 (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {
2382 goto Exit;
2383 }
2384 }
2385
2386 VerifyStatus = Pkcs7Verify (
2387 SigData,
2388 SigDataSize,
2389 RootCert,
2390 RootCertSize,
2391 NewData,
2392 NewDataSize
2393 );
2394 if (!VerifyStatus) {
2395 goto Exit;
2396 }
2397
2398 //
2399 // Delete signer's certificates when delete the common authenticated variable.
2400 //
2401 if ((PayloadSize == 0) && (Variable->CurrPtr != NULL) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
2402 Status = DeleteCertsFromDb (VariableName, VendorGuid);
2403 if (EFI_ERROR (Status)) {
2404 VerifyStatus = FALSE;
2405 goto Exit;
2406 }
2407 } else if (Variable->CurrPtr == NULL && PayloadSize != 0) {
2408 //
2409 // Insert signer's certificates when adding a new common authenticated variable.
2410 //
2411 Status = InsertCertsToDb (VariableName, VendorGuid, SignerCerts, CertStackSize);
2412 if (EFI_ERROR (Status)) {
2413 VerifyStatus = FALSE;
2414 goto Exit;
2415 }
2416 }
2417 } else if (AuthVarType == AuthVarTypePayload) {
2418 CertList = (EFI_SIGNATURE_LIST *) PayloadPtr;
2419 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
2420 RootCert = Cert->SignatureData;
2421 RootCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);
2422
2423 // Verify Pkcs7 SignedData via Pkcs7Verify library.
2424 //
2425 VerifyStatus = Pkcs7Verify (
2426 SigData,
2427 SigDataSize,
2428 RootCert,
2429 RootCertSize,
2430 NewData,
2431 NewDataSize
2432 );
2433 } else {
2434 return EFI_SECURITY_VIOLATION;
2435 }
2436
2437 Exit:
2438
2439 if (AuthVarType == AuthVarTypePk || AuthVarType == AuthVarTypePriv) {
2440 Pkcs7FreeSigners (RootCert);
2441 Pkcs7FreeSigners (SignerCerts);
2442 }
2443
2444 if (!VerifyStatus) {
2445 return EFI_SECURITY_VIOLATION;
2446 }
2447
2448 Status = CheckSignatureListFormat(VariableName, VendorGuid, PayloadPtr, PayloadSize);
2449 if (EFI_ERROR (Status)) {
2450 return Status;
2451 }
2452
2453 if ((PayloadSize == 0) && (VarDel != NULL)) {
2454 *VarDel = TRUE;
2455 }
2456
2457 //
2458 // Final step: Update/Append Variable if it pass Pkcs7Verify
2459 //
2460 return UpdateVariable (
2461 VariableName,
2462 VendorGuid,
2463 PayloadPtr,
2464 PayloadSize,
2465 Attributes,
2466 0,
2467 0,
2468 Variable,
2469 &CertData->TimeStamp
2470 );
2471 }
2472