From 4cc6522a85473e6ae49e1558988cde408739305e Mon Sep 17 00:00:00 2001 From: Valerio Setti Date: Fri, 16 Feb 2024 14:40:42 +0100 Subject: [PATCH] pem: do not parse ASN1 data after decryption (removes ASN1 dependency) Now that we have padding verification after decryption and since this can be used to validate the password as well there is no need to parse ASN1 content any more, so we can simplify/remove that dependency. Signed-off-by: Valerio Setti --- ChangeLog.d/8799.txt | 3 +-- include/mbedtls/asn1.h | 5 ++--- library/asn1parse.c | 5 ++--- library/pem.c | 23 ----------------------- tests/suites/test_suite_pem.data | 13 +++---------- tests/suites/test_suite_pem.function | 1 - 6 files changed, 8 insertions(+), 42 deletions(-) diff --git a/ChangeLog.d/8799.txt b/ChangeLog.d/8799.txt index b44bb99919..50e7c118c8 100644 --- a/ChangeLog.d/8799.txt +++ b/ChangeLog.d/8799.txt @@ -1,4 +1,3 @@ Bugfix * mbedtls_pem_read_buffer() now performs a check on the padding data of - decrypted keys and it rejects invalid ones. It also parses and validates - the main ASN.1 SEQUENCE header. + decrypted keys and it rejects invalid ones. diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h index d8ee469308..ff019f432a 100644 --- a/include/mbedtls/asn1.h +++ b/include/mbedtls/asn1.h @@ -198,7 +198,7 @@ typedef struct mbedtls_asn1_named_data { mbedtls_asn1_named_data; #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \ - defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) || defined(MBEDTLS_PEM_PARSE_C) + defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Get the length of an ASN.1 element. * Updates the pointer to immediately behind the length. @@ -245,8 +245,7 @@ int mbedtls_asn1_get_len(unsigned char **p, int mbedtls_asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag); -#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || - MBEDTLS_PSA_UTIL_HAVE_ECDSA || MBEDTLS_PEM_PARSE_C */ +#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ #if defined(MBEDTLS_ASN1_PARSE_C) /** diff --git a/library/asn1parse.c b/library/asn1parse.c index 644b43ba96..e33fdf71da 100644 --- a/library/asn1parse.c +++ b/library/asn1parse.c @@ -8,7 +8,7 @@ #include "common.h" #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \ - defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) || defined(MBEDTLS_PEM_PARSE_C) + defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) #include "mbedtls/asn1.h" #include "mbedtls/platform_util.h" @@ -74,8 +74,7 @@ int mbedtls_asn1_get_tag(unsigned char **p, return mbedtls_asn1_get_len(p, end, len); } -#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || - MBEDTLS_PSA_UTIL_HAVE_ECDSA || MBEDTLS_PEM_PARSE_C */ +#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ #if defined(MBEDTLS_ASN1_PARSE_C) int mbedtls_asn1_get_bool(unsigned char **p, diff --git a/library/pem.c b/library/pem.c index 3f01d3bdd3..48180eed48 100644 --- a/library/pem.c +++ b/library/pem.c @@ -17,7 +17,6 @@ #include "mbedtls/cipher.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" -#include "mbedtls/asn1.h" #include @@ -466,28 +465,6 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const mbedtls_zeroize_and_free(buf, len); return ret; } - - /* - * In RFC1421 PEM is used as container for DER (ASN.1) content so we - * can use ASN.1 functions to parse the main SEQUENCE tag and to get its - * length. - */ - unsigned char *p = buf; - size_t sequence_len; - ret = mbedtls_asn1_get_tag(&p, buf + len, &sequence_len, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED); - if (ret != 0) { - mbedtls_free(buf); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); - } - /* Add also the sequence block (tag + len) to the total amount of valid data. */ - sequence_len += (p - buf); - - /* Ensure that the reported SEQUENCE length matches the data len (i.e. no - * trailing garbage data). */ - if (len != sequence_len) { - return MBEDTLS_ERR_PEM_BAD_INPUT_DATA; - } #else mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; diff --git a/tests/suites/test_suite_pem.data b/tests/suites/test_suite_pem.data index e3bb7e4da1..6f8af6c31d 100644 --- a/tests/suites/test_suite_pem.data +++ b/tests/suites/test_suite_pem.data @@ -61,21 +61,14 @@ PEM read (valid EC key encoded with AES-128-CBC) depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: AES-128-CBC,151F851B6A7F3FBDAA5B7173117D0127\n\nLw+0OM+0Bwcl+ls/vxQbLrVshGc7bsNPvvtj2sJeMFFEq3V1mj/IO++0KK/CDhMH\nh6CZPsmgVOeM5uFpqYaq0fJbUduN2eDMWszWRm0SFkY=\n-----END EC PRIVATE KEY-----":"pwdpwd":0:"3041020101040f00d8023c809afd45e426d1a4dbe0ffa00706052b81040004a1220320000400da1ecfa53d528237625e119e2e0500d2eb671724f16deb6a63749516b7" -# The text "hello world" (which is clearly not a valid ASN.1 SEQUENCE) is encoded -# with AES-128-CBC to prove that ASN.1 parsing after decoding fails. +# The text "hello world" together with some invalid padding data is encoded +# with AES-128-CBC in order to test padding validation. # Since PBKDF1 isn't supported in OpenSSL, here's the steps: # 1. generate the key (password="password"; IV=0x3132333435363738 in hex or "12345678" as string) # echo -n "password12345678" | openssl md5 # 2. encode data -# echo -n "hello world" | openssl aes-128-cbc -e -base64 -p -K "bbb0ddff1b944b3cc68eaaeb7ac20099" -iv "3132333435363738" -PEM read (Invalid SEQUENCE encoded with AES-128-CBC) -depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC -mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: AES-128-CBC,31323334353637380000000000000000\n\nDfRGkwS+VjvR0IYsjZwW6Q==\n-----END EC PRIVATE KEY-----":"password":MBEDTLS_ERR_PEM_INVALID_DATA + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG:"" - -# Same as above, but with invalid padding data. -# Generated with: # echo -n -e "\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x01\x02\x03\x04\x05" | openssl aes-128-cbc -e -base64 -p -K "bbb0ddff1b944b3cc68eaaeb7ac20099" -iv "3132333435363738" -nopad -PEM read (Invalid padding data for AES-128-CBC) +PEM read (AES-128-CBC, invalid padding data) depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: AES-128-CBC,31323334353637380000000000000000\n\n333hxynfxEdXrSHQfIabxQ==\n-----END EC PRIVATE KEY-----":"password":MBEDTLS_ERR_PEM_BAD_INPUT_DATA:"" diff --git a/tests/suites/test_suite_pem.function b/tests/suites/test_suite_pem.function index 2acc16e9f3..413dc551c3 100644 --- a/tests/suites/test_suite_pem.function +++ b/tests/suites/test_suite_pem.function @@ -3,7 +3,6 @@ #include "mbedtls/pem.h" #include "mbedtls/des.h" #include "mbedtls/aes.h" -#include "mbedtls/asn1.h" /* END_HEADER */ /* BEGIN_CASE depends_on:MBEDTLS_PEM_WRITE_C */