123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /*
- * SPDX-License-Identifier: GPL-2.0-or-later
- *
- * uefi vars device - AuthVariableLib
- */
- #include "qemu/osdep.h"
- #include "qemu/error-report.h"
- #include "system/dma.h"
- #include "hw/uefi/var-service.h"
- static const uint16_t name_pk[] = u"PK";
- static const uint16_t name_kek[] = u"KEK";
- static const uint16_t name_db[] = u"db";
- static const uint16_t name_dbx[] = u"dbx";
- static const uint16_t name_setup_mode[] = u"SetupMode";
- static const uint16_t name_sigs_support[] = u"SignatureSupport";
- static const uint16_t name_sb[] = u"SecureBoot";
- static const uint16_t name_sb_enable[] = u"SecureBootEnable";
- static const uint16_t name_custom_mode[] = u"CustomMode";
- static const uint16_t name_vk[] = u"VendorKeys";
- static const uint16_t name_vk_nv[] = u"VendorKeysNv";
- static const uint32_t sigdb_attrs =
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS |
- EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
- static void set_secure_boot(uefi_vars_state *uv, uint8_t sb)
- {
- uefi_vars_set_variable(uv, EfiGlobalVariable,
- name_sb, sizeof(name_sb),
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- &sb, sizeof(sb));
- }
- static void set_secure_boot_enable(uefi_vars_state *uv, uint8_t sbe)
- {
- uefi_vars_set_variable(uv, EfiSecureBootEnableDisable,
- name_sb_enable, sizeof(name_sb_enable),
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS,
- &sbe, sizeof(sbe));
- }
- static void set_setup_mode(uefi_vars_state *uv, uint8_t sm)
- {
- uefi_vars_set_variable(uv, EfiGlobalVariable,
- name_setup_mode, sizeof(name_setup_mode),
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- &sm, sizeof(sm));
- }
- static void set_custom_mode(uefi_vars_state *uv, uint8_t cm)
- {
- uefi_vars_set_variable(uv, EfiCustomModeEnable,
- name_custom_mode, sizeof(name_custom_mode),
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS,
- &cm, sizeof(cm));
- }
- static void set_signature_support(uefi_vars_state *uv)
- {
- QemuUUID sigs_support[5];
- sigs_support[0] = EfiCertSha256Guid;
- sigs_support[1] = EfiCertSha384Guid;
- sigs_support[2] = EfiCertSha512Guid;
- sigs_support[3] = EfiCertRsa2048Guid;
- sigs_support[4] = EfiCertX509Guid;
- uefi_vars_set_variable(uv, EfiGlobalVariable,
- name_sigs_support, sizeof(name_sigs_support),
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- sigs_support, sizeof(sigs_support));
- }
- static bool setup_mode_is_active(uefi_vars_state *uv)
- {
- uefi_variable *var;
- uint8_t *value;
- var = uefi_vars_find_variable(uv, EfiGlobalVariable,
- name_setup_mode, sizeof(name_setup_mode));
- if (var) {
- value = var->data;
- if (value[0] == SETUP_MODE) {
- return true;
- }
- }
- return false;
- }
- static bool custom_mode_is_active(uefi_vars_state *uv)
- {
- uefi_variable *var;
- uint8_t *value;
- var = uefi_vars_find_variable(uv, EfiCustomModeEnable,
- name_custom_mode, sizeof(name_custom_mode));
- if (var) {
- value = var->data;
- if (value[0] == CUSTOM_SECURE_BOOT_MODE) {
- return true;
- }
- }
- return false;
- }
- bool uefi_vars_is_sb_pk(uefi_variable *var)
- {
- if (qemu_uuid_is_equal(&var->guid, &EfiGlobalVariable) &&
- uefi_str_equal(var->name, var->name_size, name_pk, sizeof(name_pk))) {
- return true;
- }
- return false;
- }
- static bool uefi_vars_is_sb_kek(uefi_variable *var)
- {
- if (qemu_uuid_is_equal(&var->guid, &EfiGlobalVariable) &&
- uefi_str_equal(var->name, var->name_size, name_kek, sizeof(name_kek))) {
- return true;
- }
- return false;
- }
- static bool uefi_vars_is_sb_db(uefi_variable *var)
- {
- if (!qemu_uuid_is_equal(&var->guid, &EfiImageSecurityDatabase)) {
- return false;
- }
- if (uefi_str_equal(var->name, var->name_size, name_db, sizeof(name_db))) {
- return true;
- }
- if (uefi_str_equal(var->name, var->name_size, name_dbx, sizeof(name_dbx))) {
- return true;
- }
- return false;
- }
- bool uefi_vars_is_sb_any(uefi_variable *var)
- {
- if (uefi_vars_is_sb_pk(var) ||
- uefi_vars_is_sb_kek(var) ||
- uefi_vars_is_sb_db(var)) {
- return true;
- }
- return false;
- }
- static uefi_variable *uefi_vars_find_siglist(uefi_vars_state *uv,
- uefi_variable *var)
- {
- if (uefi_vars_is_sb_pk(var)) {
- return uefi_vars_find_variable(uv, EfiGlobalVariable,
- name_pk, sizeof(name_pk));
- }
- if (uefi_vars_is_sb_kek(var)) {
- return uefi_vars_find_variable(uv, EfiGlobalVariable,
- name_pk, sizeof(name_pk));
- }
- if (uefi_vars_is_sb_db(var)) {
- return uefi_vars_find_variable(uv, EfiGlobalVariable,
- name_kek, sizeof(name_kek));
- }
- return NULL;
- }
- static efi_status uefi_vars_check_auth_2_sb(uefi_vars_state *uv,
- uefi_variable *var,
- mm_variable_access *va,
- void *data,
- uint64_t data_offset)
- {
- variable_auth_2 *auth = data;
- uefi_variable *siglist;
- if (custom_mode_is_active(uv)) {
- /* no authentication in custom mode */
- return EFI_SUCCESS;
- }
- if (setup_mode_is_active(uv) && !uefi_vars_is_sb_pk(var)) {
- /* no authentication in setup mode (except PK) */
- return EFI_SUCCESS;
- }
- if (auth->hdr_length == 24) {
- /* no signature (auth->cert_data is empty) */
- return EFI_SECURITY_VIOLATION;
- }
- siglist = uefi_vars_find_siglist(uv, var);
- if (!siglist && setup_mode_is_active(uv) && uefi_vars_is_sb_pk(var)) {
- /* check PK is self-signed */
- uefi_variable tmp = {
- .guid = EfiGlobalVariable,
- .name = (uint16_t *)name_pk,
- .name_size = sizeof(name_pk),
- .attributes = sigdb_attrs,
- .data = data + data_offset,
- .data_size = va->data_size - data_offset,
- };
- return uefi_vars_check_pkcs7_2(&tmp, NULL, NULL, va, data);
- }
- return uefi_vars_check_pkcs7_2(siglist, NULL, NULL, va, data);
- }
- efi_status uefi_vars_check_auth_2(uefi_vars_state *uv, uefi_variable *var,
- mm_variable_access *va, void *data)
- {
- variable_auth_2 *auth = data;
- uint64_t data_offset;
- efi_status status;
- if (va->data_size < sizeof(*auth)) {
- return EFI_SECURITY_VIOLATION;
- }
- if (uadd64_overflow(sizeof(efi_time), auth->hdr_length, &data_offset)) {
- return EFI_SECURITY_VIOLATION;
- }
- if (va->data_size < data_offset) {
- return EFI_SECURITY_VIOLATION;
- }
- if (auth->hdr_revision != 0x0200 ||
- auth->hdr_cert_type != WIN_CERT_TYPE_EFI_GUID ||
- !qemu_uuid_is_equal(&auth->guid_cert_type, &EfiCertTypePkcs7Guid)) {
- return EFI_UNSUPPORTED;
- }
- if (uefi_vars_is_sb_any(var)) {
- /* secure boot variables */
- status = uefi_vars_check_auth_2_sb(uv, var, va, data, data_offset);
- if (status != EFI_SUCCESS) {
- return status;
- }
- } else {
- /* other authenticated variables */
- status = uefi_vars_check_pkcs7_2(NULL,
- &var->digest, &var->digest_size,
- va, data);
- if (status != EFI_SUCCESS) {
- return status;
- }
- }
- /* checks passed, set variable data */
- var->time = auth->timestamp;
- if (va->data_size - data_offset > 0) {
- var->data = g_malloc(va->data_size - data_offset);
- memcpy(var->data, data + data_offset, va->data_size - data_offset);
- var->data_size = va->data_size - data_offset;
- }
- return EFI_SUCCESS;
- }
- efi_status uefi_vars_check_secure_boot(uefi_vars_state *uv, uefi_variable *var)
- {
- uint8_t *value = var->data;
- if (uefi_vars_is_sb_any(var)) {
- if (var->attributes != sigdb_attrs) {
- return EFI_INVALID_PARAMETER;
- }
- }
- /* reject SecureBootEnable updates if force_secure_boot is set */
- if (qemu_uuid_is_equal(&var->guid, &EfiSecureBootEnableDisable) &&
- uefi_str_equal(var->name, var->name_size,
- name_sb_enable, sizeof(name_sb_enable)) &&
- uv->force_secure_boot &&
- value[0] != SECURE_BOOT_ENABLE) {
- return EFI_WRITE_PROTECTED;
- }
- /* reject CustomMode updates if disable_custom_mode is set */
- if (qemu_uuid_is_equal(&var->guid, &EfiCustomModeEnable) &&
- uefi_str_equal(var->name, var->name_size,
- name_custom_mode, sizeof(name_custom_mode)) &&
- uv->disable_custom_mode) {
- return EFI_WRITE_PROTECTED;
- }
- return EFI_SUCCESS;
- }
- /* AuthVariableLibInitialize */
- void uefi_vars_auth_init(uefi_vars_state *uv)
- {
- uefi_variable *pk_var, *sbe_var;
- uint8_t platform_mode, sb, sbe, vk;
- /* SetupMode */
- pk_var = uefi_vars_find_variable(uv, EfiGlobalVariable,
- name_pk, sizeof(name_pk));
- if (!pk_var) {
- platform_mode = SETUP_MODE;
- } else {
- platform_mode = USER_MODE;
- }
- set_setup_mode(uv, platform_mode);
- /* SignatureSupport */
- set_signature_support(uv);
- /* SecureBootEnable */
- sbe = SECURE_BOOT_DISABLE;
- sbe_var = uefi_vars_find_variable(uv, EfiSecureBootEnableDisable,
- name_sb_enable, sizeof(name_sb_enable));
- if (sbe_var) {
- if (platform_mode == USER_MODE) {
- sbe = ((uint8_t *)sbe_var->data)[0];
- }
- } else if (platform_mode == USER_MODE) {
- sbe = SECURE_BOOT_ENABLE;
- set_secure_boot_enable(uv, sbe);
- }
- if (uv->force_secure_boot && sbe != SECURE_BOOT_ENABLE) {
- sbe = SECURE_BOOT_ENABLE;
- set_secure_boot_enable(uv, sbe);
- }
- /* SecureBoot */
- if ((sbe == SECURE_BOOT_ENABLE) && (platform_mode == USER_MODE)) {
- sb = SECURE_BOOT_MODE_ENABLE;
- } else {
- sb = SECURE_BOOT_MODE_DISABLE;
- }
- set_secure_boot(uv, sb);
- /* CustomMode */
- set_custom_mode(uv, STANDARD_SECURE_BOOT_MODE);
- vk = 0;
- uefi_vars_set_variable(uv, EfiGlobalVariable,
- name_vk_nv, sizeof(name_vk_nv),
- EFI_VARIABLE_NON_VOLATILE |
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
- &vk, sizeof(vk));
- uefi_vars_set_variable(uv, EfiGlobalVariable,
- name_vk, sizeof(name_vk),
- EFI_VARIABLE_BOOTSERVICE_ACCESS |
- EFI_VARIABLE_RUNTIME_ACCESS,
- &vk, sizeof(vk));
- /* flush to disk */
- uefi_vars_json_save(uv);
- }
|