From 9505164ef4d70806b836cbb889c9cc190fd35ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Jun 2015 10:39:46 +0200 Subject: [PATCH] Create cert profile API (unimplemented yet) --- include/mbedtls/x509.h | 7 ++++ include/mbedtls/x509_crt.h | 48 ++++++++++++++++++++++ library/x509_crt.c | 55 +++++++++++++++++++++----- tests/suites/test_suite_x509parse.data | 2 +- 4 files changed, 101 insertions(+), 11 deletions(-) diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h index 7cb0d468c..597053c7d 100644 --- a/include/mbedtls/x509.h +++ b/include/mbedtls/x509.h @@ -97,6 +97,13 @@ #define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ #define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ #define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + /* \} name */ /* \} addtogroup x509_module */ diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 8aabfdeff..7acee5779 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -94,6 +94,20 @@ typedef struct mbedtls_x509_crt } mbedtls_x509_crt; +/* + * Security profile for certificate verification + * + * All lists are terminated by the respective _NONE value. + */ +typedef struct +{ + const mbedtls_md_type_t *allowed_mds; /**< MDs for signatures */ + const mbedtls_pk_type_t *allowed_pks; /**< PK algs for signatures */ + size_t rsa_min_bitlen; /**< Minimum size for RSA keys */ + const mbedtls_ecp_group *allowed_curves;/**< Elliptic curves for ECDSA */ +} +mbedtls_x509_crt_profile; + #define MBEDTLS_X509_CRT_VERSION_1 0 #define MBEDTLS_X509_CRT_VERSION_2 1 #define MBEDTLS_X509_CRT_VERSION_3 2 @@ -232,6 +246,9 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, * \note In case verification failed, the results can be displayed * using \c mbedtls_x509_crt_verify_info() * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * * \param crt a certificate to be verified * \param trust_ca the trusted CA chain * \param ca_crl the CRL chain for trusted CA's @@ -255,6 +272,37 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ); +/** + * \brief Verify the certificate signature according to profile + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \param crt a certificate to be verified + * \param trust_ca the trusted CA chain + * \param ca_crl the CRL chain for trusted CA's + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED + * in which case *flags will have one or more + * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags + * set, + * or another error in case of a fatal error encountered + * during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) /** * \brief Check usage of certificate against keyUsage extension. diff --git a/library/x509_crt.c b/library/x509_crt.c index a26715a6b..e3d7cc739 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1401,6 +1401,12 @@ static const struct x509_crt_verify_string x509_crt_verify_strings[] = { { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, { 0, NULL } }; @@ -1502,7 +1508,8 @@ int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509 * Check that the given certificate is valid according to the CRL. */ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, - mbedtls_x509_crl *crl_list) + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) { int flags = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; @@ -1554,6 +1561,8 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); + (void) profile; /* WIP:TODO: check profile */ + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), crl_list->sig.p, crl_list->sig.len ) != 0 ) @@ -1764,7 +1773,9 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, static int x509_crt_verify_top( mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, int path_cnt, uint32_t *flags, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + int path_cnt, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { @@ -1796,6 +1807,8 @@ static int x509_crt_verify_top( else mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); + (void) profile; /* WIP:TODO: check profile */ + for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) { if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) @@ -1846,7 +1859,7 @@ static int x509_crt_verify_top( { #if defined(MBEDTLS_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the chain's top crt */ - *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl ); + *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); #else ((void) ca_crl); #endif @@ -1880,8 +1893,10 @@ static int x509_crt_verify_top( } static int x509_crt_verify_child( - mbedtls_x509_crt *child, mbedtls_x509_crt *parent, mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, int path_cnt, uint32_t *flags, + mbedtls_x509_crt *child, mbedtls_x509_crt *parent, + mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + int path_cnt, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { @@ -1891,6 +1906,8 @@ static int x509_crt_verify_child( mbedtls_x509_crt *grandparent; const mbedtls_md_info_t *md_info; + (void) profile; /* WIP */ + /* path_cnt is 0 for the first intermediate CA */ if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) { @@ -1914,6 +1931,8 @@ static int x509_crt_verify_child( } else { + (void) profile; /* WIP:TODO: check profile */ + mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, @@ -1926,7 +1945,7 @@ static int x509_crt_verify_child( #if defined(MBEDTLS_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the given crt */ - *flags |= x509_crt_verifycrl(child, parent, ca_crl); + *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile ); #endif /* Look for a grandparent upwards the chain */ @@ -1942,14 +1961,14 @@ static int x509_crt_verify_child( /* Is our parent part of the chain or at the top? */ if( grandparent != NULL ) { - ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, + ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, profile, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { - ret = x509_crt_verify_top( parent, trust_ca, ca_crl, + ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); @@ -1974,6 +1993,22 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, + NULL /* WIP */, cn, flags, f_vrfy, p_vrfy ) ); +} + + +/* + * Verify the certificate validity, with profile + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) { size_t cn_len; int ret; @@ -2044,14 +2079,14 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, /* Are we part of the chain or at the top? */ if( parent != NULL ) { - ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, + ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, pathlen, flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { - ret = x509_crt_verify_top( crt, trust_ca, ca_crl, + ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, pathlen, flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index e3bc13001..932712a6f 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -272,7 +272,7 @@ X509 Verify Information: two issues x509_verify_info:MBEDTLS_X509_BADCERT_EXPIRED | MBEDTLS_X509_BADCRL_EXPIRED:"":"The certificate validity has expired\nThe CRL is expired\n" X509 Verify Information: two issues, one unknown -x509_verify_info:MBEDTLS_X509_BADCERT_OTHER | 0x8000:"":"Other reason (can be used by verify callback)\nUnknown reason (this should not happen)\n" +x509_verify_info:MBEDTLS_X509_BADCERT_OTHER | 0x80000000:"":"Other reason (can be used by verify callback)\nUnknown reason (this should not happen)\n" X509 Verify Information: empty, with prefix x509_verify_info:0:" ! ":""