[PATCH v8 05/15] lib: rsa: internalize PKCS#1 DigestInfo prefixes

James Hilliard <[email protected]>
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <20260814-submit-ce-series-v2-v8-5-fe9212431a94__23787.386207708$1786798909$gmane$org@gmail.com>
The checksum algorithm table is shared by RSA and ECDSA, but its DER
prefix fields are used only by RSA PKCS#1 v1.5 padding verification.
Keeping those prefixes in the software hash implementations also ties
signature metadata to a particular hash backend and duplicates it between
the legacy and MbedTLS shims.

Keep the SHA-1, SHA-256, SHA-384 and SHA-512 DigestInfo prefixes in the RSA
verifier instead. Select the prefix by checksum name when checking PKCS#1
v1.5 padding, include every algorithm in host tools and only configured
algorithms in target builds, and reject padding which is too short for the
required eight-byte padding string.

Remove the DER fields from the generic checksum descriptor and remove the
now-unneeded constants from the hash implementations. ECDSA-only and
hardware-hash-only builds then carry no RSA-specific DigestInfo data.

Reviewed-by: Simon Glass <[email protected]>
Signed-off-by: James Hilliard <[email protected]>
---
Changes v6 -> v7:
  - New patch
---
 boot/image-sig.c        |  8 ------
 include/image.h         |  2 --
 include/u-boot/sha1.h   |  3 ---
 include/u-boot/sha256.h |  3 ---
 include/u-boot/sha512.h |  6 -----
 lib/mbedtls/sha1.c      |  5 ----
 lib/mbedtls/sha256.c    |  6 -----
 lib/mbedtls/sha512.c    | 12 ---------
 lib/rsa/rsa-verify.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++++---
 lib/sha1.c              |  5 ----
 lib/sha256.c            |  6 -----
 lib/sha512.c            | 12 ---------
 tools/image-sig-host.c  |  8 ------
 13 files changed, 63 insertions(+), 80 deletions(-)

