1. Secure Boot NVRAM策略概述
Secure Boot作为UEFI固件的重要安全机制,其策略配置主要通过NVRAM变量来实现和维护。本文将详细介绍Secure Boot相关的NVRAM策略管理。
1.1 核心安全变量
Secure Boot使用以下关键NVRAM变量:
- PK (Platform Key):平台密钥
- KEK (Key Exchange Key):密钥交换密钥
- db (Signature Database):允许签名数据库
- dbx (Forbidden Signature Database):禁止签名数据库
- dbt (Timestamp Database):时间戳数据库
1.2 变量属性要求
1 2 3 4 5 6 7 8 9 10 11 12 13
| #define SECURE_BOOT_VAR_ATTR ( \ EFI_VARIABLE_NON_VOLATILE | \ EFI_VARIABLE_BOOTSERVICE_ACCESS | \ EFI_VARIABLE_RUNTIME_ACCESS | \ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS \ )
#define KEY_DATABASE_ATTR ( \ SECURE_BOOT_VAR_ATTR | \ EFI_VARIABLE_APPEND_WRITE \ )
|
2. 密钥层级结构
2.1 密钥链关系
1 2 3 4 5
| PK (Platform Key) └── KEK (Key Exchange Key) ├── db (Allowed Signatures) ├── dbx (Revoked Signatures) └── dbt (Timestamp Signatures)
|
2.2 密钥更新策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| EFI_STATUS UpdatePlatformKey( IN UINT8 *NewKey, IN UINTN KeySize ) { EFI_STATUS Status; EFI_VARIABLE_AUTHENTICATION_2 *VarAuth; UINTN DataSize; DataSize = sizeof(EFI_VARIABLE_AUTHENTICATION_2) + KeySize; VarAuth = AllocatePool(DataSize); if (VarAuth == NULL) return EFI_OUT_OF_RESOURCES; Status = PrepareAuthData(VarAuth, NewKey, KeySize); if (EFI_ERROR(Status)) { FreePool(VarAuth); return Status; } Status = gRT->SetVariable( EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, SECURE_BOOT_VAR_ATTR, DataSize, VarAuth ); FreePool(VarAuth); return Status; }
|
3. 安全策略实施
3.1 变量访问控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| typedef struct { EFI_GUID *VarGuid; CHAR16 *VarName; UINT32 MinRequiredAttr; BOOLEAN AllowAppend; } SECURE_VAR_POLICY;
BOOLEAN IsVariableAccessAllowed( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN BOOLEAN IsWrite ) { if (CompareGuid(VendorGuid, &gEfiGlobalVariableGuid)) { if (StrCmp(VariableName, EFI_PLATFORM_KEY_NAME) == 0) { return (Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0; } } return TRUE; }
|
3.2 签名验证机制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| EFI_STATUS VerifySignature( IN UINT8 *Data, IN UINTN DataSize, IN UINT8 *Signature, IN UINTN SigSize ) { EFI_STATUS Status; UINT8 Hash[SHA256_DIGEST_SIZE]; Status = CalculateSha256(Data, DataSize, Hash); if (EFI_ERROR(Status)) return Status; Status = VerifyPkcs1Signature( Hash, sizeof(Hash), Signature, SigSize, GetPublicKey() ); return Status; }
|
4. 安全启动状态管理
4.1 状态变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| typedef struct { BOOLEAN SecureBootEnabled; BOOLEAN PkPresent; BOOLEAN KekPresent; UINT32 DbCount; UINT32 DbxCount; UINT32 DbtCount; } SECURE_BOOT_STATUS;
EFI_STATUS GetSecureBootStatus( OUT SECURE_BOOT_STATUS *Status ) { EFI_STATUS RetStatus; UINT8 SecureBoot = 0; UINTN DataSize = sizeof(SecureBoot); RetStatus = gRT->GetVariable( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, &SecureBoot ); Status->SecureBootEnabled = !EFI_ERROR(RetStatus) && SecureBoot; return EFI_SUCCESS; }
|
4.2 审计日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| typedef struct { EFI_TIME Timestamp; UINT32 EventType; CHAR16 VariableName[256]; EFI_GUID VendorGuid; UINT32 Attributes; EFI_STATUS Status; } SECURE_BOOT_AUDIT_LOG;
VOID LogSecureBootEvent( IN UINT32 EventType, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN EFI_STATUS Status ) { SECURE_BOOT_AUDIT_LOG Log; gRT->GetTime(&Log.Timestamp, NULL); Log.EventType = EventType; StrCpy(Log.VariableName, VariableName); CopyMem(&Log.VendorGuid, VendorGuid, sizeof(EFI_GUID)); Log.Attributes = Attributes; Log.Status = Status; SaveAuditLog(&Log); }
|
5. 故障恢复机制
5.1 密钥备份
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| typedef struct { UINT32 Version; EFI_TIME BackupTime; UINT8 KeyData[]; } KEY_BACKUP_DATA;
EFI_STATUS BackupSecureBootKeys() { KEY_BACKUP_DATA *Backup; UINTN BackupSize; EFI_STATUS Status; Status = PrepareKeyBackup(&Backup, &BackupSize); if (EFI_ERROR(Status)) return Status; Status = gRT->SetVariable( L"SecureBootKeyBackup", &gEfiSecureBootBackupGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_WRITE_ONCE, BackupSize, Backup ); FreePool(Backup); return Status; }
|
5.2 恢复流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| typedef enum { RecoveryStepBackupCheck, RecoveryStepPkRestore, RecoveryStepKekRestore, RecoveryStepDbRestore, RecoveryStepComplete } RECOVERY_STEP;
EFI_STATUS PerformSecureBootRecovery() { EFI_STATUS Status; RECOVERY_STEP CurrentStep = RecoveryStepBackupCheck; while (CurrentStep != RecoveryStepComplete) { Status = ExecuteRecoveryStep(CurrentStep); if (EFI_ERROR(Status)) { LogSecureBootEvent( SECURE_BOOT_EVENT_RECOVERY_FAILED, L"Recovery", &gEfiSecureBootBackupGuid, 0, Status ); return Status; } CurrentStep++; } return EFI_SUCCESS; }
|
6. 最佳实践建议
6.1 安全配置
- 使用强密码学算法(如RSA-2048或更高)
- 实施最小权限原则
- 定期轮换密钥
- 保持dbx数据库更新
- 启用审计日志
6.2 性能优化
- 缓存常用验证结果
- 优化签名验证路径
- 合理设置变量大小限制
- 实施高效的密钥查找算法
6.3 开发建议
- 严格遵循UEFI规范
- 实现完整的错误处理
- 提供详细的调试信息
- 支持灾难恢复机制
- 定期进行安全审计
参考资料
- UEFI Secure Boot
- NIST SP 800-147: BIOS Protection Guidelines
- UEFI Specification Version 2.10 - Secure Boot
- TCG PC Client Platform Firmware Profile Specification