From patchwork Wed Feb 26 04:54:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1244660 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=skNOh1O9; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48S3R30NsRz9sPR for ; Wed, 26 Feb 2020 15:55:58 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id DBF5580911; Wed, 26 Feb 2020 05:55:42 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="skNOh1O9"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D1BB280911; Wed, 26 Feb 2020 05:55:13 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B3B568100C for ; Wed, 26 Feb 2020 05:55:01 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pg1-x541.google.com with SMTP id j15so683615pgm.6 for ; Tue, 25 Feb 2020 20:55:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fKNqYfZ6qodB/68XFwzYRG4F59rBT1HXt0iLzV2w40k=; b=skNOh1O9PXp4slyWdcmPdJtEEEHZThNLlNjiQrPaqfaLZEBAxAdS9W7FKdAeHZRyuP U9rpz/km1A+DjN4Rm8bx3RKIa2ucPG2TpTjzghkssByofCROawgBegg4Wg3/eosD0wvz OVW8fD3ftLCZP0mHVbWcvgph8tjrtz3BlYrJ7ePuQZWYa97ikI4F0eFdHv3sQPspq41T jAOlwzSEZHE1dMyCeKPovuzgVZExexXK/VjhIfOGdNw7oerK4XBvXLG7tuN2I+zzw2Z+ +gsr9R9yh7ocyDlYR23KwX02Qf8lJrDrmQzndrQlUI08iZ7qp9diWRPd4CIcbEk7pXeC GB6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fKNqYfZ6qodB/68XFwzYRG4F59rBT1HXt0iLzV2w40k=; b=orWdbn6Rk/nhrMt7xTuqlJ43Xg3h/QvNfuLefyH/zVDBDKGF4ra2iTL6PxwzjW/T8a pKpu2q5p6r6J+cFbLkDlhh8PutWvPDAKAHOGpDN4WU1E2SfCFhHJnJg4aTbWUPvGpQ2d k7qntU1Lcni/9oyOdJ7fuWsx6QlL8E47e6s2w4r/2lMSL/8TdlvPrnsyZqr92pLJCqgY guspdhLMC9UFcqwMPR+kPzlTzk8qDXsDTx4CFvEL4f2UtpHq1SPDv+k22ZydWPxMgKIs 1eqOXXfq7kAeBHQHCqZQaOst/iiY0bg3qmiQG4j5MdjKx2gCTklQ57KX+pUuLv6wxVAP fF0Q== X-Gm-Message-State: APjAAAXvY4nQ/o2t+GSQ1kouw10h64ABmnqC3wa5MtsePQERq8UXBKFM WTvwp31OLWOSPmxqKUIiVKMFTA== X-Google-Smtp-Source: APXvYqzSs1F7G+dEHA1QacadobFAF56g+9bo4LCKyBRtkySHWTL3XNgl+fWiHoJJdRNQsXqkgn6yyA== X-Received: by 2002:a62:ab06:: with SMTP id p6mr2364327pff.52.1582692900134; Tue, 25 Feb 2020 20:55:00 -0800 (PST) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id d2sm754609pjv.18.2020.02.25.20.54.59 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 25 Feb 2020 20:54:59 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Cc: sjg@chromium.org, ilias.apalodimas@linaro.org, mail@patrick-wildt.de, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v6 05/16] efi_loader: variable: add secure boot state transition Date: Wed, 26 Feb 2020 13:54:37 +0900 Message-Id: <20200226045448.2453-6-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200226045448.2453-1-takahiro.akashi@linaro.org> References: <20200226045448.2453-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean UEFI specification defines several global variables which are related to the current secure boot state. In this commit, those values will be maintained according to operations. Currently, AuditMode and DeployedMode are defined but not implemented. Signed-off-by: AKASHI Takahiro --- lib/efi_loader/efi_variable.c | 231 +++++++++++++++++++++++++++++++++- 1 file changed, 228 insertions(+), 3 deletions(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index c82128f0c9ad..bf0ee486e4cf 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -16,8 +16,16 @@ #include #include "../lib/crypto/pkcs7_parser.h" +enum efi_secure_mode { + EFI_MODE_SETUP, + EFI_MODE_USER, + EFI_MODE_AUDIT, + EFI_MODE_DEPLOYED, +}; + const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; static bool efi_secure_boot; +static int efi_secure_mode; #define READ_ONLY BIT(31) @@ -160,6 +168,210 @@ static const char *parse_attr(const char *str, u32 *attrp, u64 *timep) return str; } +static efi_status_t efi_set_variable_internal(u16 *variable_name, + const efi_guid_t *vendor, + u32 attributes, + efi_uintn_t data_size, + const void *data, + bool ro_check); + +/** + * efi_transfer_secure_state - handle a secure boot state transition + * @mode: new state + * + * Depending on @mode, secure boot related variables are updated. + * Those variables are *read-only* for users, efi_set_variable_internal() + * is called here. + * + * Return: EFI_SUCCESS on success, status code (negative) on error + */ +static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode) +{ + u32 attributes; + u8 val; + efi_status_t ret; + + debug("Secure state from %d to %d\n", efi_secure_mode, mode); + + attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS; + if (mode == EFI_MODE_DEPLOYED) { + val = 1; + ret = efi_set_variable_internal(L"SecureBoot", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"SetupMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"AuditMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 1; + ret = efi_set_variable_internal(L"DeployedMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + + efi_secure_boot = true; + } else if (mode == EFI_MODE_AUDIT) { + ret = efi_set_variable_internal(L"PK", + &efi_global_variable_guid, + attributes, + 0, NULL, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"SecureBoot", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 1; + ret = efi_set_variable_internal(L"SetupMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 1; + ret = efi_set_variable_internal(L"AuditMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"DeployedMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + + efi_secure_boot = true; + } else if (mode == EFI_MODE_USER) { + val = 1; + ret = efi_set_variable_internal(L"SecureBoot", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"SetupMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"AuditMode", + &efi_global_variable_guid, + attributes, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"DeployedMode", + &efi_global_variable_guid, + attributes, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + + efi_secure_boot = true; + } else if (mode == EFI_MODE_SETUP) { + val = 0; + ret = efi_set_variable_internal(L"SecureBoot", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 1; + ret = efi_set_variable_internal(L"SetupMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"AuditMode", + &efi_global_variable_guid, + attributes, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"DeployedMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + } else { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; + +err: + /* TODO: What action should be taken here? */ + printf("ERROR: Secure state transition failed\n"); + return ret; +} + +/** + * efi_init_secure_state - initialize secure boot state + * + * Return: EFI_SUCCESS on success, status code (negative) on error + */ +static efi_status_t efi_init_secure_state(void) +{ + efi_uintn_t size = 0; + efi_status_t ret; + + ret = EFI_CALL(efi_get_variable(L"PK", &efi_global_variable_guid, + NULL, &size, NULL)); + if (ret == EFI_BUFFER_TOO_SMALL && IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) + ret = efi_transfer_secure_state(EFI_MODE_USER); + else + ret = efi_transfer_secure_state(EFI_MODE_SETUP); + + return ret; +} + /** * efi_secure_boot_enabled - return if secure boot is enabled or not * @@ -909,10 +1121,19 @@ efi_status_t EFIAPI efi_set_variable_common(u16 *variable_name, EFI_PRINT("setting: %s=%s\n", native_name, val); out: - if (env_set(native_name, val)) + if (env_set(native_name, val)) { ret = EFI_DEVICE_ERROR; - else + } else { + if ((u16_strcmp(variable_name, L"PK") == 0 && + guidcmp(vendor, &efi_global_variable_guid) == 0)) { + ret = efi_transfer_secure_state( + (delete ? EFI_MODE_SETUP : + EFI_MODE_USER)); + if (ret != EFI_SUCCESS) + goto err; + } ret = EFI_SUCCESS; + } err: free(native_name); @@ -1097,5 +1318,9 @@ void efi_variables_boot_exit_notify(void) */ efi_status_t efi_init_variables(void) { - return EFI_SUCCESS; + efi_status_t ret; + + ret = efi_init_secure_state(); + + return ret; }