diff --git a/boot/image-sig.c b/boot/image-sig.c
index 4eab017bc2d..80a9c4325bd 100644
--- a/boot/image-sig.c
+++ b/boot/image-sig.c
@@ -18,8 +18,6 @@ struct checksum_algo checksum_algos[] = {
 	{
 		.name = "sha1",
 		.checksum_len = SHA1_SUM_LEN,
-		.der_len = SHA1_DER_LEN,
-		.der_prefix = sha1_der_prefix,
 		.calculate = hash_calculate,
 	},
 #endif
@@ -27,8 +25,6 @@ struct checksum_algo checksum_algos[] = {
 	{
 		.name = "sha256",
 		.checksum_len = SHA256_SUM_LEN,
-		.der_len = SHA256_DER_LEN,
-		.der_prefix = sha256_der_prefix,
 		.calculate = hash_calculate,
 	},
 #endif
@@ -36,8 +32,6 @@ struct checksum_algo checksum_algos[] = {
 	{
 		.name = "sha384",
 		.checksum_len = SHA384_SUM_LEN,
-		.der_len = SHA384_DER_LEN,
-		.der_prefix = sha384_der_prefix,
 		.calculate = hash_calculate,
 	},
 #endif
@@ -45,8 +39,6 @@ struct checksum_algo checksum_algos[] = {
 	{
 		.name = "sha512",
 		.checksum_len = SHA512_SUM_LEN,
-		.der_len = SHA512_DER_LEN,
-		.der_prefix = sha512_der_prefix,
 		.calculate = hash_calculate,
 	},
 #endif
diff --git a/include/image.h b/include/image.h
index 6edcb1995bf..b7086528e47 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1660,8 +1660,6 @@ struct image_region {
 struct checksum_algo {
 	const char *name;
 	const int checksum_len;
-	const int der_len;
-	const uint8_t *der_prefix;
 #if IMAGE_ENABLE_SIGN
 	const EVP_MD *(*calculate_sign)(void);
 #endif
diff --git a/include/u-boot/sha1.h b/include/u-boot/sha1.h
index c2d62e9cf0f..7a167130dae 100644
--- a/include/u-boot/sha1.h
+++ b/include/u-boot/sha1.h
@@ -28,7 +28,6 @@ extern "C" {
 
 #define SHA1_SUM_POS	-0x20
 #define SHA1_SUM_LEN	20
-#define SHA1_DER_LEN	15
 
 #define SHA1_DEF_CHUNK_SZ 0x10000
 
@@ -36,8 +35,6 @@ extern "C" {
 #define K_OPAD_VAL 0x5C
 #define K_PAD_LEN 64
 
-extern const uint8_t sha1_der_prefix[];
-
 #if CONFIG_IS_ENABLED(MBEDTLS_LIB_CRYPTO)
 typedef mbedtls_sha1_context sha1_context;
 #else
diff --git a/include/u-boot/sha256.h b/include/u-boot/sha256.h
index 2d86508332e..4137b0c5851 100644
--- a/include/u-boot/sha256.h
+++ b/include/u-boot/sha256.h
@@ -13,9 +13,6 @@
 
 #define SHA224_SUM_LEN	28
 #define SHA256_SUM_LEN	32
-#define SHA256_DER_LEN	19
-
-extern const uint8_t sha256_der_prefix[];
 
 /* Reset watchdog each time we process this many bytes */
 #define CHUNKSZ_SHA256	(64 * 1024)
diff --git a/include/u-boot/sha512.h b/include/u-boot/sha512.h
index 92660d93357..d186238d856 100644
--- a/include/u-boot/sha512.h
+++ b/include/u-boot/sha512.h
@@ -9,9 +9,7 @@
 #endif
 
 #define SHA384_SUM_LEN          48
-#define SHA384_DER_LEN          19
 #define SHA512_SUM_LEN          64
-#define SHA512_DER_LEN          19
 #define SHA512_BLOCK_SIZE       128
 
 #define CHUNKSZ_SHA384	(16 * 1024)
@@ -28,8 +26,6 @@ typedef struct {
 } sha512_context;
 #endif
 
-extern const uint8_t sha512_der_prefix[];
-
 void sha512_starts(sha512_context * ctx);
 void sha512_update(sha512_context *ctx, const uint8_t *input, uint32_t length);
 void sha512_finish(sha512_context * ctx, uint8_t digest[SHA512_SUM_LEN]);
@@ -37,8 +33,6 @@ void sha512_finish(sha512_context * ctx, uint8_t digest[SHA512_SUM_LEN]);
 void sha512_csum_wd(const unsigned char *input, unsigned int ilen,
 		unsigned char *output, unsigned int chunk_sz);
 
-extern const uint8_t sha384_der_prefix[];
-
 void sha384_starts(sha512_context * ctx);
 void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length);
 void sha384_finish(sha512_context * ctx, uint8_t digest[SHA384_SUM_LEN]);
diff --git a/lib/mbedtls/sha1.c b/lib/mbedtls/sha1.c
index 2aee5037795..3dbec314e11 100644
--- a/lib/mbedtls/sha1.c
+++ b/lib/mbedtls/sha1.c
@@ -11,11 +11,6 @@
 #include <string.h>
 #include <u-boot/sha1.h>
 
-const u8 sha1_der_prefix[SHA1_DER_LEN] = {
-	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
-	0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
-};
-
 void sha1_starts(sha1_context *ctx)
 {
 	mbedtls_sha1_init(ctx);
diff --git a/lib/mbedtls/sha256.c b/lib/mbedtls/sha256.c
index 59edcb517df..d4b97a1c16d 100644
--- a/lib/mbedtls/sha256.c
+++ b/lib/mbedtls/sha256.c
@@ -16,12 +16,6 @@
 #include <mbedtls/hkdf.h>
 #endif
 
-const u8 sha256_der_prefix[SHA256_DER_LEN] = {
-	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
-	0x00, 0x04, 0x20
-};
-
 void sha256_starts(sha256_context *ctx)
 {
 	mbedtls_sha256_init(ctx);
diff --git a/lib/mbedtls/sha512.c b/lib/mbedtls/sha512.c
index 5615248cb91..308edcbd635 100644
--- a/lib/mbedtls/sha512.c
+++ b/lib/mbedtls/sha512.c
@@ -11,18 +11,6 @@
 #include <compiler.h>
 #include <u-boot/sha512.h>
 
-const u8 sha384_der_prefix[SHA384_DER_LEN] = {
-	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
-	0x00, 0x04, 0x30
-};
-
-const u8 sha512_der_prefix[SHA512_DER_LEN] = {
-	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
-	0x00, 0x04, 0x40
-};
-
 void sha384_starts(sha512_context *ctx)
 {
 	mbedtls_sha512_init(ctx);
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index 3169c3a6dd1..5b70c971c31 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -25,6 +25,56 @@
 /* Default public exponent for backward compatibility */
 #define RSA_DEFAULT_PUBEXP	65537
 
+static const unsigned char rsa_sha1_der_prefix[] = {
+	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
+	0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
+};
+
+static const unsigned char rsa_sha256_der_prefix[] = {
+	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
+	0x00, 0x04, 0x20
+};
+
+static const unsigned char rsa_sha384_der_prefix[] = {
+	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
+	0x00, 0x04, 0x30
+};
+
+static const unsigned char rsa_sha512_der_prefix[] = {
+	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
+	0x00, 0x04, 0x40
+};
+
+static int rsa_get_digest_info(const char *name,
+			       const unsigned char **der_prefix)
+{
+	if ((tools_build() || CONFIG_IS_ENABLED(SHA1)) &&
+	    !strcmp(name, "sha1")) {
+		*der_prefix = rsa_sha1_der_prefix;
+		return sizeof(rsa_sha1_der_prefix);
+	}
+	if ((tools_build() || CONFIG_IS_ENABLED(SHA256)) &&
+	    !strcmp(name, "sha256")) {
+		*der_prefix = rsa_sha256_der_prefix;
+		return sizeof(rsa_sha256_der_prefix);
+	}
+	if ((tools_build() || CONFIG_IS_ENABLED(SHA384)) &&
+	    !strcmp(name, "sha384")) {
+		*der_prefix = rsa_sha384_der_prefix;
+		return sizeof(rsa_sha384_der_prefix);
+	}
+	if ((tools_build() || CONFIG_IS_ENABLED(SHA512)) &&
+	    !strcmp(name, "sha512")) {
+		*der_prefix = rsa_sha512_der_prefix;
+		return sizeof(rsa_sha512_der_prefix);
+	}
+
+	return -EINVAL;
+}
+
 /**
  * rsa_verify_padding() - Verify RSA message padding is valid
  *
@@ -33,28 +83,37 @@
  *
  * @msg:	Padded message
  * @pad_len:	Number of expected padding bytes
- * @algo:	Checksum algo structure having information on DER encoding etc.
+ * @algo:	Checksum algorithm used to select the DigestInfo prefix
  * Return: 0 on success, != 0 on failure
  */
 static int rsa_verify_padding(const uint8_t *msg, const int pad_len,
-			      struct checksum_algo *algo)
+			      const struct checksum_algo *algo)
 {
+	const unsigned char *der_prefix;
+	int der_len;
 	int ff_len;
 	int ret;
 
+	der_len = rsa_get_digest_info(algo->name, &der_prefix);
+	if (der_len < 0)
+		return der_len;
+
+	ff_len = pad_len - der_len - 3;
+	if (ff_len < 8)
+		return -EINVAL;
+
 	/* first byte must be 0x00 */
 	ret = *msg++;
 	/* second byte must be 0x01 */
 	ret |= *msg++ ^ 0x01;
 	/* next ff_len bytes must be 0xff */
-	ff_len = pad_len - algo->der_len - 3;
 	ret |= *msg ^ 0xff;
 	ret |= memcmp(msg, msg+1, ff_len-1);
 	msg += ff_len;
 	/* next byte must be 0x00 */
 	ret |= *msg++;
 	/* next der_len bytes must match der_prefix */
-	ret |= memcmp(msg, algo->der_prefix, algo->der_len);
+	ret |= memcmp(msg, der_prefix, der_len);
 
 	return ret;
 }
diff --git a/lib/sha1.c b/lib/sha1.c
index be502c6126b..4f35850b384 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -24,11 +24,6 @@
 
 #include <linux/compiler_attributes.h>
 
-const uint8_t sha1_der_prefix[SHA1_DER_LEN] = {
-	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
-	0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
-};
-
 /*
  * 32-bit integer manipulation macros (big endian)
  */
diff --git a/lib/sha256.c b/lib/sha256.c
index c2e77c854b9..b99f8105c8d 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -13,12 +13,6 @@
 
 #include <linux/compiler_attributes.h>
 
-const uint8_t sha256_der_prefix[SHA256_DER_LEN] = {
-	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
-	0x00, 0x04, 0x20
-};
-
 /*
  * 32-bit integer manipulation macros (big endian)
  */
diff --git a/lib/sha512.c b/lib/sha512.c
index 0e75c1a943b..06d9b5564f9 100644
--- a/lib/sha512.c
+++ b/lib/sha512.c
@@ -16,18 +16,6 @@
 #include <compiler.h>
 #include <u-boot/sha512.h>
 
-const uint8_t sha384_der_prefix[SHA384_DER_LEN] = {
-	0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
-	0x00, 0x04, 0x30
-};
-
-const uint8_t sha512_der_prefix[SHA512_DER_LEN] = {
-	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
-	0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
-	0x00, 0x04, 0x40
-};
-
 #define SHA384_H0	0xcbbb9d5dc1059ed8ULL
 #define SHA384_H1	0x629a292a367cd507ULL
 #define SHA384_H2	0x9159015a3070dd17ULL
diff --git a/tools/image-sig-host.c b/tools/image-sig-host.c
index 5285263c616..758f14337ed 100644
--- a/tools/image-sig-host.c
+++ b/tools/image-sig-host.c
@@ -16,32 +16,24 @@ struct checksum_algo checksum_algos[] = {
 	{
 		.name = "sha1",
 		.checksum_len = SHA1_SUM_LEN,
-		.der_len = SHA1_DER_LEN,
-		.der_prefix = sha1_der_prefix,
 		.calculate_sign = EVP_sha1,
 		.calculate = hash_calculate,
 	},
 	{
 		.name = "sha256",
 		.checksum_len = SHA256_SUM_LEN,
-		.der_len = SHA256_DER_LEN,
-		.der_prefix = sha256_der_prefix,
 		.calculate_sign = EVP_sha256,
 		.calculate = hash_calculate,
 	},
 	{
 		.name = "sha384",
 		.checksum_len = SHA384_SUM_LEN,
-		.der_len = SHA384_DER_LEN,
-		.der_prefix = sha384_der_prefix,
 		.calculate_sign = EVP_sha384,
 		.calculate = hash_calculate,
 	},
 	{
 		.name = "sha512",
 		.checksum_len = SHA512_SUM_LEN,
-		.der_len = SHA512_DER_LEN,
-		.der_prefix = sha512_der_prefix,
 		.calculate_sign = EVP_sha512,
 		.calculate = hash_calculate,
 	},

-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.