From patchwork Fri Jan 28 22:20:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 1585977 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: bilbo.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=X3OUVvBV; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JlsNh750Pz9t3b for ; Sat, 29 Jan 2022 09:20:51 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 81F1E8210D; Fri, 28 Jan 2022 23:20:40 +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="X3OUVvBV"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D6DF2837B6; Fri, 28 Jan 2022 23:20:38 +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.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) (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 E1A7A81F0B for ; Fri, 28 Jan 2022 23:20:35 +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=ilias.apalodimas@linaro.org Received: by mail-ed1-x532.google.com with SMTP id n10so12625312edv.2 for ; Fri, 28 Jan 2022 14:20:35 -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:mime-version :content-transfer-encoding; bh=bRW2ondL7WU+1Ye5QXWiXg4FVQuXHAxElfoICrh8H6A=; b=X3OUVvBVlZQue2hvu9EJVkmYEvcFCy8AAqLZkKxDbUWttuSVQ/i77jCF0WsbVvAIpc kqJ31eYeJWjqWEESN6McvJUXmugGS0Wn6grD+XyM6MGXY/9TiTeZcu0Tp7myqlzo2Lwb nFcphEQACm4S7EnwPqGMAmn9uGt7Akg/idmVNQsz3ngfEcXYlYoFW9ndE6iGnONatSOI TIM1ypiW8MfA84mi6s95jNC4kex+ewSQJ7tJhhcEsrMNB9dnOurBlPymFRf2qsoBIz1J 4PMlbSnbPJExIY+rvqZjuhc/8Nuzl1jzfPKYw/YrUmYS0Zr0STZl8TyaLRwYhDGZtdLK sXIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=bRW2ondL7WU+1Ye5QXWiXg4FVQuXHAxElfoICrh8H6A=; b=qaKchStKiG876/vb6hyly2DmfS8/otTK/iRzbTEoOvLHeN1604OL92/7Nx1AX/DRlO tiRY64R+iJPj8Sqo/JbfK6EoOWKyhxQpyNYXPM+2HD7qcj0y2ehBwYm4sVRkZAd6Eb2n K98ZGzHCOjV8/xc7XN6Fz/UpA4PfmwTUpFEY+G7G20V3EaQmaGboHkY+u84mup4NChbx 2oppIfx14hIU6olSVCBFpe376rKkCJIEC24uVZ7q9+4NPkMkaVoVH8M5xjf3Zlx4ZU7m Br1FVGVx5XdqwGIum4y8m5v7e9sMkLB7FvkQI7gmv5A0X5Ae7gROr/arMIvFoZgx8803 +c2A== X-Gm-Message-State: AOAM530VaZrdvu5X3k1/85uUnxO0tnXkbr/UMt1mwFZ2KBXKsmiwc9SW DmTXjEp6IrrFeI92GRIKImpvvg== X-Google-Smtp-Source: ABdhPJyvBw2WRAwWOP5s9kLkw0Z6z5khEZDLrp8fzT8niaJsDkm+A7nOAFPk9nhPyGzIWOk+AXsTtA== X-Received: by 2002:a50:934c:: with SMTP id n12mr9947460eda.183.1643408435434; Fri, 28 Jan 2022 14:20:35 -0800 (PST) Received: from hades.. ([2a02:587:46a6:e776:230:64ff:fe3b:505d]) by smtp.gmail.com with ESMTPSA id v23sm10575038ejy.177.2022.01.28.14.20.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Jan 2022 14:20:34 -0800 (PST) From: Ilias Apalodimas To: xypron.glpk@gmx.de, takahiro.akashi@linaro.org Cc: Ilias Apalodimas , Heinrich Schuchardt , u-boot@lists.denx.de Subject: [PATCH 1/2 v2] efi_loader: correctly handle mixed hashes and signatures in db Date: Sat, 29 Jan 2022 00:20:31 +0200 Message-Id: <20220128222032.1772860-1-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.32.0 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.5 at phobos.denx.de X-Virus-Status: Clean A mix of signatures and hashes in db doesn't always work as intended. Currently if the digest algorithm is not explicitly set to sha256 we stop walking the security database and reject the image. That's problematic in case we find and try to check a signature before inspecting the sha256 hash. If the image is unsigned we will reject it even if the digest matches. Since we no longer reject the image on unknown algorithms add an explicit check and reject the image if any other hash algorithm apart from sha256 is detected on dbx. Suggested-by: Heinrich Schuchardt Signed-off-by: Ilias Apalodimas --- Changes since v1: - reject an image if an unknown sha digest type is present in dbx - Added a second patch fixing an existing issue causing the image sha256 caclulation to run more than once include/efi_api.h | 12 ++++++++ include/efi_loader.h | 3 +- lib/efi_loader/efi_image_loader.c | 8 ++--- lib/efi_loader/efi_signature.c | 49 ++++++++++++++++++++++++++----- 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index 8d5d835bd015..37d0749baa97 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -1845,9 +1845,21 @@ struct efi_system_resource_table { #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX 0x00004000 /* Certificate types in signature database */ +#define EFI_CERT_SHA1_GUID \ + EFI_GUID(0x826ca512, 0xcf10, 0x4ac9, 0xb1, 0x87, \ + 0xbe, 0x01, 0x49, 0x66, 0x31, 0xbd) +#define EFI_CERT_SHA224_GUID \ + EFI_GUID(0xb6e5233, 0xa65c, 0x44c9, 0x94, 0x07, \ + 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd) #define EFI_CERT_SHA256_GUID \ EFI_GUID(0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, \ 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28) +#define EFI_CERT_SHA384_GUID \ + EFI_GUID(0xff3e5307, 0x9fd0, 0x48c9, 0x85, 0xf1, \ + 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x01) +#define EFI_CERT_SHA512_GUID \ + EFI_GUID(0x93e0fae, 0xa6c4, 0x4f50, 0x9f, 0x1b, \ + 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a) #define EFI_CERT_RSA2048_GUID \ EFI_GUID(0x3c5766e8, 0x269c, 0x4e34, 0xaa, 0x14, \ 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6) diff --git a/include/efi_loader.h b/include/efi_loader.h index 701efcd2b623..a50fa9c010fd 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -910,7 +910,8 @@ struct x509_certificate; struct pkcs7_message; bool efi_signature_lookup_digest(struct efi_image_regions *regs, - struct efi_signature_store *db); + struct efi_signature_store *db, + bool dbx); bool efi_signature_verify(struct efi_image_regions *regs, struct pkcs7_message *msg, struct efi_signature_store *db, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 255613eb72ba..f43dfb3d57eb 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -545,13 +545,13 @@ static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs) } /* try black-list first */ - if (efi_signature_lookup_digest(regs, dbx)) { + if (efi_signature_lookup_digest(regs, dbx, true)) { EFI_PRINT("Image is not signed and its digest found in \"dbx\"\n"); goto out; } /* try white-list */ - if (efi_signature_lookup_digest(regs, db)) + if (efi_signature_lookup_digest(regs, db, false)) ret = true; else EFI_PRINT("Image is not signed and its digest not found in \"db\" or \"dbx\"\n"); @@ -633,7 +633,7 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) goto err; } - if (efi_signature_lookup_digest(regs, dbx)) { + if (efi_signature_lookup_digest(regs, dbx, true)) { EFI_PRINT("Image's digest was found in \"dbx\"\n"); goto err; } @@ -734,7 +734,7 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) EFI_PRINT("Signature was not verified by \"db\"\n"); - if (efi_signature_lookup_digest(regs, db)) { + if (efi_signature_lookup_digest(regs, db, false)) { ret = true; break; } diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index 3243e2c60de0..eb6886cdccd4 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -146,10 +146,35 @@ static bool efi_hash_regions(struct image_region *regs, int count, return true; } +/** + * hash_algo_supported - check if the requested hash algorithm is supported + * @guid: guid of the algorithm + * + * Return: true if supported false otherwise + */ +static bool hash_algo_supported(const efi_guid_t guid) +{ + int i; + const efi_guid_t unsupported_hashes[] = { + EFI_CERT_SHA1_GUID, + EFI_CERT_SHA224_GUID, + EFI_CERT_SHA384_GUID, + EFI_CERT_SHA512_GUID, + }; + + for (i = 0; i < ARRAY_SIZE(unsupported_hashes); i++) { + if (!guidcmp(&unsupported_hashes[i], &guid)) + return false; + } + + return true; +} + /** * efi_signature_lookup_digest - search for an image's digest in sigdb * @regs: List of regions to be authenticated * @db: Signature database for trusted certificates + * @dbx Caller needs to set this to true if he is searching dbx * * A message digest of image pointed to by @regs is calculated and * its hash value is compared to entries in signature database pointed @@ -158,7 +183,9 @@ static bool efi_hash_regions(struct image_region *regs, int count, * Return: true if found, false if not */ bool efi_signature_lookup_digest(struct efi_image_regions *regs, - struct efi_signature_store *db) + struct efi_signature_store *db, + bool dbx) + { struct efi_signature_store *siglist; struct efi_sig_data *sig_data; @@ -172,12 +199,20 @@ bool efi_signature_lookup_digest(struct efi_image_regions *regs, goto out; for (siglist = db; siglist; siglist = siglist->next) { - /* TODO: support other hash algorithms */ - if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) { - EFI_PRINT("Digest algorithm is not supported: %pUs\n", - &siglist->sig_type); - break; - } + /* + * if the hash algorithm is unsupported and we get an entry in + * dbx reject the image + */ + if (dbx && !hash_algo_supported(siglist->sig_type)) { + found = true; + continue; + }; + /* + * Only support sha256 for now, that's what + * hash-to-efi-sig-list produces + */ + if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) + continue; if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) { EFI_PRINT("Digesting an image failed\n");