1 From e8bd647d8271174d3737dcf68086126b73a73df6 Mon Sep 17 00:00:00 2001
2 From: Oleksii Beketov <ol.beketov@samsung.com>
3 Date: Mon, 18 Dec 2017 15:23:28 +0200
4 Subject: [PATCH] CVE-2017-14032
6 Signed-off-by: Oleksii Beketov <ol.beketov@samsung.com>
8 include/mbedtls/error.h | 2 +-
9 include/mbedtls/ssl.h | 2 +-
10 include/mbedtls/x509.h | 1 +
11 include/mbedtls/x509_crt.h | 8 +++++++-
12 library/error.c | 2 ++
13 library/x509_crt.c | 30 ++++++++++++++++++++++--------
14 6 files changed, 34 insertions(+), 11 deletions(-)
16 diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
17 index 5e549f6..31591e2 100644
18 --- a/include/mbedtls/error.h
19 +++ b/include/mbedtls/error.h
21 * Name ID Nr of Errors
23 * PKCS#12 1 4 (Started from top)
26 * PKCS5 2 4 (Started from top)
28 * PK 3 14 (Started from top)
29 diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
30 index 495e02c..4f171e0 100644
31 --- a/include/mbedtls/ssl.h
32 +++ b/include/mbedtls/ssl.h
33 @@ -1042,7 +1042,7 @@ void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode );
35 * If set, the verify callback is called for each
36 * certificate in the chain. For implementation
37 - * information, please see \c x509parse_verify()
38 + * information, please see \c mbedtls_x509_crt_verify()
40 * \param conf SSL configuration
41 * \param f_vrfy verification function
42 diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
43 index f219bf1..128eade 100644
44 --- a/include/mbedtls/x509.h
45 +++ b/include/mbedtls/x509.h
47 #define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */
48 #define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */
49 #define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */
50 +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */
54 diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
55 index 383e484..fd20336 100644
56 --- a/include/mbedtls/x509_crt.h
57 +++ b/include/mbedtls/x509_crt.h
58 @@ -267,7 +267,13 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
60 * All flags left after returning from the callback
61 * are also returned to the application. The function should
62 - * return 0 for anything but a fatal error.
63 + * return 0 for anything (including invalid certificates)
64 + * other than fatal error, as a non-zero return code
65 + * immediately aborts the verification process. For fatal
66 + * errors, a specific error code should be used (different
67 + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not
68 + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR
69 + * can be used if no better code is available.
71 * \note In case verification failed, the results can be displayed
72 * using \c mbedtls_x509_crt_verify_info()
73 diff --git a/library/error.c b/library/error.c
74 index dd2db0c..db42381 100644
77 @@ -480,6 +480,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
78 mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" );
79 if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) )
80 mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" );
81 + if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) )
82 + mbedtls_snprintf( buf, buflen, "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed" );
83 #endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
86 diff --git a/library/x509_crt.c b/library/x509_crt.c
87 index 234f145..1f31a6b 100644
88 --- a/library/x509_crt.c
89 +++ b/library/x509_crt.c
90 @@ -2055,8 +2055,8 @@ static int x509_crt_verify_child(
91 /* path_cnt is 0 for the first intermediate CA */
92 if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
94 - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
95 - return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
96 + /* return immediately as the goal is to avoid unbounded recursion */
97 + return( MBEDTLS_ERR_X509_FATAL_ERROR );
100 if( mbedtls_x509_time_is_past( &child->valid_to ) )
101 @@ -2200,11 +2200,14 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
102 mbedtls_x509_sequence *cur = NULL;
103 mbedtls_pk_type_t pk_type;
105 - if( profile == NULL )
106 - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
110 + if( profile == NULL )
112 + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
118 name = &crt->subject;
119 @@ -2278,7 +2281,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
120 ret = x509_crt_verify_top( crt, parent, ca_crl, profile,
121 pathlen, selfsigned, flags, f_vrfy, p_vrfy );
128 @@ -2293,17 +2296,28 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
129 ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile,
130 pathlen, selfsigned, flags, f_vrfy, p_vrfy );
137 ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile,
138 pathlen, selfsigned, flags, f_vrfy, p_vrfy );
146 + /* prevent misuse of the vrfy callback */
147 + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
148 + ret = MBEDTLS_ERR_X509_FATAL_ERROR;
152 + *flags = (uint32_t) -1;
157 return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );