From 6eb4626e3f2320aa9919fa4fcf0af03b7985e9fa Mon Sep 17 00:00:00 2001 From: Waleed Elmelegy Date: Fri, 9 Jun 2023 16:58:01 +0100 Subject: [PATCH 1/4] Fix crypt_and_hash decrypt issue when used with stream cipher crypt_and_hash decryption fails when used with a stream cipher mode of operation due to the input not being multiple of block size, this only applies to block cipher modes and not stream ciphers.This change exempts CTR, CFB & OFB modes from this check. Signed-off-by: Waleed Elmelegy --- programs/aes/crypt_and_hash.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c index 434c609e4..11eca7549 100644 --- a/programs/aes/crypt_and_hash.c +++ b/programs/aes/crypt_and_hash.c @@ -409,6 +409,9 @@ int main(int argc, char *argv[]) * Check the file size. */ if (cipher_info->mode != MBEDTLS_MODE_GCM && + cipher_info->mode != MBEDTLS_MODE_CTR && + cipher_info->mode != MBEDTLS_MODE_CFB && + cipher_info->mode != MBEDTLS_MODE_OFB && ((filesize - mbedtls_md_get_size(md_info)) % mbedtls_cipher_get_block_size(&cipher_ctx)) != 0) { mbedtls_fprintf(stderr, "File content not a multiple of the block size (%u).\n", From c451b4ae11577a065238606fe3b5ffcc9ae88963 Mon Sep 17 00:00:00 2001 From: Waleed Elmelegy Date: Mon, 12 Jun 2023 14:53:02 +0100 Subject: [PATCH 2/4] Replace function calls in crypt_and_hash program with locals Signed-off-by: Waleed Elmelegy --- programs/aes/crypt_and_hash.c | 40 +++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c index 11eca7549..17c8a3132 100644 --- a/programs/aes/crypt_and_hash.c +++ b/programs/aes/crypt_and_hash.c @@ -92,6 +92,8 @@ int main(int argc, char *argv[]) const mbedtls_md_info_t *md_info; mbedtls_cipher_context_t cipher_ctx; mbedtls_md_context_t md_ctx; + unsigned int cipher_block_size; + unsigned char md_size; #if defined(_WIN32_WCE) long filesize, offset; #elif defined(_WIN32) @@ -240,6 +242,9 @@ int main(int argc, char *argv[]) goto exit; } + md_size = mbedtls_md_get_size(md_info); + cipher_block_size = mbedtls_cipher_get_block_size(&cipher_ctx); + if (mode == MODE_ENCRYPT) { /* * Generate the initialization vector as: @@ -332,9 +337,9 @@ int main(int argc, char *argv[]) /* * Encrypt and write the ciphertext. */ - for (offset = 0; offset < filesize; offset += mbedtls_cipher_get_block_size(&cipher_ctx)) { - ilen = ((unsigned int) filesize - offset > mbedtls_cipher_get_block_size(&cipher_ctx)) ? - mbedtls_cipher_get_block_size(&cipher_ctx) : (unsigned int) (filesize - offset); + for (offset = 0; offset < filesize; offset += cipher_block_size) { + ilen = ((unsigned int) filesize - offset > cipher_block_size) ? + cipher_block_size : (unsigned int) (filesize - offset); if (fread(buffer, 1, ilen, fin) != ilen) { mbedtls_fprintf(stderr, "fread(%ld bytes) failed\n", (long) ilen); @@ -379,8 +384,8 @@ int main(int argc, char *argv[]) goto exit; } - if (fwrite(digest, 1, mbedtls_md_get_size(md_info), fout) != mbedtls_md_get_size(md_info)) { - mbedtls_fprintf(stderr, "fwrite(%d bytes) failed\n", mbedtls_md_get_size(md_info)); + if (fwrite(digest, 1, md_size, fout) != md_size) { + mbedtls_fprintf(stderr, "fwrite(%d bytes) failed\n", md_size); goto exit; } } @@ -395,12 +400,12 @@ int main(int argc, char *argv[]) * N*16 .. (N+1)*16 - 1 Encrypted Block #N * (N+1)*16 .. (N+1)*16 + n Hash(ciphertext) */ - if (filesize < 16 + mbedtls_md_get_size(md_info)) { + if (filesize < 16 + md_size) { mbedtls_fprintf(stderr, "File too short to be encrypted.\n"); goto exit; } - if (mbedtls_cipher_get_block_size(&cipher_ctx) == 0) { + if (cipher_block_size == 0) { mbedtls_fprintf(stderr, "Invalid cipher block size: 0. \n"); goto exit; } @@ -412,17 +417,16 @@ int main(int argc, char *argv[]) cipher_info->mode != MBEDTLS_MODE_CTR && cipher_info->mode != MBEDTLS_MODE_CFB && cipher_info->mode != MBEDTLS_MODE_OFB && - ((filesize - mbedtls_md_get_size(md_info)) % - mbedtls_cipher_get_block_size(&cipher_ctx)) != 0) { + ((filesize - md_size) % cipher_block_size) != 0) { mbedtls_fprintf(stderr, "File content not a multiple of the block size (%u).\n", - mbedtls_cipher_get_block_size(&cipher_ctx)); + cipher_block_size); goto exit; } /* * Subtract the IV + HMAC length. */ - filesize -= (16 + mbedtls_md_get_size(md_info)); + filesize -= (16 + md_size); /* * Read the IV and original filesize modulo 16. @@ -484,13 +488,13 @@ int main(int argc, char *argv[]) /* * Decrypt and write the plaintext. */ - for (offset = 0; offset < filesize; offset += mbedtls_cipher_get_block_size(&cipher_ctx)) { - ilen = ((unsigned int) filesize - offset > mbedtls_cipher_get_block_size(&cipher_ctx)) ? - mbedtls_cipher_get_block_size(&cipher_ctx) : (unsigned int) (filesize - offset); + for (offset = 0; offset < filesize; offset += cipher_block_size) { + ilen = ((unsigned int) filesize - offset > cipher_block_size) ? + cipher_block_size : (unsigned int) (filesize - offset); if (fread(buffer, 1, ilen, fin) != ilen) { mbedtls_fprintf(stderr, "fread(%u bytes) failed\n", - mbedtls_cipher_get_block_size(&cipher_ctx)); + cipher_block_size); goto exit; } @@ -518,14 +522,14 @@ int main(int argc, char *argv[]) goto exit; } - if (fread(buffer, 1, mbedtls_md_get_size(md_info), fin) != mbedtls_md_get_size(md_info)) { - mbedtls_fprintf(stderr, "fread(%d bytes) failed\n", mbedtls_md_get_size(md_info)); + if (fread(buffer, 1, md_size, fin) != md_size) { + mbedtls_fprintf(stderr, "fread(%d bytes) failed\n", md_size); goto exit; } /* Use constant-time buffer comparison */ diff = 0; - for (i = 0; i < mbedtls_md_get_size(md_info); i++) { + for (i = 0; i < md_size; i++) { diff |= digest[i] ^ buffer[i]; } From 558bdc3f422f342a05c9952892e1d5c45cb4dcb0 Mon Sep 17 00:00:00 2001 From: Waleed Elmelegy Date: Mon, 12 Jun 2023 17:37:23 +0100 Subject: [PATCH 3/4] Add crypt_and_hash decrypt issue to Changelog Signed-off-by: Waleed Elmelegy --- ChangeLog.d/fix-crypt_and_hash-decrypt-issue.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ChangeLog.d/fix-crypt_and_hash-decrypt-issue.txt diff --git a/ChangeLog.d/fix-crypt_and_hash-decrypt-issue.txt b/ChangeLog.d/fix-crypt_and_hash-decrypt-issue.txt new file mode 100644 index 000000000..ded9b2d47 --- /dev/null +++ b/ChangeLog.d/fix-crypt_and_hash-decrypt-issue.txt @@ -0,0 +1,4 @@ +Bugfix + * Fix crypt_and_hash decryption fail when used with a stream cipher + mode of operation due to the input not being multiple of block size. + Resolves #7417. From 6a4af481e19fea64d0e42f9bd53601c29a8671ed Mon Sep 17 00:00:00 2001 From: Waleed Elmelegy Date: Mon, 26 Jun 2023 11:28:42 +0100 Subject: [PATCH 4/4] Replace struct access with local variable Replace struct access with local variable to minimize differnces with development branch. Signed-off-by: Waleed Elmelegy --- programs/aes/crypt_and_hash.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c index 17c8a3132..98253c6d7 100644 --- a/programs/aes/crypt_and_hash.c +++ b/programs/aes/crypt_and_hash.c @@ -92,6 +92,7 @@ int main(int argc, char *argv[]) const mbedtls_md_info_t *md_info; mbedtls_cipher_context_t cipher_ctx; mbedtls_md_context_t md_ctx; + mbedtls_cipher_mode_t cipher_mode; unsigned int cipher_block_size; unsigned char md_size; #if defined(_WIN32_WCE) @@ -413,10 +414,11 @@ int main(int argc, char *argv[]) /* * Check the file size. */ - if (cipher_info->mode != MBEDTLS_MODE_GCM && - cipher_info->mode != MBEDTLS_MODE_CTR && - cipher_info->mode != MBEDTLS_MODE_CFB && - cipher_info->mode != MBEDTLS_MODE_OFB && + cipher_mode = cipher_info->mode; + if (cipher_mode != MBEDTLS_MODE_GCM && + cipher_mode != MBEDTLS_MODE_CTR && + cipher_mode != MBEDTLS_MODE_CFB && + cipher_mode != MBEDTLS_MODE_OFB && ((filesize - md_size) % cipher_block_size) != 0) { mbedtls_fprintf(stderr, "File content not a multiple of the block size (%u).\n", cipher_block_size);