Merge pull request #7761 from waleed-elmelegy-arm/crypt_and_hash-decrypt-fix_backport

Backport 2.28: Fix crypt_and_hash decrypt issue when used with stream cipher
This commit is contained in:
Dave Rodgman 2023-06-30 11:42:19 +01:00 committed by GitHub
commit 3fb807c064
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 19 deletions

View File

@ -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.

View File

@ -92,6 +92,9 @@ int main(int argc, char *argv[])
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
mbedtls_cipher_context_t cipher_ctx; mbedtls_cipher_context_t cipher_ctx;
mbedtls_md_context_t md_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) #if defined(_WIN32_WCE)
long filesize, offset; long filesize, offset;
#elif defined(_WIN32) #elif defined(_WIN32)
@ -240,6 +243,9 @@ int main(int argc, char *argv[])
goto exit; goto exit;
} }
md_size = mbedtls_md_get_size(md_info);
cipher_block_size = mbedtls_cipher_get_block_size(&cipher_ctx);
if (mode == MODE_ENCRYPT) { if (mode == MODE_ENCRYPT) {
/* /*
* Generate the initialization vector as: * Generate the initialization vector as:
@ -332,9 +338,9 @@ int main(int argc, char *argv[])
/* /*
* Encrypt and write the ciphertext. * Encrypt and write the ciphertext.
*/ */
for (offset = 0; offset < filesize; offset += mbedtls_cipher_get_block_size(&cipher_ctx)) { for (offset = 0; offset < filesize; offset += cipher_block_size) {
ilen = ((unsigned int) filesize - offset > mbedtls_cipher_get_block_size(&cipher_ctx)) ? ilen = ((unsigned int) filesize - offset > cipher_block_size) ?
mbedtls_cipher_get_block_size(&cipher_ctx) : (unsigned int) (filesize - offset); cipher_block_size : (unsigned int) (filesize - offset);
if (fread(buffer, 1, ilen, fin) != ilen) { if (fread(buffer, 1, ilen, fin) != ilen) {
mbedtls_fprintf(stderr, "fread(%ld bytes) failed\n", (long) ilen); mbedtls_fprintf(stderr, "fread(%ld bytes) failed\n", (long) ilen);
@ -379,8 +385,8 @@ int main(int argc, char *argv[])
goto exit; goto exit;
} }
if (fwrite(digest, 1, mbedtls_md_get_size(md_info), fout) != mbedtls_md_get_size(md_info)) { if (fwrite(digest, 1, md_size, fout) != md_size) {
mbedtls_fprintf(stderr, "fwrite(%d bytes) failed\n", mbedtls_md_get_size(md_info)); mbedtls_fprintf(stderr, "fwrite(%d bytes) failed\n", md_size);
goto exit; goto exit;
} }
} }
@ -395,12 +401,12 @@ int main(int argc, char *argv[])
* N*16 .. (N+1)*16 - 1 Encrypted Block #N * N*16 .. (N+1)*16 - 1 Encrypted Block #N
* (N+1)*16 .. (N+1)*16 + n Hash(ciphertext) * (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"); mbedtls_fprintf(stderr, "File too short to be encrypted.\n");
goto exit; 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"); mbedtls_fprintf(stderr, "Invalid cipher block size: 0. \n");
goto exit; goto exit;
} }
@ -408,18 +414,21 @@ int main(int argc, char *argv[])
/* /*
* Check the file size. * Check the file size.
*/ */
if (cipher_info->mode != MBEDTLS_MODE_GCM && cipher_mode = cipher_info->mode;
((filesize - mbedtls_md_get_size(md_info)) % if (cipher_mode != MBEDTLS_MODE_GCM &&
mbedtls_cipher_get_block_size(&cipher_ctx)) != 0) { 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", 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; goto exit;
} }
/* /*
* Subtract the IV + HMAC length. * 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. * Read the IV and original filesize modulo 16.
@ -481,13 +490,13 @@ int main(int argc, char *argv[])
/* /*
* Decrypt and write the plaintext. * Decrypt and write the plaintext.
*/ */
for (offset = 0; offset < filesize; offset += mbedtls_cipher_get_block_size(&cipher_ctx)) { for (offset = 0; offset < filesize; offset += cipher_block_size) {
ilen = ((unsigned int) filesize - offset > mbedtls_cipher_get_block_size(&cipher_ctx)) ? ilen = ((unsigned int) filesize - offset > cipher_block_size) ?
mbedtls_cipher_get_block_size(&cipher_ctx) : (unsigned int) (filesize - offset); cipher_block_size : (unsigned int) (filesize - offset);
if (fread(buffer, 1, ilen, fin) != ilen) { if (fread(buffer, 1, ilen, fin) != ilen) {
mbedtls_fprintf(stderr, "fread(%u bytes) failed\n", mbedtls_fprintf(stderr, "fread(%u bytes) failed\n",
mbedtls_cipher_get_block_size(&cipher_ctx)); cipher_block_size);
goto exit; goto exit;
} }
@ -515,14 +524,14 @@ int main(int argc, char *argv[])
goto exit; goto exit;
} }
if (fread(buffer, 1, mbedtls_md_get_size(md_info), fin) != mbedtls_md_get_size(md_info)) { if (fread(buffer, 1, md_size, fin) != md_size) {
mbedtls_fprintf(stderr, "fread(%d bytes) failed\n", mbedtls_md_get_size(md_info)); mbedtls_fprintf(stderr, "fread(%d bytes) failed\n", md_size);
goto exit; goto exit;
} }
/* Use constant-time buffer comparison */ /* Use constant-time buffer comparison */
diff = 0; 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]; diff |= digest[i] ^ buffer[i];
} }