From 39a183a629696d860f2342dd3e5094231e5e06ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 17 Apr 2015 16:14:32 +0200 Subject: [PATCH 1/3] Add x509_crt_verify_info() --- ChangeLog | 1 + include/polarssl/x509.h | 8 +++- include/polarssl/x509_crt.h | 26 ++++++++--- library/x509_crt.c | 51 ++++++++++++++++++++++ tests/suites/test_suite_x509parse.data | 21 +++++++++ tests/suites/test_suite_x509parse.function | 16 +++++++ 6 files changed, 115 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index ceb398596..8d7a8108e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ mbed TLS ChangeLog (Sorted per branch, date) Security Features + * Add 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/polarssl/x509.h b/include/polarssl/x509.h index 0dece0634..cd01539b9 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -82,17 +82,21 @@ * \name X509 Verify codes * \{ */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ #define BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ #define BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ #define BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ #define BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ -#define BADCRL_NOT_TRUSTED 0x10 /**< CRL is not correctly signed by the trusted CA. */ -#define BADCRL_EXPIRED 0x20 /**< CRL is expired. */ +#define BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ #define BADCERT_MISSING 0x40 /**< Certificate was missing. */ #define BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ #define BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ #define BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ #define BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ /* \} name */ /* \} addtogroup x509_module */ diff --git a/include/polarssl/x509_crt.h b/include/polarssl/x509_crt.h index fe270078f..24f7c7ab6 100644 --- a/include/polarssl/x509_crt.h +++ b/include/polarssl/x509_crt.h @@ -202,6 +202,21 @@ int x509_crt_parse_path( x509_crt *chain, const char *path ); int x509_crt_info( char *buf, size_t size, const char *prefix, const 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 x509_crt_verify() + * + * \return The amount of data written to the buffer, or -1 in + * case of an error. + */ +int x509_crt_verify_info( char *buf, size_t size, const char *prefix, + int flags ); + /** * \brief Verify the certificate signature * @@ -219,6 +234,9 @@ int 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 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 @@ -229,12 +247,8 @@ int x509_crt_info( char *buf, size_t size, const char *prefix, * \param p_vrfy verification parameter * * \return 0 if successful or POLARSSL_ERR_X509_SIG_VERIFY_FAILED, - * in which case *flags will have one or more of - * the following values set: - * BADCERT_EXPIRED -- - * BADCERT_REVOKED -- - * BADCERT_CN_MISMATCH -- - * BADCERT_NOT_TRUSTED + * in which case *flags will have one or more BADCERT_XXX or + * 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 77008ed23..4e4d806a9 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1382,6 +1382,57 @@ int 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[] = { + { BADCERT_EXPIRED, "The certificate validity has expired" }, + { BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { BADCRL_EXPIRED, "The CRL is expired" }, + { BADCERT_MISSING, "Certificate was missing" }, + { BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { BADCERT_FUTURE, "The certificate validity starts in the future" }, + { BADCRL_FUTURE, "The CRL is from the future" }, + { BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { 0, NULL } +}; + +int 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 = polarssl_snprintf( p, n, "%s%s\n", prefix, cur->string ); + SAFE_SNPRINTF(); + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = polarssl_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + SAFE_SNPRINTF(); + } + + return( (int) ( size - n ) ); +} + #if defined(POLARSSL_X509_CHECK_KEY_USAGE) int x509_crt_check_key_usage( const x509_crt *crt, int usage ) { diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 491f14ed6..47eef4113 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:POLARSSL_PEM_PARSE_C:POLARSSL_X509_RSASSA_PSS_SUPPORT:POLARSSL_SHA512_C 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:BADCERT_MISSING:"":"Certificate was missing\n" + +X509 Verify Information: two issues +x509_verify_info:BADCERT_EXPIRED | BADCRL_EXPIRED:"":"The certificate validity has expired\nThe CRL is expired\n" + +X509 Verify Information: two issues, one unknown +x509_verify_info: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:BADCERT_MISSING:" ! ":" ! Certificate was missing\n" + +X509 Verify Information: two issues, with prefix +x509_verify_info:BADCERT_EXPIRED | BADCRL_EXPIRED:" ! ":" ! The certificate validity has expired\n ! The CRL is expired\n" + X509 Get Distinguished Name #1 depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C 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 69594846c..ab397e59b 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:POLARSSL_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 = 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:POLARSSL_FS_IO:POLARSSL_X509_CRT_PARSE_C:POLARSSL_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, From 0c6ce2f536941413278f981f0aea169272af914c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 17 Apr 2015 16:32:21 +0200 Subject: [PATCH 2/3] Use x509_crt_verify_info() in programs --- programs/ssl/ssl_client1.c | 18 ++++----------- programs/ssl/ssl_client2.c | 42 ++++++++-------------------------- programs/ssl/ssl_mail_client.c | 24 +++++++------------ programs/ssl/ssl_server2.c | 16 ++++--------- programs/test/ssl_cert_test.c | 21 +++++++---------- programs/x509/cert_app.c | 42 ++++++++-------------------------- tests/ssl-opt.sh | 18 +++++++-------- 7 files changed, 52 insertions(+), 129 deletions(-) diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c index 57104caf6..057b84257 100644 --- a/programs/ssl/ssl_client1.c +++ b/programs/ssl/ssl_client1.c @@ -203,24 +203,16 @@ int main( void ) */ polarssl_printf( " . Verifying peer X.509 certificate..." ); - /* In real life, we may want to bail out when ret != 0 */ + /* In real life, we probably want to bail out when ret != 0 */ if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 ) { + char vrfy_buf[512]; + polarssl_printf( " failed\n" ); - if( ( ret & BADCERT_EXPIRED ) != 0 ) - polarssl_printf( " ! server certificate has expired\n" ); + x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret ); - if( ( ret & BADCERT_REVOKED ) != 0 ) - polarssl_printf( " ! server certificate has been revoked\n" ); - - if( ( ret & BADCERT_CN_MISMATCH ) != 0 ) - polarssl_printf( " ! CN mismatch (expected CN=%s)\n", "PolarSSL Server 1" ); - - if( ( ret & BADCERT_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! self-signed or not signed by a trusted CA\n" ); - - polarssl_printf( "\n" ); + polarssl_printf( "%s\n", vrfy_buf ); } else polarssl_printf( " ok\n" ); diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index da3dba738..cdadf59a4 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -350,29 +350,13 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags ) x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); polarssl_printf( "%s", buf ); - if( ( (*flags) & BADCERT_EXPIRED ) != 0 ) - polarssl_printf( " ! server certificate has expired\n" ); - - if( ( (*flags) & BADCERT_REVOKED ) != 0 ) - polarssl_printf( " ! server certificate has been revoked\n" ); - - if( ( (*flags) & BADCERT_CN_MISMATCH ) != 0 ) - polarssl_printf( " ! CN mismatch\n" ); - - if( ( (*flags) & BADCERT_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! self-signed or not signed by a trusted CA\n" ); - - if( ( (*flags) & BADCRL_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! CRL not trusted\n" ); - - if( ( (*flags) & BADCRL_EXPIRED ) != 0 ) - polarssl_printf( " ! CRL expired\n" ); - - if( ( (*flags) & BADCERT_OTHER ) != 0 ) - polarssl_printf( " ! other (unknown) flag\n" ); - if ( ( *flags ) == 0 ) polarssl_printf( " This certificate has no flags\n" ); + else + { + x509_crt_verify_info( buf, sizeof( buf ), " ! ", *flags ); + polarssl_printf( "%s\n", buf ); + } return( 0 ); } @@ -1142,21 +1126,13 @@ int main( int argc, char *argv[] ) if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 ) { + char vrfy_buf[512]; + polarssl_printf( " failed\n" ); - if( ( ret & BADCERT_EXPIRED ) != 0 ) - polarssl_printf( " ! server certificate has expired\n" ); + x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret ); - if( ( ret & BADCERT_REVOKED ) != 0 ) - polarssl_printf( " ! server certificate has been revoked\n" ); - - if( ( ret & BADCERT_CN_MISMATCH ) != 0 ) - polarssl_printf( " ! CN mismatch (expected CN=%s)\n", opt.server_name ); - - if( ( ret & BADCERT_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! self-signed or not signed by a trusted CA\n" ); - - polarssl_printf( "\n" ); + polarssl_printf( "%s\n", vrfy_buf ); } else polarssl_printf( " ok\n" ); diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c index 2b2d493d1..fcda1dde3 100644 --- a/programs/ssl/ssl_mail_client.c +++ b/programs/ssl/ssl_mail_client.c @@ -169,7 +169,7 @@ static void my_debug( void *ctx, int level, const char *str ) } } -static int do_handshake( ssl_context *ssl, struct options *opt ) +static int do_handshake( ssl_context *ssl ) { int ret; unsigned char buf[1024]; @@ -201,24 +201,16 @@ static int do_handshake( ssl_context *ssl, struct options *opt ) */ polarssl_printf( " . Verifying peer X.509 certificate..." ); - /* In real life, we may want to bail out when ret != 0 */ + /* In real life, we probably want to bail out when ret != 0 */ if( ( ret = ssl_get_verify_result( ssl ) ) != 0 ) { + char vrfy_buf[512]; + polarssl_printf( " failed\n" ); - if( ( ret & BADCERT_EXPIRED ) != 0 ) - polarssl_printf( " ! server certificate has expired\n" ); + x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret ); - if( ( ret & BADCERT_REVOKED ) != 0 ) - polarssl_printf( " ! server certificate has been revoked\n" ); - - if( ( ret & BADCERT_CN_MISMATCH ) != 0 ) - polarssl_printf( " ! CN mismatch (expected CN=%s)\n", opt->server_name ); - - if( ( ret & BADCERT_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! self-signed or not signed by a trusted CA\n" ); - - polarssl_printf( "\n" ); + polarssl_printf( "%s\n", vrfy_buf ); } else polarssl_printf( " ok\n" ); @@ -638,7 +630,7 @@ int main( int argc, char *argv[] ) if( opt.mode == MODE_SSL_TLS ) { - if( do_handshake( &ssl, &opt ) != 0 ) + if( do_handshake( &ssl ) != 0 ) goto exit; polarssl_printf( " > Get header from server:" ); @@ -707,7 +699,7 @@ int main( int argc, char *argv[] ) polarssl_printf(" ok\n" ); - if( do_handshake( &ssl, &opt ) != 0 ) + if( do_handshake( &ssl ) != 0 ) goto exit; } diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index d1bc36ed1..095fabd49 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -1626,21 +1626,13 @@ reset: if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 ) { + char vrfy_buf[512]; + polarssl_printf( " failed\n" ); - if( !ssl_get_peer_cert( &ssl ) ) - polarssl_printf( " ! no client certificate sent\n" ); + x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret ); - if( ( ret & BADCERT_EXPIRED ) != 0 ) - polarssl_printf( " ! client certificate has expired\n" ); - - if( ( ret & BADCERT_REVOKED ) != 0 ) - polarssl_printf( " ! client certificate has been revoked\n" ); - - if( ( ret & BADCERT_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! self-signed or not signed by a trusted CA\n" ); - - polarssl_printf( "\n" ); + polarssl_printf( "%s\n", vrfy_buf ); } else polarssl_printf( " ok\n" ); diff --git a/programs/test/ssl_cert_test.c b/programs/test/ssl_cert_test.c index d823964ee..a2127306f 100644 --- a/programs/test/ssl_cert_test.c +++ b/programs/test/ssl_cert_test.c @@ -173,19 +173,14 @@ int main( void ) { if( ret == POLARSSL_ERR_X509_CERT_VERIFY_FAILED ) { - if( flags & BADCERT_CN_MISMATCH ) - polarssl_printf( " CN_MISMATCH " ); - if( flags & BADCERT_EXPIRED ) - polarssl_printf( " EXPIRED " ); - if( flags & BADCERT_REVOKED ) - polarssl_printf( " REVOKED " ); - if( flags & BADCERT_NOT_TRUSTED ) - polarssl_printf( " NOT_TRUSTED " ); - if( flags & BADCRL_NOT_TRUSTED ) - polarssl_printf( " CRL_NOT_TRUSTED " ); - if( flags & BADCRL_EXPIRED ) - polarssl_printf( " CRL_EXPIRED " ); - } else { + char vrfy_buf[512]; + + polarssl_printf( " failed\n" ); + x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret ); + polarssl_printf( "%s\n", vrfy_buf ); + } + else + { polarssl_printf( " failed\n ! x509_crt_verify returned %d\n\n", ret ); goto exit; } diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c index 72f69ba93..3a6ae87e4 100644 --- a/programs/x509/cert_app.c +++ b/programs/x509/cert_app.c @@ -128,29 +128,13 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags ) x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); polarssl_printf( "%s", buf ); - if( ( (*flags) & BADCERT_EXPIRED ) != 0 ) - polarssl_printf( " ! server certificate has expired\n" ); - - if( ( (*flags) & BADCERT_REVOKED ) != 0 ) - polarssl_printf( " ! server certificate has been revoked\n" ); - - if( ( (*flags) & BADCERT_CN_MISMATCH ) != 0 ) - polarssl_printf( " ! CN mismatch\n" ); - - if( ( (*flags) & BADCERT_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! self-signed or not signed by a trusted CA\n" ); - - if( ( (*flags) & BADCRL_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! CRL not trusted\n" ); - - if( ( (*flags) & BADCRL_EXPIRED ) != 0 ) - polarssl_printf( " ! CRL expired\n" ); - - if( ( (*flags) & BADCERT_OTHER ) != 0 ) - polarssl_printf( " ! other (unknown) flag\n" ); - if ( ( *flags ) == 0 ) polarssl_printf( " This certificate has no flags\n" ); + else + { + x509_crt_verify_info( buf, sizeof( buf ), " ! ", *flags ); + polarssl_printf( "%s\n", buf ); + } return( 0 ); } @@ -358,21 +342,13 @@ int main( int argc, char *argv[] ) if( ( ret = x509_crt_verify( &crt, &cacert, &cacrl, NULL, &flags, my_verify, NULL ) ) != 0 ) { + char vrfy_buf[512]; + polarssl_printf( " failed\n" ); - if( ( ret & BADCERT_EXPIRED ) != 0 ) - polarssl_printf( " ! server certificate has expired\n" ); + x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", ret ); - if( ( ret & BADCERT_REVOKED ) != 0 ) - polarssl_printf( " ! server certificate has been revoked\n" ); - - if( ( ret & BADCERT_CN_MISMATCH ) != 0 ) - polarssl_printf( " ! CN mismatch (expected CN=%s)\n", opt.server_name ); - - if( ( ret & BADCERT_NOT_TRUSTED ) != 0 ) - polarssl_printf( " ! self-signed or not signed by a trusted CA\n" ); - - polarssl_printf( "\n" ); + polarssl_printf( "%s\n", vrfy_buf ); } else polarssl_printf( " ok\n" ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 63c0a2332..75c59423a 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1338,7 +1338,7 @@ run_test "Authentication: server badcert, client required" \ "$P_CLI debug_level=1 auth_mode=required" \ 1 \ -c "x509_verify_cert() returned" \ - -c "! self-signed or not signed by a trusted CA" \ + -c "! The certificate is not correctly signed by the trusted CA" \ -c "! ssl_handshake returned" \ -c "X509 - Certificate verification failed" @@ -1348,7 +1348,7 @@ run_test "Authentication: server badcert, client optional" \ "$P_CLI debug_level=1 auth_mode=optional" \ 0 \ -c "x509_verify_cert() returned" \ - -c "! self-signed or not signed by a trusted CA" \ + -c "! The certificate is not correctly signed by the trusted CA" \ -C "! ssl_handshake returned" \ -C "X509 - Certificate verification failed" @@ -1358,7 +1358,7 @@ run_test "Authentication: server badcert, client none" \ "$P_CLI debug_level=1 auth_mode=none" \ 0 \ -C "x509_verify_cert() returned" \ - -C "! self-signed or not signed by a trusted CA" \ + -C "! The certificate is not correctly signed by the trusted CA" \ -C "! ssl_handshake returned" \ -C "X509 - Certificate verification failed" @@ -1374,7 +1374,7 @@ run_test "Authentication: client badcert, server required" \ -C "skip write certificate verify" \ -S "skip parse certificate verify" \ -s "x509_verify_cert() returned" \ - -S "! self-signed or not signed by a trusted CA" \ + -S "! The certificate is not correctly signed by the trusted CA" \ -s "! ssl_handshake returned" \ -c "! ssl_handshake returned" \ -s "X509 - Certificate verification failed" @@ -1391,7 +1391,7 @@ run_test "Authentication: client badcert, server optional" \ -C "skip write certificate verify" \ -S "skip parse certificate verify" \ -s "x509_verify_cert() returned" \ - -s "! self-signed or not signed by a trusted CA" \ + -s "! The certificate is not correctly signed by the trusted CA" \ -S "! ssl_handshake returned" \ -C "! ssl_handshake returned" \ -S "X509 - Certificate verification failed" @@ -1408,7 +1408,7 @@ run_test "Authentication: client badcert, server none" \ -c "skip write certificate verify" \ -s "skip parse certificate verify" \ -S "x509_verify_cert() returned" \ - -S "! self-signed or not signed by a trusted CA" \ + -S "! The certificate is not correctly signed by the trusted CA" \ -S "! ssl_handshake returned" \ -C "! ssl_handshake returned" \ -S "X509 - Certificate verification failed" @@ -1425,7 +1425,7 @@ run_test "Authentication: client no cert, server optional" \ -S "SSLv3 client has no certificate" \ -c "skip write certificate verify" \ -s "skip parse certificate verify" \ - -s "! no client certificate sent" \ + -s "! Certificate was missing" \ -S "! ssl_handshake returned" \ -C "! ssl_handshake returned" \ -S "X509 - Certificate verification failed" @@ -1436,7 +1436,7 @@ run_test "Authentication: openssl client no cert, server optional" \ 0 \ -S "skip write certificate request" \ -s "skip parse certificate verify" \ - -s "! no client certificate sent" \ + -s "! Certificate was missing" \ -S "! ssl_handshake returned" \ -S "X509 - Certificate verification failed" @@ -1462,7 +1462,7 @@ run_test "Authentication: client no cert, ssl3" \ -c "got no certificate to send" \ -s "SSLv3 client has no certificate" \ -s "skip parse certificate verify" \ - -s "! no client certificate sent" \ + -s "! Certificate was missing" \ -S "! ssl_handshake returned" \ -C "! ssl_handshake returned" \ -S "X509 - Certificate verification failed" From 9f98251e724a5b5dbdd8b8dda9af9d9ada80f43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 17 Apr 2015 16:55:53 +0200 Subject: [PATCH 3/3] Make results of (ext)KeyUsage accessible --- ChangeLog | 3 +++ include/polarssl/ssl.h | 3 ++- library/ssl_srv.c | 3 ++- library/ssl_tls.c | 20 +++++++++++++++----- tests/ssl-opt.sh | 22 ++++++++++++++++++++++ 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8d7a8108e..ab1b78bad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ mbed TLS ChangeLog (Sorted per branch, date) = mbed TLS 1.3 branch Security + * With authmode set to SSL_VERIFY_OPTIONAL, verification of keyUsage and + extendedKeyUsage on the leaf certificate was lost (results not accessible + via ssl_get_verify_results()). Features * Add x509_crt_verify_info() to display certificate verification results. diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index cd9f770e9..54382e5a0 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -1980,7 +1980,8 @@ static inline x509_crt *ssl_own_cert( ssl_context *ssl ) */ int ssl_check_cert_usage( const x509_crt *cert, const ssl_ciphersuite_t *ciphersuite, - int cert_endpoint ); + int cert_endpoint, + int *flags ); #endif /* POLARSSL_X509_CRT_PARSE_C */ /* constant-time buffer comparison */ diff --git a/library/ssl_srv.c b/library/ssl_srv.c index dad6872ea..5f01a01bc 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -829,6 +829,7 @@ static int ssl_pick_cert( ssl_context *ssl, { ssl_key_cert *cur, *list, *fallback = NULL; pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + int flags; #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) if( ssl->handshake->sni_key_cert != NULL ) @@ -862,7 +863,7 @@ static int ssl_pick_cert( ssl_context *ssl, * and decrypting with the same RSA key. */ if( ssl_check_cert_usage( cur->cert, ciphersuite_info, - SSL_IS_SERVER ) != 0 ) + SSL_IS_SERVER, &flags ) != 0 ) { SSL_DEBUG_MSG( 3, ( "certificate mismatch: " "(extended) key usage extension" ) ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d2e0c52bc..72cd6d21a 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2859,7 +2859,8 @@ int ssl_parse_certificate( ssl_context *ssl ) if( ssl_check_cert_usage( ssl->session_negotiate->peer_cert, ciphersuite_info, - ! ssl->endpoint ) != 0 ) + ! ssl->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) { SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); if( ret == 0 ) @@ -5199,8 +5200,10 @@ int ssl_curve_is_acceptable( const ssl_context *ssl, ecp_group_id grp_id ) #if defined(POLARSSL_X509_CRT_PARSE_C) int ssl_check_cert_usage( const x509_crt *cert, const ssl_ciphersuite_t *ciphersuite, - int cert_endpoint ) + int cert_endpoint, + int *flags ) { + int ret = 0; #if defined(POLARSSL_X509_CHECK_KEY_USAGE) int usage = 0; #endif @@ -5213,6 +5216,7 @@ int ssl_check_cert_usage( const x509_crt *cert, !defined(POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) ((void) cert); ((void) cert_endpoint); + ((void) flags); #endif #if defined(POLARSSL_X509_CHECK_KEY_USAGE) @@ -5252,7 +5256,10 @@ int ssl_check_cert_usage( const x509_crt *cert, } if( x509_crt_check_key_usage( cert, usage ) != 0 ) - return( -1 ); + { + *flags |= BADCERT_KEY_USAGE; + ret = -1; + } #else ((void) ciphersuite); #endif /* POLARSSL_X509_CHECK_KEY_USAGE */ @@ -5270,10 +5277,13 @@ int ssl_check_cert_usage( const x509_crt *cert, } if( x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) - return( -1 ); + { + *flags |= BADCERT_EXT_KEY_USAGE; + ret = -1; + } #endif /* POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE */ - return( 0 ); + return( ret ); } #endif /* POLARSSL_X509_CRT_PARSE_C */ diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 75c59423a..5cf4ff608 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1878,6 +1878,17 @@ run_test "keyUsage cli: KeyEncipherment, DHE-RSA: fail" \ -c "Processing of the Certificate handshake message failed" \ -C "Ciphersuite is TLS-" +run_test "keyUsage cli: KeyEncipherment, DHE-RSA: fail, soft" \ + "$O_SRV -key data_files/server2.key \ + -cert data_files/server2.ku-ke.crt" \ + "$P_CLI debug_level=1 auth_mode=optional \ + force_ciphersuite=TLS-DHE-RSA-WITH-AES-128-CBC-SHA" \ + 0 \ + -c "bad certificate (usage extensions)" \ + -C "Processing of the Certificate handshake message failed" \ + -c "Ciphersuite is TLS-" \ + -c "! Usage does not match the keyUsage extension" + run_test "keyUsage cli: DigitalSignature, DHE-RSA: OK" \ "$O_SRV -key data_files/server2.key \ -cert data_files/server2.ku-ds.crt" \ @@ -1898,6 +1909,17 @@ run_test "keyUsage cli: DigitalSignature, RSA: fail" \ -c "Processing of the Certificate handshake message failed" \ -C "Ciphersuite is TLS-" +run_test "keyUsage cli: DigitalSignature, RSA: fail, soft" \ + "$O_SRV -key data_files/server2.key \ + -cert data_files/server2.ku-ds.crt" \ + "$P_CLI debug_level=1 auth_mode=optional \ + force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \ + 0 \ + -c "bad certificate (usage extensions)" \ + -C "Processing of the Certificate handshake message failed" \ + -c "Ciphersuite is TLS-" \ + -c "! Usage does not match the keyUsage extension" + # Tests for keyUsage in leaf certificates, part 3: # server-side checking of client cert