From e30361e1864db1fd48b16a67059be39e32a36ca8 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 24 Aug 2020 09:18:07 +1000 Subject: [PATCH 1/2] Fix out of bounds read when writing to very long buffer mp_to_unsigned_bin_len() didn't handle buffers longer than maximum MP size. Fixed tfm and sp_int versions. --- wolfcrypt/src/sp_int.c | 5 ++++- wolfcrypt/src/tfm.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 952712fa0..072801135 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -442,13 +442,16 @@ int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz) int i, j, b; j = outSz - 1; - for (i=0; j>=0; i++) { + for (i = 0; j >= 0 && i < a->used; i++) { for (b = 0; b < SP_WORD_SIZE; b += 8) { out[j--] = a->dp[i] >> b; if (j < 0) break; } } + for (; j >= 0; j--) { + out[j] = 0; + } return MP_OKAY; } diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index bf128174e..35d4f806d 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -3645,12 +3645,15 @@ int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c) #if DIGIT_BIT == 64 || DIGIT_BIT == 32 int i, j, x; - for (x=c-1,j=0,i=0; x >= 0; x--) { + for (x=c-1, j=0, i=0; x >= 0 && i < a->used; x--) { b[x] = (unsigned char)(a->dp[i] >> j); j += 8; i += j == DIGIT_BIT; j &= DIGIT_BIT - 1; } + for (; x >= 0; x--) { + b[x] = 0; + } return FP_OKAY; #else From 4f44df96dc33d091a71b0826916870758c55d9ec Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 24 Aug 2020 22:48:52 +1000 Subject: [PATCH 2/2] MP: integer OOB write fix mp_to_unsigned_bin_len() now checks length passed in is greater than or equal length to write. --- wolfcrypt/src/integer.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index c7d2c7e34..6eaff1a62 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -321,9 +321,14 @@ int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c) len = mp_unsigned_bin_size(a); + if (len > c) { + return MP_VAL; + } + /* pad front w/ zeros to match length */ - for (i = 0; i < c - len; i++) - b[i] = 0x00; + for (i = 0; i < c - len; i++) { + b[i] = 0x00; + } return mp_to_unsigned_bin(a, b + i); }