From: Omar Almahri <[email protected]>

rsa_gen_key_prop() copies the DER public exponent into a fixed 8 byte
buffer with memcpy(pub_exp + sizeof(uint64_t) - e_sz, e, e_sz). e_sz
comes from the key and is only bounded by e_sz <= n_sz in rsa_get_e(),
nothing limits it to 8 bytes. Since e_sz is a size_t, an exponent larger
than 8 bytes underflows the destination to pub_exp - (e_sz - 8) and
writes attacker-controlled bytes below the allocation. A 256 byte
exponent gives a 248 byte heap underflow of controlled content.

It's reachable while verifying a certificate embedded in an
attacker-supplied PKCS#7 (efi_signature.c -> pkcs7_verify_one ->
public_key_verify_signature -> rsa_verify_with_pkey -> rsa_gen_key_prop),
before the cert is checked against the trust anchors, so on a Secure Boot
board it's pre-trust.

The fix rejects an exponent that doesn't fit the 8 byte buffer before the
copy.

Reported-by: Omar A. <[email protected]>
Fixes: e0d310b098b1 ("lib: rsa: generate additional parameters for public key")
Signed-off-by: Omar Almahri <[email protected]>
Reviewed-by: Heinrich Schuchardt <[email protected]>
---
 lib/rsa/rsa-keyprop.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/lib/rsa/rsa-keyprop.c b/lib/rsa/rsa-keyprop.c
index 80d0594a430..2ac039ac3f4 100644
--- a/lib/rsa/rsa-keyprop.c
+++ b/lib/rsa/rsa-keyprop.c
@@ -665,6 +665,16 @@ int rsa_gen_key_prop(const void *key, uint32_t keylen, 
struct key_prop **prop)
        if (ret)
                goto out;
 
+       /*
+        * The public exponent is copied right-justified into an 8-byte
+        * buffer below; an exponent longer than that buffer underflows the
+        * destination pointer and writes out of bounds. Reject it here.
+        */
+       if (rsa_key.e_sz > sizeof(uint64_t)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        /* modulus */
        /* removing leading 0's */
        for (i = 0; i < rsa_key.n_sz && !rsa_key.n[i]; i++)
-- 
2.53.0

Reply via email to