diff --git a/ChangeLog.d/pkcs7-reject-weak-hashes.txt b/ChangeLog.d/pkcs7-reject-weak-hashes.txt new file mode 100644 index 0000000000..ce3f295db1 --- /dev/null +++ b/ChangeLog.d/pkcs7-reject-weak-hashes.txt @@ -0,0 +1,9 @@ +Security + * PKCS7 now rejects weak hash algorithms (RIPEMD160, MD5, SHA-1, SHA-224, + SHA3-224) on signature verification. The new configuration option + MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES allows to keep using weak hash + algorithms in PKCS7 for backward compatibility purposes. + +Features + * SHA3-256, SHA3-384 and SHA3-512 are now accepted in the default X.509 + certificate profile. diff --git a/framework b/framework index e0f6275eff..d6dec17adf 160000 --- a/framework +++ b/framework @@ -1 +1 @@ -Subproject commit e0f6275eff2e45e295fdd6b6877de4cbdaddae83 +Subproject commit d6dec17adfb5bf283c6a7a5bb6c451ecdc0b8201 diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 8fa445a132..f684347519 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3248,6 +3248,15 @@ */ #define MBEDTLS_PKCS7_C +/** + * \def MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES + * + * Allow weak signature algorithms (RIPEMD160, MD5, SHA-1) in PKCS#7. + * + * Requires: MBEDTLS_PKCS7_C + */ +// #define MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES + /** * \def MBEDTLS_PKCS12_C * diff --git a/include/mbedtls/pkcs7.h b/include/mbedtls/pkcs7.h index e9b482208e..5e58580412 100644 --- a/include/mbedtls/pkcs7.h +++ b/include/mbedtls/pkcs7.h @@ -31,6 +31,12 @@ * assumed these fields are empty. * - The RFC allows for the signed Data type to contain contentInfo. This * implementation assumes the type is DATA and the content is empty. + * - The RFC doesn't put any constrain on the hash algorithm to be used, but + * this implementation by default rejects weak hash algorithms (i.e. RIPEMD160, + * MD5, SHA-1, SHA-224, SHA3-224). In general accepted hash algorithms + * are the ones belonging to ::mbedtls_x509_crt_profile_default. + * #MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES can be enabled to accept all + * supported hash algorithms. */ #ifndef MBEDTLS_PKCS7_H @@ -190,6 +196,9 @@ int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, * \note This function internally calculates the hash on the supplied * plain data for signature verification. * + * \note For limitation on the supported hash algorithms, please refer + * to the note at the top of this document. + * * \return 0 if the signature verifies, or a negative error code on failure. */ int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, @@ -219,6 +228,9 @@ int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, * \note This function is different from mbedtls_pkcs7_signed_data_verify() * in that it is directly passed the hash of the data. * + * \note For limitation on the supported hash algorithms, please refer + * to the note at the top of this document. + * * \return 0 if the signature verifies, or a negative error code on failure. */ int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, diff --git a/library/pkcs7.c b/library/pkcs7.c index 117e9798f4..49ca7e9ec1 100644 --- a/library/pkcs7.c +++ b/library/pkcs7.c @@ -666,6 +666,20 @@ static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7, return ret; } +#if !defined(MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES) + /* Ensure the MD alg from the PKCS#7 context and signature algorithm from + * the certificate belong to the list of secure algorithms + * (i.e. mbedtls_x509_crt_profile_default). */ + ret = mbedtls_x509_profile_check_md_alg(&mbedtls_x509_crt_profile_default, md_alg); + if (ret != 0) { + return MBEDTLS_ERR_PKCS7_INVALID_ALG; + } + ret = mbedtls_x509_profile_check_pk_alg(&mbedtls_x509_crt_profile_default, cert->sig_pk); + if (ret != 0) { + return MBEDTLS_ERR_PKCS7_INVALID_ALG; + } +#endif /* MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES */ + md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; diff --git a/library/x509_crt.c b/library/x509_crt.c index 15d7d2e686..f9e36470cb 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -88,11 +88,13 @@ typedef struct { * concerns. */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = { - /* Hashes from SHA-256 and above. Note that this selection - * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ + /* Hashes from SHA-256 and above. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA3_256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA3_384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA3_512), 0xFFFFFFF, /* Any PK alg */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Curves at or above 128-bit security level. Note that this selection @@ -166,12 +168,8 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = (uint32_t) -1, }; -/* - * Check md_alg against profile - * Return 0 if md_alg is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, - mbedtls_md_type_t md_alg) +int mbedtls_x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg) { if (md_alg == MBEDTLS_MD_NONE) { return -1; @@ -184,12 +182,8 @@ static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, return -1; } -/* - * Check pk_alg against profile - * Return 0 if pk_alg is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg) +int mbedtls_x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg) { if (pk_alg == MBEDTLS_PK_NONE) { return -1; @@ -2055,11 +2049,11 @@ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, /* * Check if CRL is correctly signed by the trusted CA */ - if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) { + if (mbedtls_x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) { flags |= MBEDTLS_X509_BADCRL_BAD_MD; } - if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) { + if (mbedtls_x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) { flags |= MBEDTLS_X509_BADCRL_BAD_PK; } @@ -2590,11 +2584,11 @@ static int x509_crt_verify_chain( } /* Check signature algorithm: MD & PK algs */ - if (x509_profile_check_md_alg(profile, child->sig_md) != 0) { + if (mbedtls_x509_profile_check_md_alg(profile, child->sig_md) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_MD; } - if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) { + if (mbedtls_x509_profile_check_pk_alg(profile, child->sig_pk) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_PK; } @@ -3102,7 +3096,7 @@ static int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt, /* Check the type and size of the key */ pk_type = mbedtls_pk_get_type(&crt->pk); - if (x509_profile_check_pk_alg(profile, pk_type) != 0) { + if (mbedtls_x509_profile_check_pk_alg(profile, pk_type) != 0) { ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; } diff --git a/library/x509_internal.h b/library/x509_internal.h index 8a2d2ed007..0ebd3dc038 100644 --- a/library/x509_internal.h +++ b/library/x509_internal.h @@ -14,6 +14,7 @@ #include "mbedtls/build_info.h" #include "mbedtls/x509.h" +#include "mbedtls/x509_crt.h" #include "mbedtls/asn1.h" #include "pk_internal.h" @@ -83,4 +84,18 @@ int mbedtls_x509_info_key_usage(char **buf, size_t *size, int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, const mbedtls_x509_san_list *san_list); +/* + * Check md_alg against profile + * Return 0 if md_alg is acceptable for this profile, -1 otherwise + */ +int mbedtls_x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg); + +/* + * Check pk_alg against profile + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise + */ +int mbedtls_x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg); + #endif /* MBEDTLS_X509_INTERNAL_H */ diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data index f76f307db5..0932e7d576 100644 --- a/tests/suites/test_suite_pkcs7.data +++ b/tests/suites/test_suite_pkcs7.data @@ -94,10 +94,30 @@ PKCS7 Signed Data Verification Pass SHA256 #9.1 depends_on:MBEDTLS_MD_CAN_SHA256 pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha256.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":MBEDTLS_MD_SHA256:0 +PKCS7 Signed Data Verification Fail SHA1 #10 +depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_MD_CAN_SHA256:!MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha1.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG + PKCS7 Signed Data Verification Pass SHA1 #10 -depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_MD_CAN_SHA256 +depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha1.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:0 +PKCS7 Signed Data Verification Fail MD5 #10.1 +depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_MD_CAN_SHA256:!MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_md5.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG + +PKCS7 Signed Data Verification Pass MD5 #10.1 +depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_md5.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:0 + +PKCS7 Signed Data Verification Fail RIPEMD160 #10.2 +depends_on:MBEDTLS_MD_CAN_RIPEMD160:MBEDTLS_MD_CAN_SHA256:!MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_ripemd160.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:MBEDTLS_ERR_PKCS7_INVALID_ALG + +PKCS7 Signed Data Verification Pass RIPEMD160 #10.2 +depends_on:MBEDTLS_MD_CAN_RIPEMD160:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PKCS7_ALLOW_WEAK_SIGNATURES +pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_ripemd160.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:0 + PKCS7 Signed Data Verification Pass SHA512 #11 depends_on:MBEDTLS_MD_CAN_SHA512:MBEDTLS_MD_CAN_SHA256 pkcs7_verify:"../framework/data_files/pkcs7_data_cert_signed_sha512.der":"../framework/data_files/pkcs7-rsa-sha256-1.der":"../framework/data_files/pkcs7_data.bin":0:0