n and rr are sized with a floor division by 32 (num_bits >> 5), but
br_i32_decode() and the zero-init loop before br_i32_reduce() need
ceil(bits/32) words plus a header word. Whenever the stripped modulus
byte length isn't a multiple of 4, br_i32_decode() writes one word
past the end of n; whenever it's odd, the zero-init loop writes one
zero word past the end of rr. The modulus length is fully
attacker-controlled via the DER public key's ASN.1 INTEGER length, so
both overflows are reachable with a crafted key.
Switch both allocations to ceiling division so they always hold the
full word count each site writes, using DIV_ROUND_UP() instead of
open-coded rounding for readability. rrtmp is already exactly sized
and is left unchanged.
Fixes: 49d0ea3746c ("lib: rsa: fix allocated size for rr and rrtmp in
rsa_gen_key_prop()")
Signed-off-by: Prasad Kummari <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
---
lib/rsa/rsa-keyprop.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/rsa/rsa-keyprop.c b/lib/rsa/rsa-keyprop.c
index 2ac039ac3f4..ca186a1440c 100644
--- a/lib/rsa/rsa-keyprop.c
+++ b/lib/rsa/rsa-keyprop.c
@@ -12,6 +12,7 @@
#include <image.h>
#include <malloc.h>
#include <crypto/internal/rsa.h>
+#include <linux/kernel.h>
#include <u-boot/rsa-mod-exp.h>
#include <asm/unaligned.h>
@@ -687,8 +688,9 @@ int rsa_gen_key_prop(const void *key, uint32_t keylen,
struct key_prop **prop)
}
memcpy((void *)(*prop)->modulus, &rsa_key.n[i], rsa_key.n_sz - i);
- n = calloc(sizeof(uint32_t), 1 + ((*prop)->num_bits >> 5));
- rr = calloc(sizeof(uint32_t), 1 + (((*prop)->num_bits * 2) >> 5));
+ n = calloc(sizeof(uint32_t), 1 + DIV_ROUND_UP((*prop)->num_bits, 32));
+ rr = calloc(sizeof(uint32_t),
+ 1 + DIV_ROUND_UP((*prop)->num_bits * 2, 32));
rrtmp = calloc(sizeof(uint32_t), 2 + (((*prop)->num_bits * 2) >> 5));
if (!n || !rr || !rrtmp) {
ret = -ENOMEM;
--
2.43.0