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
// Secure Boot变量通用属性
#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;
}

// 更新PK
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) {
// PK特殊处理
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);

// 检查Secure Boot使能状态
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规范
  • 实现完整的错误处理
  • 提供详细的调试信息
  • 支持灾难恢复机制
  • 定期进行安全审计

参考资料

  1. UEFI Secure Boot
  2. NIST SP 800-147: BIOS Protection Guidelines
  3. UEFI Specification Version 2.10 - Secure Boot
  4. TCG PC Client Platform Firmware Profile Specification