[PATCH 1/1] rsa: fix retrieving public exponent on big-endian systems

Rasmus Villemoes rasmus.villemoes at prevas.dk
Tue Oct 6 12:09:45 CEST 2020


Commit fdf0819afb (rsa: fix alignment issue when getting public
exponent) changed the logic to avoid doing an 8-byte access to a
possibly-not-8-byte-aligned address.

However, using rsa_convert_big_endian is wrong: That function converts
an array of big-endian (32-bit) words with the most significant word
first (aka a BE byte array) to an array of cpu-endian words with the
least significant word first. While the exponent is indeed _stored_ as
a big-endian 64-bit word (two BE words with MSW first), we want to
extract it as a cpu-endian 64 bit word. On a little-endian host,
swapping the words and byte-swapping each 32-bit word works, because
that's the same as byte-swapping the whole 64 bit word. But on a
big-endian host, the fdt32_to_cpu are no-ops, but
rsa_convert_big_endian() still does the word-swapping, breaking
verified boot.

To fix that, while still ensuring we don't do unaligned accesses, add
a little helper that first memcpy's the bytes to a local fdt64_t, then
applies fdt64_to_cpu(). [The name is chosen based on the
[bl]eXX_to_cpup in linux/byteorder/generic.h].

Fixes: fdf0819afb ("rsa: fix alignment issue when getting public exponent")
Signed-off-by: Rasmus Villemoes <rasmus.villemoes at prevas.dk>
---
 lib/rsa/rsa-mod-exp.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/lib/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c
index a437cbe26f..78c688d14c 100644
--- a/lib/rsa/rsa-mod-exp.c
+++ b/lib/rsa/rsa-mod-exp.c
@@ -25,6 +25,14 @@
 #define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a)
 #define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a))
 
+static inline uint64_t fdt64_to_cpup(const void *p)
+{
+	fdt64_t w;
+
+	memcpy(&w, p, sizeof(w));
+	return fdt64_to_cpu(w);
+}
+
 /* Default public exponent for backward compatibility */
 #define RSA_DEFAULT_PUBEXP	65537
 
@@ -263,8 +271,7 @@ int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len,
 	if (!prop->public_exponent)
 		key.exponent = RSA_DEFAULT_PUBEXP;
 	else
-		rsa_convert_big_endian((uint32_t *)&key.exponent,
-				       prop->public_exponent, 2);
+		key.exponent = fdt64_to_cpup(prop->public_exponent);
 
 	if (!key.len || !prop->modulus || !prop->rr) {
 		debug("%s: Missing RSA key info", __func__);
-- 
2.23.0



More information about the U-Boot mailing list