From ed798a9092b1259c0c20b6638d2f585290001d0e Mon Sep 17 00:00:00 2001 From: openluopworld Date: Fri, 5 Nov 2021 19:40:40 +0800 Subject: [PATCH] An initialization vector IV can have any number of bits between 1 and 2^64. So it should be filled to the lower 64-bit in the last step when computing ghash. Signed-off-by: openluopworld --- ChangeLog.d/bugfix-for-gcm-long-iv-size.txt | 3 +++ library/gcm.c | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 ChangeLog.d/bugfix-for-gcm-long-iv-size.txt diff --git a/ChangeLog.d/bugfix-for-gcm-long-iv-size.txt b/ChangeLog.d/bugfix-for-gcm-long-iv-size.txt new file mode 100644 index 000000000000..0e46ad3780ec --- /dev/null +++ b/ChangeLog.d/bugfix-for-gcm-long-iv-size.txt @@ -0,0 +1,3 @@ +Bugfix + * Fix a bug in mbedtls_gcm_starts() when bits of iv are longer than 2^32. + * Fix #4884. diff --git a/library/gcm.c b/library/gcm.c index 2afe5025a09e..441ed69a82f7 100644 --- a/library/gcm.c +++ b/library/gcm.c @@ -111,6 +111,20 @@ } #endif +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE( n, b, i ) \ +{ \ + ( b )[( i ) ] = (unsigned char) ( ( (n) >> 56 ) & 0xff ); \ + ( b )[( i ) + 1] = (unsigned char) ( ( (n) >> 48 ) & 0xff ); \ + ( b )[( i ) + 2] = (unsigned char) ( ( (n) >> 40 ) & 0xff ); \ + ( b )[( i ) + 3] = (unsigned char) ( ( (n) >> 32 ) & 0xff ); \ + ( b )[( i ) + 4] = (unsigned char) ( ( (n) >> 24 ) & 0xff ); \ + ( b )[( i ) + 5] = (unsigned char) ( ( (n) >> 16 ) & 0xff ); \ + ( b )[( i ) + 6] = (unsigned char) ( ( (n) >> 8 ) & 0xff ); \ + ( b )[( i ) + 7] = (unsigned char) ( ( (n) ) & 0xff ); \ +} +#endif + /* * Initialize a context */ @@ -309,6 +323,7 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, size_t i; const unsigned char *p; size_t use_len, olen = 0; + uint64_t iv_bits; GCM_VALIDATE_RET( ctx != NULL ); GCM_VALIDATE_RET( iv != NULL ); @@ -338,7 +353,8 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, else { memset( work_buf, 0x00, 16 ); - PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); + iv_bits = (uint64_t)iv_len * 8; + PUT_UINT64_BE( iv_bits, work_buf, 8 ); p = iv; while( iv_len > 0 )