diff --git a/ChangeLog b/ChangeLog index 74b1d3632..dc27e50c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -72,6 +72,7 @@ Changes Security Features + * Add mbedtls_x509_crt_verify_info() to display certificate verification results. * Add support for reading DH parameters with privateValueLength included (contributed by Daniel Kahn Gillmor). * Add support for bit strings in X.509 names (request by Fredrik Axelsson). diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h index bd9862832..bdb5749b7 100644 --- a/include/mbedtls/x509.h +++ b/include/mbedtls/x509.h @@ -82,17 +82,21 @@ * \name X509 Verify codes * \{ */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ #define MBEDTLS_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ #define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ #define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ #define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ -#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< CRL is not correctly signed by the trusted CA. */ -#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< CRL is expired. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ #define MBEDTLS_BADCERT_MISSING 0x40 /**< Certificate was missing. */ #define MBEDTLS_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ #define MBEDTLS_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ #define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ #define MBEDTLS_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ /* \} name */ /* \} addtogroup x509_module */ diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 23d7fb91b..880099b53 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -201,6 +201,21 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, const mbedtls_x509_crt *crt ); +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + int flags ); + /** * \brief Verify the certificate signature * @@ -218,6 +233,9 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, * are also returned to the application. The function should * return 0 for anything but a fatal error. * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * * \param crt a certificate to be verified * \param trust_ca the trusted CA chain * \param ca_crl the CRL chain for trusted CA's @@ -228,12 +246,9 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, * \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 of - * the following values set: - * MBEDTLS_BADCERT_EXPIRED -- - * MBEDTLS_X509_BADCERT_REVOKED -- - * MBEDTLS_X509_BADCERT_CN_MISMATCH -- - * MBEDTLS_X509_BADCERT_NOT_TRUSTED + * 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. */ diff --git a/library/x509_crt.c b/library/x509_crt.c index bc360dc8f..7a94dd0d2 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1380,6 +1380,57 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, return( (int) ( size - n ) ); } +struct x509_crt_verify_string { + int code; + const char *string; +}; + +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + { MBEDTLS_BADCERT_EXPIRED, "The certificate validity has expired" }, + { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, + { MBEDTLS_BADCERT_MISSING, "Certificate was missing" }, + { MBEDTLS_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { MBEDTLS_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, + { MBEDTLS_BADCRL_FUTURE, "The CRL is from the future" }, + { MBEDTLS_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { MBEDTLS_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { MBEDTLS_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { 0, NULL } +}; + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + int flags ) +{ + int ret; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + SAFE_SNPRINTF(); + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + SAFE_SNPRINTF(); + } + + return( (int) ( size - n ) ); +} + #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, unsigned int usage ) { diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index dd1c2bb18..09c4e4263 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -262,6 +262,27 @@ X509 CSR Information RSA-PSS with SHA512 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_SHA512_C mbedtls_x509_csr_info:"data_files/server9.req.sha512":"CSR version \: 1\nsubject name \: C=NL, O=PolarSSL, CN=localhost\nsigned using \: RSASSA-PSS (SHA512, MGF1-SHA512, 0x3E)\nRSA key size \: 1024 bits\n" +X509 Verify Information: empty +x509_verify_info:0:"":"" + +X509 Verify Information: one issue +x509_verify_info:MBEDTLS_BADCERT_MISSING:"":"Certificate was missing\n" + +X509 Verify Information: two issues +x509_verify_info:MBEDTLS_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_BADCERT_OTHER | 0x8000:"":"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:" ! ":"" + +X509 Verify Information: one issue, with prefix +x509_verify_info:MBEDTLS_BADCERT_MISSING:" ! ":" ! Certificate was missing\n" + +X509 Verify Information: two issues, with prefix +x509_verify_info:MBEDTLS_BADCERT_EXPIRED | MBEDTLS_X509_BADCRL_EXPIRED:" ! ":" ! The certificate validity has expired\n ! The CRL is expired\n" + X509 Get Distinguished Name #1 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C mbedtls_x509_dn_gets:"data_files/server1.crt":"subject":"C=NL, O=PolarSSL, CN=PolarSSL Server 1" diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index cead70790..27912c313 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -102,6 +102,22 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */ +void x509_verify_info( int flags, char *prefix, char *result_str ) +{ + char buf[2000]; + int res; + + memset( buf, 0, sizeof( buf ) ); + + res = mbedtls_x509_crt_verify_info( buf, sizeof( buf ), prefix, flags ); + + TEST_ASSERT( res >= 0 ); + + TEST_ASSERT( strcmp( buf, result_str ) == 0 ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_X509_CRL_PARSE_C */ void x509_verify( char *crt_file, char *ca_file, char *crl_file, char *cn_name_str, int result, int flags_result,