blob: 6c87959b60f45a796355a1a12984391a80474914 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
Manuel Pégourié-Gonnard1c082f32014-06-12 22:34:55 +02002 * X.509 certificate parsing and verification
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker7c6b2c32013-09-16 13:49:26 +020018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020020 */
21/*
22 * The ITU-T X.509 standard defines a certificate format for PKI.
23 *
Manuel Pégourié-Gonnard1c082f32014-06-12 22:34:55 +020024 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
25 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
26 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020027 *
28 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +020030 *
31 * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020032 */
33
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000035#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020036#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020037#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020038#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_X509_CRT_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020041
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000042#include "mbedtls/x509_crt.h"
43#include "mbedtls/oid.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050044#include "mbedtls/platform_util.h"
Rich Evans00ab4702015-02-06 13:43:58 +000045
Rich Evans00ab4702015-02-06 13:43:58 +000046#include <string.h>
47
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/pem.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020050#endif
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020054#else
Simon Butcherd2642582018-10-03 15:11:19 +010055#include <stdio.h>
Rich Evans00ab4702015-02-06 13:43:58 +000056#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_free free
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_snprintf snprintf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020060#endif
61
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000063#include "mbedtls/threading.h"
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +010064#endif
65
Paul Bakkerfa6a6202013-10-28 18:48:30 +010066#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020067#include <windows.h>
68#else
69#include <time.h>
70#endif
71
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072#if defined(MBEDTLS_FS_IO)
Rich Evans00ab4702015-02-06 13:43:58 +000073#include <stdio.h>
Paul Bakker5ff3f912014-04-04 15:08:20 +020074#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020075#include <sys/types.h>
76#include <sys/stat.h>
77#include <dirent.h>
Rich Evans00ab4702015-02-06 13:43:58 +000078#endif /* !_WIN32 || EFIX64 || EFI32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +020079#endif
80
Hanno Becker21f55672019-02-15 15:27:59 +000081static int x509_crt_parse_frame( unsigned char *start,
82 unsigned char *end,
83 mbedtls_x509_crt_frame *frame );
84static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame *frame,
85 mbedtls_x509_name *subject );
86static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame *frame,
87 mbedtls_x509_name *issuer );
88static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame *frame,
89 mbedtls_x509_sequence *subject_alt );
90static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame *frame,
91 mbedtls_x509_sequence *ext_key_usage );
92
Hanno Becker337088a2019-02-25 14:53:14 +000093static void x509_free_sequence( mbedtls_x509_sequence *seq );
94static void x509_free_name( mbedtls_x509_name *name );
95
Hanno Beckerb6c39fc2019-02-25 13:50:14 +000096int mbedtls_x509_crt_cache_provide_frame( mbedtls_x509_crt const *crt )
Hanno Becker337088a2019-02-25 14:53:14 +000097{
Hanno Beckerb6c39fc2019-02-25 13:50:14 +000098 mbedtls_x509_crt_cache *cache = crt->cache;
Hanno Becker337088a2019-02-25 14:53:14 +000099 mbedtls_x509_crt_frame *frame;
100
101 frame = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_frame ) );
102 if( frame == NULL )
103 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000104 cache->frame = frame;
Hanno Becker337088a2019-02-25 14:53:14 +0000105
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000106 return( x509_crt_parse_frame( crt->raw.p,
107 crt->raw.p + crt->raw.len,
108 frame ) );
109}
Hanno Becker337088a2019-02-25 14:53:14 +0000110
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000111int mbedtls_x509_crt_cache_provide_pk( mbedtls_x509_crt const *crt )
112{
113 mbedtls_x509_crt_cache *cache = crt->cache;
114 mbedtls_pk_context *pk;
115
116 pk = mbedtls_calloc( 1, sizeof( mbedtls_pk_context ) );
117 if( pk == NULL )
118 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
119 *pk = crt->pk;
120
121 cache->pk = pk;
Hanno Becker337088a2019-02-25 14:53:14 +0000122 return( 0 );
123}
124
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000125static void x509_crt_cache_init( mbedtls_x509_crt_cache *cache )
Hanno Becker337088a2019-02-25 14:53:14 +0000126{
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000127 memset( cache, 0, sizeof( *cache ) );
128#if defined(MBEDTLS_THREADING_C)
129 mbedtls_mutex_init( &cache->frame_mutex );
130 mbedtls_mutex_init( &cache->pk_mutex );
131#endif
132}
133
134static void x509_crt_cache_clear_pk( mbedtls_x509_crt_cache *cache )
135{
136 /* The cache holds a shallow copy of the PK context
137 * in the legacy struct, so don't free PK context. */
138 mbedtls_free( cache->pk );
139 cache->pk = NULL;
140}
141
142static void x509_crt_cache_clear_frame( mbedtls_x509_crt_cache *cache )
143{
144 mbedtls_free( cache->frame );
145 cache->frame = NULL;
146}
147
148static void x509_crt_cache_free( mbedtls_x509_crt_cache *cache )
149{
150 if( cache == NULL )
Hanno Becker337088a2019-02-25 14:53:14 +0000151 return;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000152
153#if defined(MBEDTLS_THREADING_C)
154 mbedtls_mutex_free( &cache->frame_mutex );
155 mbedtls_mutex_free( &cache->pk_mutex );
156#endif
157
158 x509_crt_cache_clear_frame( cache );
159 x509_crt_cache_clear_pk( cache );
160
161 memset( cache, 0, sizeof( *cache ) );
Hanno Becker337088a2019-02-25 14:53:14 +0000162}
163
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000164int mbedtls_x509_crt_flush_cache( mbedtls_x509_crt const *crt )
Hanno Becker337088a2019-02-25 14:53:14 +0000165{
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000166#if defined(MBEDTLS_THREADING_C)
167 if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
168 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
169 if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
170 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
171#endif
172 x509_crt_cache_clear_frame( crt->cache );
173 x509_crt_cache_clear_pk( crt->cache );
174#if defined(MBEDTLS_THREADING_C)
175 if( mbedtls_mutex_unlock( &crt->cache->frame_mutex ) != 0 )
176 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
177 if( mbedtls_mutex_unlock( &crt->cache->pk_mutex ) != 0 )
178 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
179#endif
180 return( 0 );
Hanno Becker337088a2019-02-25 14:53:14 +0000181}
182
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +0200183/*
184 * Item in a verification chain: cert and flags for it
185 */
186typedef struct {
187 mbedtls_x509_crt *crt;
188 uint32_t flags;
189} x509_crt_verify_chain_item;
190
191/*
192 * Max size of verification chain: end-entity + intermediates + trusted root
193 */
194#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
Paul Bakker34617722014-06-13 17:20:13 +0200195
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200196/*
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200197 * Default profile
198 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200199const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
200{
Gilles Peskine5d2511c2017-05-12 13:16:40 +0200201#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200202 /* Allow SHA-1 (weak, but still safe in controlled environments) */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200203 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200204#endif
205 /* Only SHA-2 hashes */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200206 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
207 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
208 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
209 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
210 0xFFFFFFF, /* Any PK alg */
211 0xFFFFFFF, /* Any curve */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200212 2048,
213};
214
215/*
216 * Next-default profile
217 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200218const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
219{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200220 /* Hashes from SHA-256 and above */
221 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
222 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
223 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
224 0xFFFFFFF, /* Any PK alg */
225#if defined(MBEDTLS_ECP_C)
226 /* Curves at or above 128-bit security level */
227 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
228 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
229 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
230 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
231 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
232 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
233 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
234#else
235 0,
236#endif
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200237 2048,
238};
239
240/*
241 * NSA Suite B Profile
242 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200243const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
244{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200245 /* Only SHA-256 and 384 */
246 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
247 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
248 /* Only ECDSA */
Ron Eldor85e1dcf2018-02-06 15:59:38 +0200249 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
250 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200251#if defined(MBEDTLS_ECP_C)
252 /* Only NIST P-256 and P-384 */
253 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
254 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
255#else
256 0,
257#endif
258 0,
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200259};
260
261/*
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200262 * Check md_alg against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200263 * Return 0 if md_alg is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200264 */
265static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
266 mbedtls_md_type_t md_alg )
267{
Philippe Antoineb5b25432018-05-11 11:06:29 +0200268 if( md_alg == MBEDTLS_MD_NONE )
269 return( -1 );
270
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200271 if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
272 return( 0 );
273
274 return( -1 );
275}
276
277/*
278 * Check pk_alg against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200279 * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200280 */
281static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
282 mbedtls_pk_type_t pk_alg )
283{
Philippe Antoineb5b25432018-05-11 11:06:29 +0200284 if( pk_alg == MBEDTLS_PK_NONE )
285 return( -1 );
286
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200287 if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
288 return( 0 );
289
290 return( -1 );
291}
292
293/*
294 * Check key against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200295 * Return 0 if pk is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200296 */
297static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200298 const mbedtls_pk_context *pk )
299{
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200300 const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk );
Manuel Pégourié-Gonnard19773ff2017-10-24 10:51:26 +0200301
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200302#if defined(MBEDTLS_RSA_C)
303 if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
304 {
Manuel Pégourié-Gonnard097c7bb2015-06-18 16:43:38 +0200305 if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200306 return( 0 );
307
308 return( -1 );
309 }
310#endif
311
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +0200312#if defined(MBEDTLS_ECP_C)
313 if( pk_alg == MBEDTLS_PK_ECDSA ||
314 pk_alg == MBEDTLS_PK_ECKEY ||
315 pk_alg == MBEDTLS_PK_ECKEY_DH )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200316 {
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200317 const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200318
Philippe Antoineb5b25432018-05-11 11:06:29 +0200319 if( gid == MBEDTLS_ECP_DP_NONE )
320 return( -1 );
321
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200322 if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
323 return( 0 );
324
325 return( -1 );
326 }
327#endif
328
329 return( -1 );
330}
331
332/*
Hanno Becker1f8527f2018-11-02 09:19:16 +0000333 * Return 0 if name matches wildcard, -1 otherwise
334 */
Hanno Becker24926222019-02-21 13:10:55 +0000335static int x509_check_wildcard( char const *cn,
336 size_t cn_len,
337 unsigned char const *buf,
338 size_t buf_len )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000339{
340 size_t i;
Hanno Becker24926222019-02-21 13:10:55 +0000341 size_t cn_idx = 0;
Hanno Becker1f8527f2018-11-02 09:19:16 +0000342
343 /* We can't have a match if there is no wildcard to match */
Hanno Becker24926222019-02-21 13:10:55 +0000344 if( buf_len < 3 || buf[0] != '*' || buf[1] != '.' )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000345 return( -1 );
346
347 for( i = 0; i < cn_len; ++i )
348 {
349 if( cn[i] == '.' )
350 {
351 cn_idx = i;
352 break;
353 }
354 }
355
356 if( cn_idx == 0 )
357 return( -1 );
358
Hanno Beckerb3def1d2019-02-22 11:46:06 +0000359 if( mbedtls_x509_memcasecmp( buf + 1, cn + cn_idx,
360 buf_len - 1, cn_len - cn_idx ) == 0 )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000361 {
362 return( 0 );
363 }
364
365 return( -1 );
366}
367
368/*
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +0200369 * Reset (init or clear) a verify_chain
370 */
371static void x509_crt_verify_chain_reset(
372 mbedtls_x509_crt_verify_chain *ver_chain )
373{
374 size_t i;
375
376 for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
377 {
378 ver_chain->items[i].crt = NULL;
Hanno Beckerd6ddcd62019-01-10 09:19:26 +0000379 ver_chain->items[i].flags = (uint32_t) -1;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +0200380 }
381
382 ver_chain->len = 0;
383}
384
385/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200386 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
387 */
388static int x509_get_version( unsigned char **p,
389 const unsigned char *end,
390 int *ver )
391{
392 int ret;
393 size_t len;
394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
396 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200399 {
400 *ver = 0;
401 return( 0 );
402 }
403
Hanno Becker2f472142019-02-12 11:52:10 +0000404 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200405 }
406
407 end = *p + len;
408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
410 return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200411
412 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 return( MBEDTLS_ERR_X509_INVALID_VERSION +
414 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200415
416 return( 0 );
417}
418
419/*
420 * Validity ::= SEQUENCE {
421 * notBefore Time,
422 * notAfter Time }
423 */
424static int x509_get_dates( unsigned char **p,
425 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 mbedtls_x509_time *from,
427 mbedtls_x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200428{
429 int ret;
430 size_t len;
431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
433 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
434 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200435
436 end = *p + len;
437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200439 return( ret );
440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200442 return( ret );
443
444 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 return( MBEDTLS_ERR_X509_INVALID_DATE +
446 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200447
448 return( 0 );
449}
450
451/*
452 * X.509 v2/v3 unique identifier (not parsed)
453 */
454static int x509_get_uid( unsigned char **p,
455 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 mbedtls_x509_buf *uid, int n )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200457{
458 int ret;
459
460 if( *p == end )
461 return( 0 );
462
463 uid->tag = **p;
464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
466 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200467 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200469 return( 0 );
470
Hanno Becker2f472142019-02-12 11:52:10 +0000471 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200472 }
473
474 uid->p = *p;
475 *p += uid->len;
476
477 return( 0 );
478}
479
480static int x509_get_basic_constraints( unsigned char **p,
481 const unsigned char *end,
482 int *ca_istrue,
483 int *max_pathlen )
484{
485 int ret;
486 size_t len;
487
488 /*
489 * BasicConstraints ::= SEQUENCE {
490 * cA BOOLEAN DEFAULT FALSE,
491 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
492 */
493 *ca_istrue = 0; /* DEFAULT FALSE */
494 *max_pathlen = 0; /* endless */
495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
497 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000498 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200499
500 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200501 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200504 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
506 ret = mbedtls_asn1_get_int( p, end, ca_istrue );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200507
508 if( ret != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000509 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200510
511 if( *ca_istrue != 0 )
512 *ca_istrue = 1;
513 }
514
515 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200516 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000519 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200520
521 if( *p != end )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000522 return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200523
524 (*max_pathlen)++;
525
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200526 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200527}
528
529static int x509_get_ns_cert_type( unsigned char **p,
530 const unsigned char *end,
531 unsigned char *ns_cert_type)
532{
533 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200535
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000537 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200538
539 if( bs.len != 1 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000540 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200541
542 /* Get actual bitstring */
543 *ns_cert_type = *bs.p;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200544 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200545}
546
547static int x509_get_key_usage( unsigned char **p,
548 const unsigned char *end,
Manuel Pégourié-Gonnard1d0ca1a2015-03-27 16:50:00 +0100549 unsigned int *key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200550{
551 int ret;
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200552 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000556 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200557
558 if( bs.len < 1 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000559 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200560
561 /* Get actual bitstring */
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200562 *key_usage = 0;
563 for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
564 {
565 *key_usage |= (unsigned int) bs.p[i] << (8*i);
566 }
567
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200568 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200569}
570
571/*
572 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
573 *
574 * KeyPurposeId ::= OBJECT IDENTIFIER
575 */
576static int x509_get_ext_key_usage( unsigned char **p,
577 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200578 mbedtls_x509_sequence *ext_key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200579{
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000580 return( mbedtls_asn1_get_sequence_of( p, end, ext_key_usage,
581 MBEDTLS_ASN1_OID ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200582}
583
584/*
585 * SubjectAltName ::= GeneralNames
586 *
587 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
588 *
589 * GeneralName ::= CHOICE {
590 * otherName [0] OtherName,
591 * rfc822Name [1] IA5String,
592 * dNSName [2] IA5String,
593 * x400Address [3] ORAddress,
594 * directoryName [4] Name,
595 * ediPartyName [5] EDIPartyName,
596 * uniformResourceIdentifier [6] IA5String,
597 * iPAddress [7] OCTET STRING,
598 * registeredID [8] OBJECT IDENTIFIER }
599 *
600 * OtherName ::= SEQUENCE {
601 * type-id OBJECT IDENTIFIER,
602 * value [0] EXPLICIT ANY DEFINED BY type-id }
603 *
604 * EDIPartyName ::= SEQUENCE {
605 * nameAssigner [0] DirectoryString OPTIONAL,
606 * partyName [1] DirectoryString }
607 *
Manuel Pégourié-Gonnardb4fe3cb2015-01-22 16:11:05 +0000608 * NOTE: we only parse and use dNSName at this point.
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200609 */
Hanno Beckerad462192019-02-21 13:32:31 +0000610static int x509_get_subject_alt_name_cb( void *ctx,
611 int tag,
612 unsigned char *data,
613 size_t data_len )
614{
615 mbedtls_asn1_sequence **cur_ptr = (mbedtls_asn1_sequence **) ctx;
616 mbedtls_asn1_sequence *cur = *cur_ptr;
617
Hanno Beckerad462192019-02-21 13:32:31 +0000618 /* Allocate and assign next pointer */
619 if( cur->buf.p != NULL )
620 {
621 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
622 if( cur->next == NULL )
Hanno Becker90b94082019-02-21 21:13:21 +0000623 return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
Hanno Beckerad462192019-02-21 13:32:31 +0000624 cur = cur->next;
625 }
626
627 cur->buf.tag = tag;
628 cur->buf.p = data;
629 cur->buf.len = data_len;
630
631 *cur_ptr = cur;
632 return( 0 );
633}
634
Hanno Becker5984d302019-02-21 14:46:54 +0000635static int x509_get_subject_alt_name( unsigned char *p,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200636 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 mbedtls_x509_sequence *subject_alt_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200638{
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000639 return( mbedtls_asn1_traverse_sequence_of( &p, end,
640 MBEDTLS_ASN1_TAG_CLASS_MASK,
641 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
642 MBEDTLS_ASN1_TAG_VALUE_MASK,
643 2 /* SubjectAlt DNS */,
644 x509_get_subject_alt_name_cb,
645 (void*) &subject_alt_name ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200646}
647
648/*
649 * X.509 v3 extensions
650 *
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200651 */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000652static int x509_crt_get_ext_cb( void *ctx,
653 int tag,
654 unsigned char *p,
655 size_t ext_len )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200656{
657 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +0000658 mbedtls_x509_crt_frame *frame = (mbedtls_x509_crt_frame *) ctx;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200659 size_t len;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000660 unsigned char *end, *end_ext_octet;
661 mbedtls_x509_buf extn_oid = { 0, 0, NULL };
662 int is_critical = 0; /* DEFAULT FALSE */
663 int ext_type = 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200664
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000665 ((void) tag);
Hanno Becker4e1bfc12019-02-12 17:22:36 +0000666
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000667 /*
668 * Extension ::= SEQUENCE {
669 * extnID OBJECT IDENTIFIER,
670 * critical BOOLEAN DEFAULT FALSE,
671 * extnValue OCTET STRING }
672 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200673
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000674 end = p + ext_len;
675
676 /* Get extension ID */
677 if( ( ret = mbedtls_asn1_get_tag( &p, end, &extn_oid.len,
678 MBEDTLS_ASN1_OID ) ) != 0 )
679 goto err;
680
681 extn_oid.tag = MBEDTLS_ASN1_OID;
682 extn_oid.p = p;
683 p += extn_oid.len;
684
685 /* Get optional critical */
686 if( ( ret = mbedtls_asn1_get_bool( &p, end, &is_critical ) ) != 0 &&
687 ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
688 goto err;
689
690 /* Data should be octet string type */
691 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
692 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
693 goto err;
694
695 end_ext_octet = p + len;
696 if( end_ext_octet != end )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200697 {
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000698 ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
699 goto err;
700 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200701
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000702 /*
703 * Detect supported extensions
704 */
705 ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
706 if( ret != 0 )
707 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000709 if( is_critical )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200710 {
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000711 /* Data is marked as critical: fail */
712 ret = MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
713 goto err;
714 }
715#endif
716 return( 0 );
717 }
718
719 /* Forbid repeated extensions */
Hanno Becker21f55672019-02-15 15:27:59 +0000720 if( ( frame->ext_types & ext_type ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000721 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
722
Hanno Becker21f55672019-02-15 15:27:59 +0000723 frame->ext_types |= ext_type;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000724 switch( ext_type )
725 {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100726 case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000727 {
728 int ca_istrue;
729 int max_pathlen;
730
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200731 /* Parse basic constraints */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000732 ret = x509_get_basic_constraints( &p, end_ext_octet,
733 &ca_istrue,
734 &max_pathlen );
735 if( ret != 0 )
736 goto err;
737
Hanno Becker21f55672019-02-15 15:27:59 +0000738 frame->ca_istrue = ca_istrue;
739 frame->max_pathlen = max_pathlen;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200740 break;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000741 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 case MBEDTLS_X509_EXT_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200744 /* Parse key usage */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000745 ret = x509_get_key_usage( &p, end_ext_octet,
Hanno Becker21f55672019-02-15 15:27:59 +0000746 &frame->key_usage );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000747 if( ret != 0 )
748 goto err;
749 break;
750
751 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
752 /* Copy reference to raw subject alt name data. */
Hanno Becker21f55672019-02-15 15:27:59 +0000753 frame->subject_alt_raw.p = p;
754 frame->subject_alt_raw.len = end_ext_octet - p;
755
756 ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
757 MBEDTLS_ASN1_TAG_CLASS_MASK,
758 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
759 MBEDTLS_ASN1_TAG_VALUE_MASK,
760 2 /* SubjectAlt DNS */,
761 NULL, NULL );
762 if( ret != 0 )
763 goto err;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200764 break;
765
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200767 /* Parse extended key usage */
Hanno Becker21f55672019-02-15 15:27:59 +0000768 frame->ext_key_usage_raw.p = p;
769 frame->ext_key_usage_raw.len = end_ext_octet - p;
770 if( frame->ext_key_usage_raw.len == 0 )
Hanno Becker5984d302019-02-21 14:46:54 +0000771 {
Hanno Becker21f55672019-02-15 15:27:59 +0000772 ret = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
773 goto err;
Hanno Becker5984d302019-02-21 14:46:54 +0000774 }
Hanno Becker21f55672019-02-15 15:27:59 +0000775
776 /* Check structural sanity of extension. */
777 ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
778 0xFF, MBEDTLS_ASN1_OID,
779 0, 0, NULL, NULL );
780 if( ret != 0 )
781 goto err;
782
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200783 break;
784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200786 /* Parse netscape certificate type */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000787 ret = x509_get_ns_cert_type( &p, end_ext_octet,
Hanno Becker21f55672019-02-15 15:27:59 +0000788 &frame->ns_cert_type );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000789 if( ret != 0 )
790 goto err;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200791 break;
792
793 default:
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000794 /*
795 * If this is a non-critical extension, which the oid layer
796 * supports, but there isn't an X.509 parser for it,
797 * skip the extension.
798 */
799#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
800 if( is_critical )
801 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
802#endif
803 p = end_ext_octet;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200804 }
805
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200806 return( 0 );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000807
808err:
809 return( ret );
810}
811
Hanno Becker21f55672019-02-15 15:27:59 +0000812static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000813{
814 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +0000815 unsigned char *p = frame->v3_ext.p;
816 unsigned char *end = p + frame->v3_ext.len;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000817
Hanno Becker21f55672019-02-15 15:27:59 +0000818 if( p == end )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000819 return( 0 );
820
Hanno Becker21f55672019-02-15 15:27:59 +0000821 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000822 0xFF, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED,
Hanno Becker21f55672019-02-15 15:27:59 +0000823 0, 0, x509_crt_get_ext_cb, frame );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000824
825 if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
826 return( ret );
827 if( ret == MBEDTLS_ERR_X509_INVALID_EXTENSIONS )
828 return( ret );
829
830 if( ret != 0 )
831 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
832
833 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200834}
835
Hanno Becker21f55672019-02-15 15:27:59 +0000836static int x509_crt_parse_frame( unsigned char *start,
837 unsigned char *end,
838 mbedtls_x509_crt_frame *frame )
839{
840 int ret;
841 unsigned char *p;
842 size_t len;
843
844 mbedtls_x509_buf tmp;
845 unsigned char *tbs_start;
846
847 mbedtls_x509_buf outer_sig_alg;
848 size_t inner_sig_alg_len;
849 unsigned char *inner_sig_alg_start;
850
851 memset( frame, 0, sizeof( *frame ) );
852
853 /*
854 * Certificate ::= SEQUENCE {
855 * tbsCertificate TBSCertificate,
856 * signatureAlgorithm AlgorithmIdentifier,
857 * signatureValue BIT STRING
858 * }
859 *
860 */
861 p = start;
862
863 frame->raw.p = p;
864 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
865 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
866 {
867 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
868 }
869
870 /* NOTE: We are currently not checking that the `Certificate`
871 * structure spans the entire buffer. */
872 end = p + len;
873 frame->raw.len = end - frame->raw.p;
874
875 /*
876 * TBSCertificate ::= SEQUENCE { ...
877 */
878 frame->tbs.p = p;
879 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
880 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
881 {
882 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
883 }
884 tbs_start = p;
885
886 /* Breadth-first parsing: Jump over TBS for now. */
887 p += len;
888 frame->tbs.len = p - frame->tbs.p;
889
890 /*
891 * AlgorithmIdentifier ::= SEQUENCE { ...
892 */
893 outer_sig_alg.p = p;
894 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
895 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
896 {
897 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
898 }
899 p += len;
900 outer_sig_alg.len = p - outer_sig_alg.p;
901
902 /*
903 * signatureValue BIT STRING
904 */
905 ret = mbedtls_x509_get_sig( &p, end, &tmp );
906 if( ret != 0 )
907 return( ret );
908 frame->sig.p = tmp.p;
909 frame->sig.len = tmp.len;
910
911 /* Check that we consumed the entire `Certificate` structure. */
912 if( p != end )
913 {
914 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
915 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
916 }
917
918 /* Parse TBSCertificate structure
919 *
920 * TBSCertificate ::= SEQUENCE {
921 * version [0] EXPLICIT Version DEFAULT v1,
922 * serialNumber CertificateSerialNumber,
923 * signature AlgorithmIdentifier,
924 * issuer Name,
925 * validity Validity,
926 * subject Name,
927 * subjectPublicKeyInfo SubjectPublicKeyInfo,
928 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
929 * -- If present, version MUST be v2 or v3
930 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
931 * -- If present, version MUST be v2 or v3
932 * extensions [3] EXPLICIT Extensions OPTIONAL
933 * -- If present, version MUST be v3
934 * }
935 */
936 end = frame->tbs.p + frame->tbs.len;
937 p = tbs_start;
938
939 /*
940 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
941 */
942 {
943 int version;
944 ret = x509_get_version( &p, end, &version );
945 if( ret != 0 )
946 return( ret );
947
948 if( version < 0 || version > 2 )
949 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
950
951 frame->version = version + 1;
952 }
953
954 /*
955 * CertificateSerialNumber ::= INTEGER
956 */
957 ret = mbedtls_x509_get_serial( &p, end, &tmp );
958 if( ret != 0 )
959 return( ret );
960
961 frame->serial.p = tmp.p;
962 frame->serial.len = tmp.len;
963
964 /*
965 * signature AlgorithmIdentifier
966 */
967 inner_sig_alg_start = p;
968 ret = mbedtls_x509_get_sig_alg_raw( &p, end, &frame->sig_md,
969 &frame->sig_pk, NULL );
970 if( ret != 0 )
971 return( ret );
972 inner_sig_alg_len = p - inner_sig_alg_start;
973
974 frame->sig_alg.p = inner_sig_alg_start;
975 frame->sig_alg.len = inner_sig_alg_len;
976
977 /* Consistency check:
978 * Inner and outer AlgorithmIdentifier structures must coincide:
979 *
980 * Quoting RFC 5280, Section 4.1.1.2:
981 * This field MUST contain the same algorithm identifier as the
982 * signature field in the sequence tbsCertificate (Section 4.1.2.3).
983 */
984 if( outer_sig_alg.len != inner_sig_alg_len ||
985 memcmp( outer_sig_alg.p, inner_sig_alg_start, inner_sig_alg_len ) != 0 )
986 {
987 return( MBEDTLS_ERR_X509_SIG_MISMATCH );
988 }
989
990 /*
991 * issuer Name
992 *
993 * Name ::= CHOICE { -- only one possibility for now --
994 * rdnSequence RDNSequence }
995 *
996 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
997 */
998 frame->issuer_raw_with_hdr.p = p;
999
1000 ret = mbedtls_asn1_get_tag( &p, end, &len,
1001 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1002 if( ret != 0 )
1003 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
1004 frame->issuer_raw.p = p;
1005 frame->issuer_raw.len = len;
1006 p += len;
1007
1008 ret = mbedtls_x509_name_cmp_raw( &frame->issuer_raw,
1009 &frame->issuer_raw,
1010 NULL, NULL );
1011 if( ret != 0 )
1012 return( ret );
1013
1014 frame->issuer_raw_with_hdr.len = p - frame->issuer_raw_with_hdr.p;
1015
1016 /*
1017 * Validity ::= SEQUENCE { ...
1018 */
1019 ret = x509_get_dates( &p, end, &frame->valid_from, &frame->valid_to );
1020 if( ret != 0 )
1021 return( ret );
1022
1023 /*
1024 * subject Name
1025 *
1026 * Name ::= CHOICE { -- only one possibility for now --
1027 * rdnSequence RDNSequence }
1028 *
1029 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
1030 */
1031 frame->subject_raw_with_hdr.p = p;
1032
1033 ret = mbedtls_asn1_get_tag( &p, end, &len,
1034 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1035 if( ret != 0 )
1036 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
1037 frame->subject_raw.p = p;
1038 frame->subject_raw.len = len;
1039 p += len;
1040
1041 ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
1042 &frame->subject_raw,
1043 NULL, NULL );
1044 if( ret != 0 )
1045 return( ret );
1046
1047 frame->subject_raw_with_hdr.len = p - frame->subject_raw_with_hdr.p;
1048
1049 /*
1050 * SubjectPublicKeyInfo
1051 */
1052 frame->pubkey_raw.p = p;
1053 ret = mbedtls_asn1_get_tag( &p, end, &len,
1054 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1055 if( ret != 0 )
1056 return( ret + MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
1057 p += len;
1058 frame->pubkey_raw.len = p - frame->pubkey_raw.p;
1059
1060 /*
1061 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1062 * -- If present, version shall be v2 or v3
1063 */
1064 if( frame->version == 2 || frame->version == 3 )
1065 {
1066 ret = x509_get_uid( &p, end, &tmp, 1 /* implicit tag */ );
1067 if( ret != 0 )
1068 return( ret );
1069
1070 frame->issuer_id.p = tmp.p;
1071 frame->issuer_id.len = tmp.len;
1072 }
1073
1074 /*
1075 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1076 * -- If present, version shall be v2 or v3
1077 */
1078 if( frame->version == 2 || frame->version == 3 )
1079 {
1080 ret = x509_get_uid( &p, end, &tmp, 2 /* implicit tag */ );
1081 if( ret != 0 )
1082 return( ret );
1083
1084 frame->subject_id.p = tmp.p;
1085 frame->subject_id.len = tmp.len;
1086 }
1087
1088 /*
1089 * extensions [3] EXPLICIT Extensions OPTIONAL
1090 * -- If present, version shall be v3
1091 */
1092#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
1093 if( frame->version == 3 )
1094#endif
1095 {
1096 if( p != end )
1097 {
1098 ret = mbedtls_asn1_get_tag( &p, end, &len,
1099 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
1100 MBEDTLS_ASN1_CONSTRUCTED | 3 );
1101 if( len == 0 )
1102 ret = MBEDTLS_ERR_ASN1_OUT_OF_DATA;
1103 if( ret != 0 )
1104 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
1105
1106 frame->v3_ext.p = p;
1107 frame->v3_ext.len = len;
1108
1109 p += len;
1110 }
1111
1112 ret = x509_crt_frame_parse_ext( frame );
1113 if( ret != 0 )
1114 return( ret );
1115 }
1116
1117 /* Wrapup: Check that we consumed the entire `TBSCertificate` structure. */
1118 if( p != end )
1119 {
1120 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
1121 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
1122 }
1123
1124 return( 0 );
1125}
1126
1127static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame *frame,
1128 mbedtls_x509_name *subject )
1129{
1130 unsigned char *p = frame->subject_raw.p;
1131 unsigned char *end = p + frame->subject_raw.len;
1132
1133 return( mbedtls_x509_get_name( &p, end, subject ) );
1134}
1135
1136static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame *frame,
1137 mbedtls_x509_name *issuer )
1138{
1139 unsigned char *p = frame->issuer_raw.p;
1140 unsigned char *end = p + frame->issuer_raw.len;
1141
1142 return( mbedtls_x509_get_name( &p, end, issuer ) );
1143}
1144
1145static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame *frame,
1146 mbedtls_x509_sequence *subject_alt )
1147{
1148 int ret;
1149 unsigned char *p = frame->subject_alt_raw.p;
1150 unsigned char *end = p + frame->subject_alt_raw.len;
1151
1152 memset( subject_alt, 0, sizeof( *subject_alt ) );
1153
1154 if( ( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) == 0 )
1155 return( 0 );
1156
1157 ret = x509_get_subject_alt_name( p, end, subject_alt );
1158 if( ret != 0 )
1159 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1160 return( ret );
1161}
1162
1163static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame *frame,
1164 mbedtls_x509_sequence *ext_key_usage )
1165{
1166 int ret;
1167 unsigned char *p = frame->ext_key_usage_raw.p;
1168 unsigned char *end = p + frame->ext_key_usage_raw.len;
1169
1170 memset( ext_key_usage, 0, sizeof( *ext_key_usage ) );
1171
1172 if( ( frame->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
1173 return( 0 );
1174
1175 ret = x509_get_ext_key_usage( &p, end, ext_key_usage );
1176 if( ret != 0 )
1177 {
1178 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1179 return( ret );
1180 }
1181
1182 return( 0 );
1183}
1184
1185static int x509_crt_pk_from_frame( mbedtls_x509_crt_frame *frame,
1186 mbedtls_pk_context *pk )
1187{
1188 unsigned char *p = frame->pubkey_raw.p;
1189 unsigned char *end = p + frame->pubkey_raw.len;
1190 return( mbedtls_pk_parse_subpubkey( &p, end, pk ) );
1191}
1192
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001193/*
1194 * Parse and fill a single X.509 certificate in DER format
1195 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001196static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
1197 const unsigned char *buf,
1198 size_t buflen,
1199 int make_copy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001200{
1201 int ret;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001202 mbedtls_x509_crt_frame *frame;
1203 mbedtls_x509_crt_cache *cache;
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +01001204
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001205 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001206 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001207
Hanno Becker21f55672019-02-15 15:27:59 +00001208 if( make_copy == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001209 {
Hanno Becker21f55672019-02-15 15:27:59 +00001210 crt->raw.p = (unsigned char*) buf;
1211 crt->raw.len = buflen;
1212 crt->own_buffer = 0;
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001213 }
1214 else
1215 {
Hanno Becker21f55672019-02-15 15:27:59 +00001216 crt->raw.p = mbedtls_calloc( 1, buflen );
1217 if( crt->raw.p == NULL )
1218 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
1219 crt->raw.len = buflen;
1220 memcpy( crt->raw.p, buf, buflen );
1221
1222 crt->own_buffer = 1;
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001223 }
Janos Follathcc0e49d2016-02-17 14:34:12 +00001224
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001225 cache = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_cache ) );
1226 if( cache == NULL )
1227 {
1228 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
1229 goto exit;
1230 }
1231 crt->cache = cache;
1232 x509_crt_cache_init( cache );
1233
1234 ret = mbedtls_x509_crt_cache_provide_frame( crt );
Hanno Becker21f55672019-02-15 15:27:59 +00001235 if( ret != 0 )
1236 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001237
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001238 frame = mbedtls_x509_crt_cache_get_frame( crt->cache );
1239
Hanno Becker21f55672019-02-15 15:27:59 +00001240 /* Currently, we accept DER encoded CRTs with trailing garbage
1241 * and promise to not account for the garbage in the `raw` field.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001242 *
Hanno Becker21f55672019-02-15 15:27:59 +00001243 * Note that this means that `crt->raw.len` is not necessarily the
1244 * full size of the heap buffer allocated at `crt->raw.p` in case
1245 * of copy-mode, but this is not a problem: freeing the buffer doesn't
1246 * need the size, and the garbage data doesn't need zeroization. */
1247 crt->raw.len = frame->raw.len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001248
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001249 cache->pk_raw = frame->pubkey_raw;
1250
Hanno Becker21f55672019-02-15 15:27:59 +00001251 /* Copy frame to legacy CRT structure -- that's inefficient, but if
1252 * memory matters, the new CRT structure should be used anyway. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001253 crt->tbs.p = frame->tbs.p;
1254 crt->tbs.len = frame->tbs.len;
1255 crt->serial.p = frame->serial.p;
1256 crt->serial.len = frame->serial.len;
1257 crt->issuer_raw.p = frame->issuer_raw_with_hdr.p;
1258 crt->issuer_raw.len = frame->issuer_raw_with_hdr.len;
1259 crt->subject_raw.p = frame->subject_raw_with_hdr.p;
1260 crt->subject_raw.len = frame->subject_raw_with_hdr.len;
1261 crt->issuer_raw_no_hdr = frame->issuer_raw;
1262 crt->subject_raw_no_hdr = frame->subject_raw;
1263 crt->issuer_id.p = frame->issuer_id.p;
1264 crt->issuer_id.len = frame->issuer_id.len;
1265 crt->subject_id.p = frame->subject_id.p;
1266 crt->subject_id.len = frame->subject_id.len;
1267 crt->pk_raw.p = frame->pubkey_raw.p;
1268 crt->pk_raw.len = frame->pubkey_raw.len;
1269 crt->ext_key_usage_raw = frame->ext_key_usage_raw;
1270 crt->subject_alt_raw = frame->subject_alt_raw;
1271 crt->sig.p = frame->sig.p;
1272 crt->sig.len = frame->sig.len;
1273 crt->valid_from = frame->valid_from;
1274 crt->valid_to = frame->valid_to;
1275 crt->v3_ext.p = frame->v3_ext.p;
1276 crt->v3_ext.len = frame->v3_ext.len;
1277 crt->version = frame->version;
1278 crt->ca_istrue = frame->ca_istrue;
1279 crt->max_pathlen = frame->max_pathlen;
1280 crt->ext_types = frame->ext_types;
1281 crt->key_usage = frame->key_usage;
1282 crt->ns_cert_type = frame->ns_cert_type;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001283
1284 /*
Hanno Becker21f55672019-02-15 15:27:59 +00001285 * Obtain the remaining fields from the frame.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001286 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001287
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001288 {
Hanno Becker21f55672019-02-15 15:27:59 +00001289 /* sig_oid: Previously, needed for convenience in
1290 * mbedtls_x509_crt_info(), now pure legacy burden. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001291 unsigned char *tmp = frame->sig_alg.p;
1292 unsigned char *end = tmp + frame->sig_alg.len;
Hanno Becker21f55672019-02-15 15:27:59 +00001293 mbedtls_x509_buf sig_oid, sig_params;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001294
Hanno Becker21f55672019-02-15 15:27:59 +00001295 ret = mbedtls_x509_get_alg( &tmp, end,
1296 &sig_oid, &sig_params );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001297 if( ret != 0 )
1298 {
Hanno Becker21f55672019-02-15 15:27:59 +00001299 /* This should never happen, because we check
1300 * the sanity of the AlgorithmIdentifier structure
1301 * during frame parsing. */
1302 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1303 goto exit;
1304 }
1305 crt->sig_oid = sig_oid;
1306
1307 /* Signature parameters */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001308 tmp = frame->sig_alg.p;
Hanno Becker21f55672019-02-15 15:27:59 +00001309 ret = mbedtls_x509_get_sig_alg_raw( &tmp, end,
1310 &crt->sig_md, &crt->sig_pk,
1311 &crt->sig_opts );
1312 if( ret != 0 )
1313 {
1314 /* Again, this should never happen. */
1315 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1316 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001317 }
1318 }
1319
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001320 ret = x509_crt_pk_from_frame( frame, &crt->pk );
Hanno Becker21f55672019-02-15 15:27:59 +00001321 if( ret != 0 )
1322 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001323
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001324 ret = x509_crt_subject_from_frame( frame, &crt->subject );
Hanno Becker21f55672019-02-15 15:27:59 +00001325 if( ret != 0 )
1326 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001327
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001328 ret = x509_crt_issuer_from_frame( frame, &crt->issuer );
Hanno Becker21f55672019-02-15 15:27:59 +00001329 if( ret != 0 )
1330 goto exit;
1331
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001332 ret = x509_crt_subject_alt_from_frame( frame, &crt->subject_alt_names );
Hanno Becker21f55672019-02-15 15:27:59 +00001333 if( ret != 0 )
1334 goto exit;
1335
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001336 ret = x509_crt_ext_key_usage_from_frame( frame, &crt->ext_key_usage );
1337 if( ret != 0 )
1338 goto exit;
1339
1340
1341 /* The cache just references the PK structure from the legacy
1342 * implementation, so set up the latter first before setting up
1343 * the cache. */
1344 ret = mbedtls_x509_crt_cache_provide_pk( crt );
Hanno Becker21f55672019-02-15 15:27:59 +00001345 if( ret != 0 )
1346 goto exit;
1347
1348exit:
1349 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001351
Hanno Becker21f55672019-02-15 15:27:59 +00001352 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001353}
1354
1355/*
1356 * Parse one X.509 certificate in DER format from a buffer and add them to a
1357 * chained list
1358 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001359static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
1360 const unsigned char *buf,
1361 size_t buflen,
1362 int make_copy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001363{
1364 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 mbedtls_x509_crt *crt = chain, *prev = NULL;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001366
1367 /*
1368 * Check for valid input
1369 */
1370 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001372
Hanno Becker371e0e42019-02-25 18:08:59 +00001373 while( crt->raw.p != NULL && crt->next != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001374 {
1375 prev = crt;
1376 crt = crt->next;
1377 }
1378
1379 /*
1380 * Add new certificate on the end of the chain if needed.
1381 */
Hanno Becker371e0e42019-02-25 18:08:59 +00001382 if( crt->raw.p != NULL && crt->next == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001383 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001384 crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001385
1386 if( crt->next == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001387 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001388
1389 prev = crt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 mbedtls_x509_crt_init( crt->next );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001391 crt = crt->next;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001392 }
1393
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001394 if( ( ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001395 {
1396 if( prev )
1397 prev->next = NULL;
1398
1399 if( crt != chain )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 mbedtls_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001401
1402 return( ret );
1403 }
1404
1405 return( 0 );
1406}
1407
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001408int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain,
1409 const unsigned char *buf,
1410 size_t buflen )
1411{
1412 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0 ) );
1413}
1414
1415int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain,
1416 const unsigned char *buf,
1417 size_t buflen )
1418{
1419 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1 ) );
1420}
1421
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001422/*
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001423 * Parse one or more PEM certificates from a buffer and add them to the chained
1424 * list
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001425 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001426int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
1427 const unsigned char *buf,
1428 size_t buflen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001429{
Janos Follath98e28a72016-05-31 14:03:54 +01001430#if defined(MBEDTLS_PEM_PARSE_C)
Andres AGc0db5112016-12-07 15:05:53 +00001431 int success = 0, first_error = 0, total_failed = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 int buf_format = MBEDTLS_X509_FORMAT_DER;
Janos Follath98e28a72016-05-31 14:03:54 +01001433#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001434
1435 /*
1436 * Check for valid input
1437 */
1438 if( chain == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001439 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001440
1441 /*
1442 * Determine buffer content. Buffer contains either one DER certificate or
1443 * one or more PEM certificates.
1444 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001445#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001446 if( buflen != 0 && buf[buflen - 1] == '\0' &&
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001447 strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
1448 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 buf_format = MBEDTLS_X509_FORMAT_PEM;
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001450 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452 if( buf_format == MBEDTLS_X509_FORMAT_DER )
1453 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
Janos Follath98e28a72016-05-31 14:03:54 +01001454#else
1455 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
1456#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458#if defined(MBEDTLS_PEM_PARSE_C)
1459 if( buf_format == MBEDTLS_X509_FORMAT_PEM )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001460 {
1461 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462 mbedtls_pem_context pem;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001463
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001464 /* 1 rather than 0 since the terminating NULL byte is counted in */
1465 while( buflen > 1 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001466 {
1467 size_t use_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001468 mbedtls_pem_init( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001469
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001470 /* If we get there, we know the string is null-terminated */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 ret = mbedtls_pem_read_buffer( &pem,
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001472 "-----BEGIN CERTIFICATE-----",
1473 "-----END CERTIFICATE-----",
1474 buf, NULL, 0, &use_len );
1475
1476 if( ret == 0 )
1477 {
1478 /*
1479 * Was PEM encoded
1480 */
1481 buflen -= use_len;
1482 buf += use_len;
1483 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001485 {
1486 return( ret );
1487 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001489 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001490 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001491
1492 /*
1493 * PEM header and footer were found
1494 */
1495 buflen -= use_len;
1496 buf += use_len;
1497
1498 if( first_error == 0 )
1499 first_error = ret;
1500
Paul Bakker5a5fa922014-09-26 14:53:04 +02001501 total_failed++;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001502 continue;
1503 }
1504 else
1505 break;
1506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001510
1511 if( ret != 0 )
1512 {
1513 /*
1514 * Quit parsing on a memory error
1515 */
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001516 if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001517 return( ret );
1518
1519 if( first_error == 0 )
1520 first_error = ret;
1521
1522 total_failed++;
1523 continue;
1524 }
1525
1526 success = 1;
1527 }
1528 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001529
1530 if( success )
1531 return( total_failed );
1532 else if( first_error )
1533 return( first_error );
1534 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001535 return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
Janos Follath98e28a72016-05-31 14:03:54 +01001536#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001537}
1538
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539#if defined(MBEDTLS_FS_IO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001540/*
1541 * Load one or more certificates and add them to the chained list
1542 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001544{
1545 int ret;
1546 size_t n;
1547 unsigned char *buf;
1548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001549 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001550 return( ret );
1551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001552 ret = mbedtls_x509_crt_parse( chain, buf, n );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001553
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001554 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 mbedtls_free( buf );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001556
1557 return( ret );
1558}
1559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001561{
1562 int ret = 0;
Paul Bakkerfa6a6202013-10-28 18:48:30 +01001563#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001564 int w_ret;
1565 WCHAR szDir[MAX_PATH];
1566 char filename[MAX_PATH];
Paul Bakker9af723c2014-05-01 13:03:14 +02001567 char *p;
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001568 size_t len = strlen( path );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001569
Paul Bakker9af723c2014-05-01 13:03:14 +02001570 WIN32_FIND_DATAW file_data;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001571 HANDLE hFind;
1572
1573 if( len > MAX_PATH - 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001575
Paul Bakker9af723c2014-05-01 13:03:14 +02001576 memset( szDir, 0, sizeof(szDir) );
1577 memset( filename, 0, MAX_PATH );
1578 memcpy( filename, path, len );
1579 filename[len++] = '\\';
1580 p = filename + len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001581 filename[len++] = '*';
1582
Simon B3c6b18d2016-11-03 01:11:37 +00001583 w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001584 MAX_PATH - 3 );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001585 if( w_ret == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001587
1588 hFind = FindFirstFileW( szDir, &file_data );
Paul Bakker66d5d072014-06-17 16:39:18 +02001589 if( hFind == INVALID_HANDLE_VALUE )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001591
1592 len = MAX_PATH - len;
1593 do
1594 {
Paul Bakker9af723c2014-05-01 13:03:14 +02001595 memset( p, 0, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001596
1597 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
1598 continue;
1599
Paul Bakker9af723c2014-05-01 13:03:14 +02001600 w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
Paul Bakker66d5d072014-06-17 16:39:18 +02001601 lstrlenW( file_data.cFileName ),
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001602 p, (int) len - 1,
Paul Bakker9af723c2014-05-01 13:03:14 +02001603 NULL, NULL );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001604 if( w_ret == 0 )
Ron Eldor36d90422017-01-09 15:09:16 +02001605 {
1606 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
1607 goto cleanup;
1608 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 w_ret = mbedtls_x509_crt_parse_file( chain, filename );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001611 if( w_ret < 0 )
1612 ret++;
1613 else
1614 ret += w_ret;
1615 }
1616 while( FindNextFileW( hFind, &file_data ) != 0 );
1617
Paul Bakker66d5d072014-06-17 16:39:18 +02001618 if( GetLastError() != ERROR_NO_MORE_FILES )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001620
Ron Eldor36d90422017-01-09 15:09:16 +02001621cleanup:
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001622 FindClose( hFind );
Paul Bakkerbe089b02013-10-14 15:51:50 +02001623#else /* _WIN32 */
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001624 int t_ret;
Andres AGf9113192016-09-02 14:06:04 +01001625 int snp_ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001626 struct stat sb;
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001627 struct dirent *entry;
Andres AGf9113192016-09-02 14:06:04 +01001628 char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001629 DIR *dir = opendir( path );
1630
Paul Bakker66d5d072014-06-17 16:39:18 +02001631 if( dir == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001633
Ron Eldor63140682017-01-09 19:27:59 +02001634#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02001635 if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02001636 {
1637 closedir( dir );
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001638 return( ret );
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02001639 }
Ron Eldor63140682017-01-09 19:27:59 +02001640#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001641
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001642 while( ( entry = readdir( dir ) ) != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001643 {
Andres AGf9113192016-09-02 14:06:04 +01001644 snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
1645 "%s/%s", path, entry->d_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001646
Andres AGf9113192016-09-02 14:06:04 +01001647 if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001648 {
Andres AGf9113192016-09-02 14:06:04 +01001649 ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1650 goto cleanup;
1651 }
1652 else if( stat( entry_name, &sb ) == -1 )
1653 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001655 goto cleanup;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001656 }
1657
1658 if( !S_ISREG( sb.st_mode ) )
1659 continue;
1660
1661 // Ignore parse errors
1662 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001664 if( t_ret < 0 )
1665 ret++;
1666 else
1667 ret += t_ret;
1668 }
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001669
1670cleanup:
Andres AGf9113192016-09-02 14:06:04 +01001671 closedir( dir );
1672
Ron Eldor63140682017-01-09 19:27:59 +02001673#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02001674 if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675 ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
Ron Eldor63140682017-01-09 19:27:59 +02001676#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001677
Paul Bakkerbe089b02013-10-14 15:51:50 +02001678#endif /* _WIN32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001679
1680 return( ret );
1681}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682#endif /* MBEDTLS_FS_IO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001683
Hanno Becker02a21932019-06-10 15:08:43 +01001684#if !defined(MBEDTLS_X509_REMOVE_INFO)
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001685static int x509_info_subject_alt_name( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 const mbedtls_x509_sequence *subject_alt_name )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001687{
1688 size_t i;
1689 size_t n = *size;
1690 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 const mbedtls_x509_sequence *cur = subject_alt_name;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001692 const char *sep = "";
1693 size_t sep_len = 0;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001694
1695 while( cur != NULL )
1696 {
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001697 if( cur->buf.len + sep_len >= n )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001698 {
1699 *p = '\0';
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001700 return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001701 }
1702
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001703 n -= cur->buf.len + sep_len;
1704 for( i = 0; i < sep_len; i++ )
1705 *p++ = sep[i];
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001706 for( i = 0; i < cur->buf.len; i++ )
1707 *p++ = cur->buf.p[i];
1708
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001709 sep = ", ";
1710 sep_len = 2;
1711
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001712 cur = cur->next;
1713 }
1714
1715 *p = '\0';
1716
1717 *size = n;
1718 *buf = p;
1719
1720 return( 0 );
1721}
1722
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001723#define PRINT_ITEM(i) \
1724 { \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001726 MBEDTLS_X509_SAFE_SNPRINTF; \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001727 sep = ", "; \
1728 }
1729
1730#define CERT_TYPE(type,name) \
Hanno Beckerd6028a12018-10-15 12:01:35 +01001731 if( ns_cert_type & (type) ) \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001732 PRINT_ITEM( name );
1733
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001734static int x509_info_cert_type( char **buf, size_t *size,
1735 unsigned char ns_cert_type )
1736{
1737 int ret;
1738 size_t n = *size;
1739 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001740 const char *sep = "";
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001741
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001742 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001743 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" );
1745 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" );
1746 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001747 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" );
1748 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" );
1749 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" );
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001750
1751 *size = n;
1752 *buf = p;
1753
1754 return( 0 );
1755}
1756
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001757#define KEY_USAGE(code,name) \
Hanno Beckerd6028a12018-10-15 12:01:35 +01001758 if( key_usage & (code) ) \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001759 PRINT_ITEM( name );
1760
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001761static int x509_info_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02001762 unsigned int key_usage )
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001763{
1764 int ret;
1765 size_t n = *size;
1766 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001767 const char *sep = "";
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001769 KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" );
1770 KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001771 KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" );
1772 KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" );
1773 KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774 KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" );
1775 KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" );
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02001776 KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" );
1777 KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" );
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001778
1779 *size = n;
1780 *buf = p;
1781
1782 return( 0 );
1783}
1784
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001785static int x509_info_ext_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001786 const mbedtls_x509_sequence *extended_key_usage )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001787{
1788 int ret;
1789 const char *desc;
1790 size_t n = *size;
1791 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 const mbedtls_x509_sequence *cur = extended_key_usage;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001793 const char *sep = "";
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001794
1795 while( cur != NULL )
1796 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001798 desc = "???";
1799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001800 ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001801 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001802
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001803 sep = ", ";
1804
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001805 cur = cur->next;
1806 }
1807
1808 *size = n;
1809 *buf = p;
1810
1811 return( 0 );
1812}
1813
Hanno Becker4f869ed2019-02-24 16:47:57 +00001814typedef struct mbedtls_x509_crt_sig_info
1815{
1816 mbedtls_md_type_t sig_md;
1817 mbedtls_pk_type_t sig_pk;
1818 void *sig_opts;
1819 uint8_t crt_hash[MBEDTLS_MD_MAX_SIZE];
1820 size_t crt_hash_len;
1821 mbedtls_x509_buf_raw sig;
1822 mbedtls_x509_buf_raw issuer_raw;
1823} mbedtls_x509_crt_sig_info;
1824
1825static void x509_crt_free_sig_info( mbedtls_x509_crt_sig_info *info )
1826{
1827#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
1828 mbedtls_free( info->sig_opts );
1829#else
1830 ((void) info);
1831#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
1832}
1833
1834static int x509_crt_get_sig_info( mbedtls_x509_crt_frame const *frame,
1835 mbedtls_x509_crt_sig_info *info )
1836{
1837 const mbedtls_md_info_t *md_info;
1838
1839 md_info = mbedtls_md_info_from_type( frame->sig_md );
1840 if( mbedtls_md( md_info, frame->tbs.p, frame->tbs.len,
1841 info->crt_hash ) != 0 )
1842 {
1843 /* Note: this can't happen except after an internal error */
1844 return( -1 );
1845 }
1846
1847 info->crt_hash_len = mbedtls_md_get_size( md_info );
1848
1849 /* Make sure that this function leaves the target structure
1850 * ready to be freed, regardless of success of failure. */
1851 info->sig_opts = NULL;
1852
1853#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
1854 {
1855 int ret;
1856 unsigned char *alg_start = frame->sig_alg.p;
1857 unsigned char *alg_end = alg_start + frame->sig_alg.len;
1858
1859 /* Get signature options -- currently only
1860 * necessary for RSASSA-PSS. */
1861 ret = mbedtls_x509_get_sig_alg_raw( &alg_start, alg_end, &info->sig_md,
1862 &info->sig_pk, &info->sig_opts );
1863 if( ret != 0 )
1864 {
1865 /* Note: this can't happen except after an internal error */
1866 return( -1 );
1867 }
1868 }
1869#else /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
1870 info->sig_md = frame->sig_md;
1871 info->sig_pk = frame->sig_pk;
1872#endif /* !MBEDTLS_X509_RSASSA_PSS_SUPPORT */
1873
1874 info->issuer_raw = frame->issuer_raw;
1875 info->sig = frame->sig;
1876 return( 0 );
1877}
1878
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001879/*
1880 * Return an informational string about the certificate.
1881 */
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001882#define BEFORE_COLON 18
1883#define BC "18"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
Hanno Becker4f869ed2019-02-24 16:47:57 +00001885 const mbedtls_x509_crt *crt_raw )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001886{
1887 int ret;
1888 size_t n;
1889 char *p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001890 char key_size_str[BEFORE_COLON];
Hanno Becker4f869ed2019-02-24 16:47:57 +00001891 mbedtls_x509_crt_frame *crt;
1892 mbedtls_pk_context *pk;
1893
1894 mbedtls_x509_name issuer, subject;
1895 mbedtls_x509_sequence ext_key_usage, subject_alt_names;
1896 mbedtls_x509_crt_sig_info sig_info;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001897
1898 p = buf;
1899 n = size;
1900
Hanno Becker4f869ed2019-02-24 16:47:57 +00001901 memset( &sig_info, 0, sizeof( mbedtls_x509_crt_sig_info ) );
1902 if( NULL == crt_raw )
Janos Follath98e28a72016-05-31 14:03:54 +01001903 {
1904 ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001905 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Janos Follath98e28a72016-05-31 14:03:54 +01001906
1907 return( (int) ( size - n ) );
1908 }
1909
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001910 ret = mbedtls_x509_crt_frame_acquire( crt_raw, &crt );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001911 if( ret != 0 )
1912 return( MBEDTLS_ERR_X509_FATAL_ERROR );
1913
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001914 ret = mbedtls_x509_crt_pk_acquire( (mbedtls_x509_crt*) crt_raw, &pk );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001915 if( ret != 0 )
1916 {
1917 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1918 goto cleanup;
1919 }
1920
1921 ret = x509_crt_get_sig_info( crt, &sig_info );
1922 if( ret != 0 )
1923 {
1924 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1925 goto cleanup;
1926 }
1927
1928 ret = x509_crt_subject_from_frame( crt, &subject );
1929 if( ret != 0 )
1930 {
1931 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1932 goto cleanup;
1933 }
1934
1935 ret = x509_crt_issuer_from_frame( crt, &issuer );
1936 if( ret != 0 )
1937 {
1938 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1939 goto cleanup;
1940 }
1941
1942 ret = x509_crt_subject_alt_from_frame( crt, &subject_alt_names );
1943 if( ret != 0 )
1944 {
1945 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1946 goto cleanup;
1947 }
1948
1949 ret = x509_crt_ext_key_usage_from_frame( crt, &ext_key_usage );
1950 if( ret != 0 )
1951 {
1952 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1953 goto cleanup;
1954 }
1955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001956 ret = mbedtls_snprintf( p, n, "%scert. version : %d\n",
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001957 prefix, crt->version );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001958 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001959
Hanno Becker4f869ed2019-02-24 16:47:57 +00001960 {
1961 mbedtls_x509_buf serial;
1962 serial.p = crt->serial.p;
1963 serial.len = crt->serial.len;
1964 ret = mbedtls_snprintf( p, n, "%sserial number : ",
1965 prefix );
1966 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
1967 ret = mbedtls_x509_serial_gets( p, n, &serial );
1968 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
1969 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001970
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001971 ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001972 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
1973 ret = mbedtls_x509_dn_gets( p, n, &issuer );
1974 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001975
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001977 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
1978 ret = mbedtls_x509_dn_gets( p, n, &subject );
1979 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001980
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 ret = mbedtls_snprintf( p, n, "\n%sissued on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001982 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1983 crt->valid_from.year, crt->valid_from.mon,
1984 crt->valid_from.day, crt->valid_from.hour,
1985 crt->valid_from.min, crt->valid_from.sec );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001986 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001987
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988 ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001989 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1990 crt->valid_to.year, crt->valid_to.mon,
1991 crt->valid_to.day, crt->valid_to.hour,
1992 crt->valid_to.min, crt->valid_to.sec );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001993 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001994
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00001996 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001997
Hanno Becker83cd8672019-02-21 17:13:46 +00001998 ret = mbedtls_x509_sig_alg_gets( p, n, sig_info.sig_pk,
1999 sig_info.sig_md, sig_info.sig_opts );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002000 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002001
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002002 /* Key size */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003 if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
Hanno Becker4f869ed2019-02-24 16:47:57 +00002004 mbedtls_pk_get_name( pk ) ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002005 {
2006 return( ret );
2007 }
2008
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002009 ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
Hanno Becker4f869ed2019-02-24 16:47:57 +00002010 (int) mbedtls_pk_get_bitlen( pk ) );
2011 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002012
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002013 /*
2014 * Optional extensions
2015 */
2016
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002017 if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002018 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002019 ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002020 crt->ca_istrue ? "true" : "false" );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002021 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002022
2023 if( crt->max_pathlen > 0 )
2024 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002025 ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002026 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002027 }
2028 }
2029
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002030 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002031 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002033 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002034
2035 if( ( ret = x509_info_subject_alt_name( &p, &n,
Hanno Becker4f869ed2019-02-24 16:47:57 +00002036 &subject_alt_names ) ) != 0 )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002037 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002038 }
2039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002041 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042 ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002043 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02002044
2045 if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
2046 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002047 }
2048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002050 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002052 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002053
2054 if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
2055 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002056 }
2057
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002059 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002061 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002062
2063 if( ( ret = x509_info_ext_key_usage( &p, &n,
Hanno Becker4f869ed2019-02-24 16:47:57 +00002064 &ext_key_usage ) ) != 0 )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002065 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002066 }
2067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 ret = mbedtls_snprintf( p, n, "\n" );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002069 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002070
Hanno Becker4f869ed2019-02-24 16:47:57 +00002071 ret = (int) ( size - n );
2072
2073cleanup:
2074
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002075 mbedtls_x509_crt_frame_release( crt_raw, crt );
2076 mbedtls_x509_crt_pk_release( (mbedtls_x509_crt*) crt_raw, pk );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002077
2078 x509_crt_free_sig_info( &sig_info );
2079 x509_free_name( issuer.next );
2080 x509_free_name( subject.next );
2081 x509_free_sequence( ext_key_usage.next );
2082 x509_free_sequence( subject_alt_names.next );
2083
2084 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002085}
2086
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002087struct x509_crt_verify_string {
2088 int code;
2089 const char *string;
2090};
2091
2092static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002093 { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002094 { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
2095 { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" },
2096 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" },
2097 { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" },
2098 { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002099 { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" },
2100 { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" },
2101 { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002102 { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002103 { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" },
2104 { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" },
2105 { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
2106 { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" },
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002107 { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." },
2108 { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
2109 { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
2110 { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." },
2111 { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
2112 { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002113 { 0, NULL }
2114};
2115
2116int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02002117 uint32_t flags )
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002118{
2119 int ret;
2120 const struct x509_crt_verify_string *cur;
2121 char *p = buf;
2122 size_t n = size;
2123
2124 for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
2125 {
2126 if( ( flags & cur->code ) == 0 )
2127 continue;
2128
2129 ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002130 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002131 flags ^= cur->code;
2132 }
2133
2134 if( flags != 0 )
2135 {
2136 ret = mbedtls_snprintf( p, n, "%sUnknown reason "
2137 "(this should not happen)\n", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002138 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002139 }
2140
2141 return( (int) ( size - n ) );
2142}
Hanno Becker02a21932019-06-10 15:08:43 +01002143#endif /* !MBEDTLS_X509_REMOVE_INFO */
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002145#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Hanno Becker45eedf12019-02-25 13:55:33 +00002146static int x509_crt_check_key_usage_frame( const mbedtls_x509_crt_frame *crt,
2147 unsigned int usage )
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002148{
Manuel Pégourié-Gonnard655a9642015-06-23 10:48:44 +02002149 unsigned int usage_must, usage_may;
2150 unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
2151 | MBEDTLS_X509_KU_DECIPHER_ONLY;
2152
2153 if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
2154 return( 0 );
2155
2156 usage_must = usage & ~may_mask;
2157
2158 if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
2159 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
2160
2161 usage_may = usage & may_mask;
2162
2163 if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002164 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002165
2166 return( 0 );
2167}
Hanno Becker45eedf12019-02-25 13:55:33 +00002168
2169int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
2170 unsigned int usage )
2171{
2172 int ret;
2173 mbedtls_x509_crt_frame *frame;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002174 ret = mbedtls_x509_crt_frame_acquire( crt,
2175 (mbedtls_x509_crt_frame**) &frame );
Hanno Becker45eedf12019-02-25 13:55:33 +00002176 if( ret != 0 )
2177 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2178
2179 ret = x509_crt_check_key_usage_frame( frame, usage );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002180 mbedtls_x509_crt_frame_release( crt, (mbedtls_x509_crt_frame*) frame );
Hanno Becker45eedf12019-02-25 13:55:33 +00002181
2182 return( ret );
2183}
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002184#endif
2185
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
Hanno Beckerc7c638e2019-02-21 21:10:51 +00002187typedef struct
2188{
2189 const char *oid;
2190 size_t oid_len;
2191} x509_crt_check_ext_key_usage_cb_ctx_t;
2192
2193static int x509_crt_check_ext_key_usage_cb( void *ctx,
2194 int tag,
2195 unsigned char *data,
2196 size_t data_len )
2197{
2198 x509_crt_check_ext_key_usage_cb_ctx_t *cb_ctx =
2199 (x509_crt_check_ext_key_usage_cb_ctx_t *) ctx;
2200 ((void) tag);
2201
2202 if( MBEDTLS_OID_CMP_RAW( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE,
2203 data, data_len ) == 0 )
2204 {
2205 return( 1 );
2206 }
2207
2208 if( data_len == cb_ctx->oid_len && memcmp( data, cb_ctx->oid,
2209 data_len ) == 0 )
2210 {
2211 return( 1 );
2212 }
2213
2214 return( 0 );
2215}
2216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
Hanno Beckere1956af2019-02-21 14:28:12 +00002218 const char *usage_oid,
2219 size_t usage_len )
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002220{
Hanno Beckere1956af2019-02-21 14:28:12 +00002221 int ret;
Hanno Beckere9718b42019-02-25 18:11:42 +00002222 mbedtls_x509_crt_frame *frame;
Hanno Beckere1956af2019-02-21 14:28:12 +00002223 unsigned ext_types;
2224 unsigned char *p, *end;
Hanno Beckerc7c638e2019-02-21 21:10:51 +00002225 x509_crt_check_ext_key_usage_cb_ctx_t cb_ctx = { usage_oid, usage_len };
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002226
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002227 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Beckere9718b42019-02-25 18:11:42 +00002228 if( ret != 0 )
2229 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2230
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002231 /* Extension is not mandatory, absent means no restriction */
Hanno Beckere9718b42019-02-25 18:11:42 +00002232 ext_types = frame->ext_types;
2233 if( ( ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) != 0 )
2234 {
2235 p = frame->ext_key_usage_raw.p;
2236 end = p + frame->ext_key_usage_raw.len;
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002237
Hanno Beckere9718b42019-02-25 18:11:42 +00002238 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
2239 0xFF, MBEDTLS_ASN1_OID, 0, 0,
2240 x509_crt_check_ext_key_usage_cb,
2241 &cb_ctx );
2242 if( ret == 1 )
2243 ret = 0;
2244 else
2245 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
2246 }
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002247
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002248 mbedtls_x509_crt_frame_release( crt, frame );
Hanno Beckere9718b42019-02-25 18:11:42 +00002249 return( ret );
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002250}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253#if defined(MBEDTLS_X509_CRL_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002254/*
2255 * Return 1 if the certificate is revoked, or 0 otherwise.
2256 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002257static int x509_serial_is_revoked( unsigned char const *serial,
2258 size_t serial_len,
2259 const mbedtls_x509_crl *crl )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002260{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002261 const mbedtls_x509_crl_entry *cur = &crl->entry;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002262
2263 while( cur != NULL && cur->serial.len != 0 )
2264 {
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002265 if( serial_len == cur->serial.len &&
2266 memcmp( serial, cur->serial.p, serial_len ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002267 {
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002268 if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002269 return( 1 );
2270 }
2271
2272 cur = cur->next;
2273 }
2274
2275 return( 0 );
2276}
2277
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002278int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt,
2279 const mbedtls_x509_crl *crl )
2280{
Hanno Becker79ae5b62019-02-25 18:12:00 +00002281 int ret;
2282 mbedtls_x509_crt_frame *frame;
2283
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002284 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Becker79ae5b62019-02-25 18:12:00 +00002285 if( ret != 0 )
2286 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2287
2288 ret = x509_serial_is_revoked( frame->serial.p,
2289 frame->serial.len,
2290 crl );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002291 mbedtls_x509_crt_frame_release( crt, frame );
Hanno Becker79ae5b62019-02-25 18:12:00 +00002292 return( ret );
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002293}
2294
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002295/*
Manuel Pégourié-Gonnardeeef9472016-02-22 11:36:55 +01002296 * Check that the given certificate is not revoked according to the CRL.
Manuel Pégourié-Gonnard08eacec2017-10-18 14:20:24 +02002297 * Skip validation if no CRL for the given CA is present.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002298 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002299static int x509_crt_verifycrl( unsigned char *crt_serial,
2300 size_t crt_serial_len,
Hanno Beckerbb266132019-02-25 18:12:46 +00002301 mbedtls_x509_crt *ca_crt,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002302 mbedtls_x509_crl *crl_list,
2303 const mbedtls_x509_crt_profile *profile )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002304{
Hanno Beckerbb266132019-02-25 18:12:46 +00002305 int ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002306 int flags = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002307 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
2308 const mbedtls_md_info_t *md_info;
Hanno Beckerbb266132019-02-25 18:12:46 +00002309 mbedtls_x509_buf_raw ca_subject;
2310 mbedtls_pk_context *pk;
2311 int can_sign;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002312
Hanno Beckerbb266132019-02-25 18:12:46 +00002313 if( ca_crt == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002314 return( flags );
2315
Hanno Beckerbb266132019-02-25 18:12:46 +00002316 {
2317 mbedtls_x509_crt_frame *ca;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002318 ret = mbedtls_x509_crt_frame_acquire( ca_crt, &ca );
Hanno Beckerbb266132019-02-25 18:12:46 +00002319 if( ret != 0 )
2320 return( MBEDTLS_X509_BADCRL_NOT_TRUSTED );
2321
2322 ca_subject = ca->subject_raw;
2323
2324 can_sign = 0;
2325 if( x509_crt_check_key_usage_frame( ca,
2326 MBEDTLS_X509_KU_CRL_SIGN ) == 0 )
2327 {
2328 can_sign = 1;
2329 }
2330
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002331 mbedtls_x509_crt_frame_release( ca_crt, ca );
Hanno Beckerbb266132019-02-25 18:12:46 +00002332 }
2333
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002334 ret = mbedtls_x509_crt_pk_acquire( ca_crt, &pk );
Hanno Beckerbb266132019-02-25 18:12:46 +00002335 if( ret != 0 )
2336 return( MBEDTLS_X509_BADCRL_NOT_TRUSTED );
2337
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002338 while( crl_list != NULL )
2339 {
2340 if( crl_list->version == 0 ||
Hanno Becker7dee12a2019-02-21 13:58:38 +00002341 mbedtls_x509_name_cmp_raw( &crl_list->issuer_raw_no_hdr,
Hanno Beckerbb266132019-02-25 18:12:46 +00002342 &ca_subject, NULL, NULL ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002343 {
2344 crl_list = crl_list->next;
2345 continue;
2346 }
2347
2348 /*
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002349 * Check if the CA is configured to sign CRLs
2350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Hanno Beckerbb266132019-02-25 18:12:46 +00002352 if( !can_sign )
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002353 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002355 break;
2356 }
2357#endif
2358
2359 /*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002360 * Check if CRL is correctly signed by the trusted CA
2361 */
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002362 if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
2363 flags |= MBEDTLS_X509_BADCRL_BAD_MD;
2364
2365 if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
2366 flags |= MBEDTLS_X509_BADCRL_BAD_PK;
2367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 md_info = mbedtls_md_info_from_type( crl_list->sig_md );
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02002369 if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002370 {
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02002371 /* Note: this can't happen except after an internal error */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002373 break;
2374 }
2375
Hanno Beckerbb266132019-02-25 18:12:46 +00002376 if( x509_profile_check_key( profile, pk ) != 0 )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002377 flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002378
Hanno Beckerbb266132019-02-25 18:12:46 +00002379 if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, pk,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
Manuel Pégourié-Gonnard53882022014-06-05 17:53:52 +02002381 crl_list->sig.p, crl_list->sig.len ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002382 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002384 break;
2385 }
2386
2387 /*
2388 * Check for validity of CRL (Do not drop out)
2389 */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002390 if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 flags |= MBEDTLS_X509_BADCRL_EXPIRED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002392
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002393 if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002394 flags |= MBEDTLS_X509_BADCRL_FUTURE;
Manuel Pégourié-Gonnard95337652014-03-10 13:15:18 +01002395
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002396 /*
2397 * Check if certificate is revoked
2398 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002399 if( x509_serial_is_revoked( crt_serial, crt_serial_len,
2400 crl_list ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002401 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 flags |= MBEDTLS_X509_BADCERT_REVOKED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002403 break;
2404 }
2405
2406 crl_list = crl_list->next;
2407 }
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002408
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002409 mbedtls_x509_crt_pk_release( ca_crt, pk );
Paul Bakkerd8bb8262014-06-17 14:06:49 +02002410 return( flags );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002411}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412#endif /* MBEDTLS_X509_CRL_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002413
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02002414/*
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002415 * Check the signature of a certificate by its parent
2416 */
Hanno Becker5299cf82019-02-25 13:50:41 +00002417static int x509_crt_check_signature( const mbedtls_x509_crt_sig_info *sig_info,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002418 mbedtls_x509_crt *parent,
2419 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002420{
Hanno Beckere449e2d2019-02-25 14:45:31 +00002421 int ret;
2422 mbedtls_pk_context *pk;
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002423
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002424 ret = mbedtls_x509_crt_pk_acquire( parent, &pk );
Hanno Beckere449e2d2019-02-25 14:45:31 +00002425 if( ret != 0 )
2426 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2427
2428 /* Skip expensive computation on obvious mismatch */
2429 if( ! mbedtls_pk_can_do( pk, sig_info->sig_pk ) )
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002430 {
Hanno Beckere449e2d2019-02-25 14:45:31 +00002431 ret = -1;
2432 goto exit;
2433 }
2434
2435#if !( defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) )
2436 ((void) rs_ctx);
2437#else
2438 if( rs_ctx != NULL && sig_info->sig_pk == MBEDTLS_PK_ECDSA )
2439 {
2440 ret = mbedtls_pk_verify_restartable( pk,
Hanno Becker5299cf82019-02-25 13:50:41 +00002441 sig_info->sig_md,
2442 sig_info->crt_hash, sig_info->crt_hash_len,
2443 sig_info->sig.p, sig_info->sig.len,
Hanno Beckere449e2d2019-02-25 14:45:31 +00002444 &rs_ctx->pk );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002445 }
Hanno Beckere449e2d2019-02-25 14:45:31 +00002446 else
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002447#endif
Hanno Beckere449e2d2019-02-25 14:45:31 +00002448 {
2449 ret = mbedtls_pk_verify_ext( sig_info->sig_pk,
2450 sig_info->sig_opts,
2451 pk,
2452 sig_info->sig_md,
2453 sig_info->crt_hash, sig_info->crt_hash_len,
2454 sig_info->sig.p, sig_info->sig.len );
2455 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002456
Hanno Beckere449e2d2019-02-25 14:45:31 +00002457exit:
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002458 mbedtls_x509_crt_pk_release( parent, pk );
Hanno Beckere449e2d2019-02-25 14:45:31 +00002459 return( ret );
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002460}
2461
2462/*
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002463 * Check if 'parent' is a suitable parent (signing CA) for 'child'.
2464 * Return 0 if yes, -1 if not.
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002465 *
2466 * top means parent is a locally-trusted certificate
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002467 */
Hanno Becker43bf9002019-02-25 14:46:49 +00002468static int x509_crt_check_parent( const mbedtls_x509_crt_sig_info *sig_info,
2469 const mbedtls_x509_crt_frame *parent,
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002470 int top )
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002471{
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002472 int need_ca_bit;
2473
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02002474 /* Parent must be the issuer */
Hanno Becker43bf9002019-02-25 14:46:49 +00002475 if( mbedtls_x509_name_cmp_raw( &sig_info->issuer_raw,
2476 &parent->subject_raw,
Hanno Becker67284cc2019-02-21 14:31:51 +00002477 NULL, NULL ) != 0 )
Hanno Becker7dee12a2019-02-21 13:58:38 +00002478 {
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002479 return( -1 );
Hanno Becker7dee12a2019-02-21 13:58:38 +00002480 }
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002481
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002482 /* Parent must have the basicConstraints CA bit set as a general rule */
2483 need_ca_bit = 1;
2484
2485 /* Exception: v1/v2 certificates that are locally trusted. */
2486 if( top && parent->version < 3 )
2487 need_ca_bit = 0;
2488
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002489 if( need_ca_bit && ! parent->ca_istrue )
2490 return( -1 );
2491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002493 if( need_ca_bit &&
Hanno Becker43bf9002019-02-25 14:46:49 +00002494 x509_crt_check_key_usage_frame( parent,
2495 MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02002496 {
2497 return( -1 );
2498 }
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002499#endif
2500
2501 return( 0 );
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002502}
2503
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002504/*
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002505 * Find a suitable parent for child in candidates, or return NULL.
2506 *
2507 * Here suitable is defined as:
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002508 * 1. subject name matches child's issuer
2509 * 2. if necessary, the CA bit is set and key usage allows signing certs
2510 * 3. for trusted roots, the signature is correct
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002511 * (for intermediates, the signature is checked and the result reported)
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002512 * 4. pathlen constraints are satisfied
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002513 *
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002514 * If there's a suitable candidate which is also time-valid, return the first
2515 * such. Otherwise, return the first suitable candidate (or NULL if there is
2516 * none).
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002517 *
2518 * The rationale for this rule is that someone could have a list of trusted
2519 * roots with two versions on the same root with different validity periods.
2520 * (At least one user reported having such a list and wanted it to just work.)
2521 * The reason we don't just require time-validity is that generally there is
2522 * only one version, and if it's expired we want the flags to state that
2523 * rather than NOT_TRUSTED, as would be the case if we required it here.
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002524 *
2525 * The rationale for rule 3 (signature for trusted roots) is that users might
2526 * have two versions of the same CA with different keys in their list, and the
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002527 * way we select the correct one is by checking the signature (as we don't
2528 * rely on key identifier extensions). (This is one way users might choose to
2529 * handle key rollover, another relies on self-issued certs, see [SIRO].)
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002530 *
2531 * Arguments:
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002532 * - [in] child: certificate for which we're looking for a parent
2533 * - [in] candidates: chained list of potential parents
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002534 * - [out] r_parent: parent found (or NULL)
2535 * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002536 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
2537 * of the chain, 0 otherwise
2538 * - [in] path_cnt: number of intermediates seen so far
2539 * - [in] self_cnt: number of self-signed intermediates seen so far
2540 * (will never be greater than path_cnt)
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002541 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002542 *
2543 * Return value:
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002544 * - 0 on success
2545 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002546 */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002547static int x509_crt_find_parent_in(
Hanno Becker5299cf82019-02-25 13:50:41 +00002548 mbedtls_x509_crt_sig_info const *child_sig,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002549 mbedtls_x509_crt *candidates,
2550 mbedtls_x509_crt **r_parent,
2551 int *r_signature_is_good,
2552 int top,
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002553 unsigned path_cnt,
2554 unsigned self_cnt,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002555 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002556{
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002557 int ret;
Hanno Becker43bf9002019-02-25 14:46:49 +00002558 mbedtls_x509_crt *parent_crt, *fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002559 int signature_is_good, fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002560
2561#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002562 /* did we have something in progress? */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002563 if( rs_ctx != NULL && rs_ctx->parent != NULL )
2564 {
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002565 /* restore saved state */
Hanno Becker43bf9002019-02-25 14:46:49 +00002566 parent_crt = rs_ctx->parent;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002567 fallback_parent = rs_ctx->fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002568 fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002569
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002570 /* clear saved state */
2571 rs_ctx->parent = NULL;
2572 rs_ctx->fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002573 rs_ctx->fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002574
2575 /* resume where we left */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002576 goto check_signature;
2577 }
2578#endif
2579
2580 fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002581 fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002582
Hanno Becker43bf9002019-02-25 14:46:49 +00002583 for( parent_crt = candidates; parent_crt != NULL;
2584 parent_crt = parent_crt->next )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002585 {
Hanno Beckera788cab2019-02-24 17:47:46 +00002586 int parent_valid, parent_match, path_len_ok;
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002587
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002588#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2589check_signature:
2590#endif
Hanno Beckera788cab2019-02-24 17:47:46 +00002591
2592 parent_valid = parent_match = path_len_ok = 0;
Hanno Beckera788cab2019-02-24 17:47:46 +00002593 {
Hanno Becker43bf9002019-02-25 14:46:49 +00002594 mbedtls_x509_crt_frame *parent;
Hanno Beckera788cab2019-02-24 17:47:46 +00002595
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002596 ret = mbedtls_x509_crt_frame_acquire( parent_crt, &parent );
Hanno Becker43bf9002019-02-25 14:46:49 +00002597 if( ret != 0 )
2598 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Hanno Beckera788cab2019-02-24 17:47:46 +00002599
Hanno Becker43bf9002019-02-25 14:46:49 +00002600 if( mbedtls_x509_time_is_past( &parent->valid_from ) &&
2601 mbedtls_x509_time_is_future( &parent->valid_to ) )
2602 {
2603 parent_valid = 1;
2604 }
2605
2606 /* basic parenting skills (name, CA bit, key usage) */
2607 if( x509_crt_check_parent( child_sig, parent, top ) == 0 )
2608 parent_match = 1;
2609
2610 /* +1 because the stored max_pathlen is 1 higher
2611 * than the actual value */
2612 if( !( parent->max_pathlen > 0 &&
2613 (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) )
2614 {
2615 path_len_ok = 1;
2616 }
2617
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002618 mbedtls_x509_crt_frame_release( parent_crt, parent );
Hanno Beckera788cab2019-02-24 17:47:46 +00002619 }
2620
2621 if( parent_match == 0 || path_len_ok == 0 )
2622 continue;
2623
2624 /* Signature */
Hanno Becker43bf9002019-02-25 14:46:49 +00002625 ret = x509_crt_check_signature( child_sig, parent_crt, rs_ctx );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002626
2627#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002628 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
2629 {
2630 /* save state */
Hanno Becker43bf9002019-02-25 14:46:49 +00002631 rs_ctx->parent = parent_crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002632 rs_ctx->fallback_parent = fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002633 rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002634
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002635 return( ret );
2636 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002637#else
2638 (void) ret;
2639#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002640
2641 signature_is_good = ret == 0;
2642 if( top && ! signature_is_good )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002643 continue;
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002644
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002645 /* optional time check */
Hanno Beckera788cab2019-02-24 17:47:46 +00002646 if( !parent_valid )
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002647 {
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002648 if( fallback_parent == NULL )
2649 {
Hanno Becker43bf9002019-02-25 14:46:49 +00002650 fallback_parent = parent_crt;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002651 fallback_signature_is_good = signature_is_good;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002652 }
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002653
2654 continue;
2655 }
2656
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002657 break;
2658 }
2659
Hanno Becker43bf9002019-02-25 14:46:49 +00002660 if( parent_crt != NULL )
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002661 {
Hanno Becker43bf9002019-02-25 14:46:49 +00002662 *r_parent = parent_crt;
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002663 *r_signature_is_good = signature_is_good;
2664 }
2665 else
2666 {
2667 *r_parent = fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002668 *r_signature_is_good = fallback_signature_is_good;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002669 }
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002670
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002671 return( 0 );
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002672}
2673
2674/*
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002675 * Find a parent in trusted CAs or the provided chain, or return NULL.
2676 *
2677 * Searches in trusted CAs first, and return the first suitable parent found
2678 * (see find_parent_in() for definition of suitable).
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002679 *
2680 * Arguments:
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002681 * - [in] child: certificate for which we're looking for a parent, followed
2682 * by a chain of possible intermediates
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002683 * - [in] trust_ca: list of locally trusted certificates
2684 * - [out] parent: parent found (or NULL)
2685 * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
2686 * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
2687 * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
2688 * - [in] self_cnt: number of self-signed certs in the chain so far
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002689 * (will always be no greater than path_cnt)
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002690 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002691 *
2692 * Return value:
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002693 * - 0 on success
2694 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002695 */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002696static int x509_crt_find_parent(
Hanno Becker5299cf82019-02-25 13:50:41 +00002697 mbedtls_x509_crt_sig_info const *child_sig,
Hanno Becker1e0677a2019-02-25 14:58:22 +00002698 mbedtls_x509_crt *rest,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002699 mbedtls_x509_crt *trust_ca,
2700 mbedtls_x509_crt **parent,
2701 int *parent_is_trusted,
2702 int *signature_is_good,
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002703 unsigned path_cnt,
2704 unsigned self_cnt,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002705 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002706{
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002707 int ret;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002708 mbedtls_x509_crt *search_list;
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002709
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002710 *parent_is_trusted = 1;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002711
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002712#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002713 /* restore then clear saved state if we have some stored */
2714 if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
2715 {
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002716 *parent_is_trusted = rs_ctx->parent_is_trusted;
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002717 rs_ctx->parent_is_trusted = -1;
2718 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002719#endif
2720
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002721 while( 1 ) {
Hanno Becker1e0677a2019-02-25 14:58:22 +00002722 search_list = *parent_is_trusted ? trust_ca : rest;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002723
Hanno Becker5299cf82019-02-25 13:50:41 +00002724 ret = x509_crt_find_parent_in( child_sig, search_list,
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002725 parent, signature_is_good,
2726 *parent_is_trusted,
2727 path_cnt, self_cnt, rs_ctx );
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002728
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002729#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002730 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
2731 {
2732 /* save state */
2733 rs_ctx->parent_is_trusted = *parent_is_trusted;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002734 return( ret );
2735 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002736#else
2737 (void) ret;
2738#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002739
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002740 /* stop here if found or already in second iteration */
2741 if( *parent != NULL || *parent_is_trusted == 0 )
2742 break;
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002743
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002744 /* prepare second iteration */
2745 *parent_is_trusted = 0;
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002746 }
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002747
2748 /* extra precaution against mistakes in the caller */
Krzysztof Stachowiakc388a8c2018-10-31 16:49:20 +01002749 if( *parent == NULL )
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002750 {
Manuel Pégourié-Gonnarda5a3e402018-10-16 11:27:23 +02002751 *parent_is_trusted = 0;
2752 *signature_is_good = 0;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002753 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002754
2755 return( 0 );
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002756}
2757
2758/*
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002759 * Check if an end-entity certificate is locally trusted
2760 *
2761 * Currently we require such certificates to be self-signed (actually only
2762 * check for self-issued as self-signatures are not checked)
2763 */
2764static int x509_crt_check_ee_locally_trusted(
Hanno Becker1e0677a2019-02-25 14:58:22 +00002765 mbedtls_x509_crt_frame const *crt,
2766 mbedtls_x509_crt const *trust_ca )
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002767{
Hanno Becker1e0677a2019-02-25 14:58:22 +00002768 mbedtls_x509_crt const *cur;
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002769
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002770 /* look for an exact match with trusted cert */
2771 for( cur = trust_ca; cur != NULL; cur = cur->next )
2772 {
2773 if( crt->raw.len == cur->raw.len &&
2774 memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
2775 {
2776 return( 0 );
2777 }
2778 }
2779
2780 /* too bad */
2781 return( -1 );
2782}
2783
2784/*
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002785 * Build and verify a certificate chain
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002786 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002787 * Given a peer-provided list of certificates EE, C1, ..., Cn and
2788 * a list of trusted certs R1, ... Rp, try to build and verify a chain
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002789 * EE, Ci1, ... Ciq [, Rj]
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002790 * such that every cert in the chain is a child of the next one,
2791 * jumping to a trusted root as early as possible.
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002792 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002793 * Verify that chain and return it with flags for all issues found.
2794 *
2795 * Special cases:
2796 * - EE == Rj -> return a one-element list containing it
2797 * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
2798 * -> return that chain with NOT_TRUSTED set on Ciq
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002799 *
Manuel Pégourié-Gonnardd19a41d2017-07-14 11:05:59 +02002800 * Tests for (aspects of) this function should include at least:
2801 * - trusted EE
2802 * - EE -> trusted root
2803 * - EE -> intermedate CA -> trusted root
2804 * - if relevant: EE untrusted
2805 * - if relevant: EE -> intermediate, untrusted
2806 * with the aspect under test checked at each relevant level (EE, int, root).
2807 * For some aspects longer chains are required, but usually length 2 is
2808 * enough (but length 1 is not in general).
2809 *
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002810 * Arguments:
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002811 * - [in] crt: the cert list EE, C1, ..., Cn
2812 * - [in] trust_ca: the trusted list R1, ..., Rp
2813 * - [in] ca_crl, profile: as in verify_with_profile()
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002814 * - [out] ver_chain: the built and verified chain
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02002815 * Only valid when return value is 0, may contain garbage otherwise!
2816 * Restart note: need not be the same when calling again to resume.
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002817 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002818 *
2819 * Return value:
2820 * - non-zero if the chain could not be fully built and examined
2821 * - 0 is the chain was successfully built and examined,
2822 * even if it was found to be invalid
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002823 */
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002824static int x509_crt_verify_chain(
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002825 mbedtls_x509_crt *crt,
2826 mbedtls_x509_crt *trust_ca,
2827 mbedtls_x509_crl *ca_crl,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002828 const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002829 mbedtls_x509_crt_verify_chain *ver_chain,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002830 mbedtls_x509_crt_restart_ctx *rs_ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002831{
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02002832 /* Don't initialize any of those variables here, so that the compiler can
2833 * catch potential issues with jumping ahead when restarting */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002834 int ret;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002835 uint32_t *flags;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002836 mbedtls_x509_crt_verify_chain_item *cur;
Hanno Becker1e0677a2019-02-25 14:58:22 +00002837 mbedtls_x509_crt *child_crt;
Hanno Becker58c35642019-02-25 18:13:46 +00002838 mbedtls_x509_crt *parent_crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002839 int parent_is_trusted;
2840 int child_is_trusted;
2841 int signature_is_good;
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002842 unsigned self_cnt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002843
2844#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2845 /* resume if we had an operation in progress */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002846 if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002847 {
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002848 /* restore saved state */
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02002849 *ver_chain = rs_ctx->ver_chain; /* struct copy */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002850 self_cnt = rs_ctx->self_cnt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002851
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002852 /* restore derived state */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002853 cur = &ver_chain->items[ver_chain->len - 1];
Hanno Becker1e0677a2019-02-25 14:58:22 +00002854 child_crt = cur->crt;
2855
2856 child_is_trusted = 0;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002857 goto find_parent;
2858 }
2859#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02002860
Hanno Becker1e0677a2019-02-25 14:58:22 +00002861 child_crt = crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002862 self_cnt = 0;
2863 parent_is_trusted = 0;
2864 child_is_trusted = 0;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002865
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002866 while( 1 ) {
Hanno Becker5299cf82019-02-25 13:50:41 +00002867#if defined(MBEDTLS_X509_CRL_PARSE_C)
2868 mbedtls_x509_buf_raw child_serial;
2869#endif /* MBEDTLS_X509_CRL_PARSE_C */
2870 int self_issued;
Hanno Becker1e0677a2019-02-25 14:58:22 +00002871
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002872 /* Add certificate to the verification chain */
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002873 cur = &ver_chain->items[ver_chain->len];
Hanno Becker1e0677a2019-02-25 14:58:22 +00002874 cur->crt = child_crt;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002875 cur->flags = 0;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002876 ver_chain->len++;
Hanno Becker10e6b9b2019-02-22 17:56:43 +00002877
2878#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2879find_parent:
2880#endif
2881
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002882 flags = &cur->flags;
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02002883
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002884 {
Hanno Becker5299cf82019-02-25 13:50:41 +00002885 mbedtls_x509_crt_sig_info child_sig;
2886 {
2887 mbedtls_x509_crt_frame *child;
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02002888
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002889 ret = mbedtls_x509_crt_frame_acquire( child_crt, &child );
Hanno Becker5299cf82019-02-25 13:50:41 +00002890 if( ret != 0 )
2891 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2892
2893 /* Check time-validity (all certificates) */
2894 if( mbedtls_x509_time_is_past( &child->valid_to ) )
2895 *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
2896 if( mbedtls_x509_time_is_future( &child->valid_from ) )
2897 *flags |= MBEDTLS_X509_BADCERT_FUTURE;
2898
2899 /* Stop here for trusted roots (but not for trusted EE certs) */
2900 if( child_is_trusted )
2901 {
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002902 mbedtls_x509_crt_frame_release( child_crt, child );
Hanno Becker5299cf82019-02-25 13:50:41 +00002903 return( 0 );
2904 }
2905
2906 self_issued = 0;
2907 if( mbedtls_x509_name_cmp_raw( &child->issuer_raw,
2908 &child->subject_raw,
2909 NULL, NULL ) == 0 )
2910 {
2911 self_issued = 1;
2912 }
2913
2914 /* Check signature algorithm: MD & PK algs */
2915 if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
2916 *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
2917
2918 if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
2919 *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
2920
2921 /* Special case: EE certs that are locally trusted */
2922 if( ver_chain->len == 1 && self_issued &&
2923 x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
2924 {
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002925 mbedtls_x509_crt_frame_release( child_crt, child );
Hanno Becker5299cf82019-02-25 13:50:41 +00002926 return( 0 );
2927 }
2928
2929#if defined(MBEDTLS_X509_CRL_PARSE_C)
2930 child_serial = child->serial;
2931#endif /* MBEDTLS_X509_CRL_PARSE_C */
2932
2933 ret = x509_crt_get_sig_info( child, &child_sig );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002934 mbedtls_x509_crt_frame_release( child_crt, child );
Hanno Becker5299cf82019-02-25 13:50:41 +00002935
Hanno Becker5299cf82019-02-25 13:50:41 +00002936 if( ret != 0 )
2937 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2938 }
2939
2940 /* Look for a parent in trusted CAs or up the chain */
2941 ret = x509_crt_find_parent( &child_sig, child_crt->next,
Hanno Becker58c35642019-02-25 18:13:46 +00002942 trust_ca, &parent_crt,
Hanno Becker5299cf82019-02-25 13:50:41 +00002943 &parent_is_trusted, &signature_is_good,
2944 ver_chain->len - 1, self_cnt, rs_ctx );
2945
2946 x509_crt_free_sig_info( &child_sig );
2947 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002948
2949#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002950 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
2951 {
2952 /* save state */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002953 rs_ctx->in_progress = x509_crt_rs_find_parent;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002954 rs_ctx->self_cnt = self_cnt;
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02002955 rs_ctx->ver_chain = *ver_chain; /* struct copy */
Hanno Becker5299cf82019-02-25 13:50:41 +00002956 return( ret );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002957 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002958#else
2959 (void) ret;
2960#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002961
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002962 /* No parent? We're done here */
Hanno Becker58c35642019-02-25 18:13:46 +00002963 if( parent_crt == NULL )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002964 {
2965 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
Hanno Becker5299cf82019-02-25 13:50:41 +00002966 return( 0 );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002967 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002968
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002969 /* Count intermediate self-issued (not necessarily self-signed) certs.
2970 * These can occur with some strategies for key rollover, see [SIRO],
2971 * and should be excluded from max_pathlen checks. */
Hanno Becker5299cf82019-02-25 13:50:41 +00002972 if( ver_chain->len != 1 && self_issued )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002973 self_cnt++;
Manuel Pégourié-Gonnardfd6c85c2014-11-20 16:34:20 +01002974
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002975 /* path_cnt is 0 for the first intermediate CA,
2976 * and if parent is trusted it's not an intermediate CA */
2977 if( ! parent_is_trusted &&
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002978 ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002979 {
2980 /* return immediately to avoid overflow the chain array */
Hanno Becker5299cf82019-02-25 13:50:41 +00002981 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002982 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002983
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002984 /* signature was checked while searching parent */
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002985 if( ! signature_is_good )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002986 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
2987
Hanno Becker58c35642019-02-25 18:13:46 +00002988 {
2989 mbedtls_pk_context *parent_pk;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002990 ret = mbedtls_x509_crt_pk_acquire( parent_crt, &parent_pk );
Hanno Becker58c35642019-02-25 18:13:46 +00002991 if( ret != 0 )
2992 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2993
2994 /* check size of signing key */
2995 if( x509_profile_check_key( profile, parent_pk ) != 0 )
2996 *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
2997
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002998 mbedtls_x509_crt_pk_release( parent_crt, parent_pk );
Hanno Becker58c35642019-02-25 18:13:46 +00002999 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003000
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003001#if defined(MBEDTLS_X509_CRL_PARSE_C)
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003002 /* Check trusted CA's CRL for the given crt */
Hanno Becker5299cf82019-02-25 13:50:41 +00003003 *flags |= x509_crt_verifycrl( child_serial.p,
3004 child_serial.len,
Hanno Becker58c35642019-02-25 18:13:46 +00003005 parent_crt, ca_crl, profile );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003006#else
3007 (void) ca_crl;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003008#endif
3009
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003010 /* prepare for next iteration */
Hanno Becker58c35642019-02-25 18:13:46 +00003011 child_crt = parent_crt;
3012 parent_crt = NULL;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003013 child_is_trusted = parent_is_trusted;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02003014 signature_is_good = 0;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003015 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003016}
3017
3018/*
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003019 * Check for CN match
3020 */
Hanno Becker24926222019-02-21 13:10:55 +00003021static int x509_crt_check_cn( unsigned char const *buf,
3022 size_t buflen,
3023 const char *cn,
3024 size_t cn_len )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003025{
Hanno Becker24926222019-02-21 13:10:55 +00003026 /* Try exact match */
Hanno Beckerb3def1d2019-02-22 11:46:06 +00003027 if( mbedtls_x509_memcasecmp( cn, buf, buflen, cn_len ) == 0 )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003028 return( 0 );
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003029
3030 /* try wildcard match */
Hanno Becker24926222019-02-21 13:10:55 +00003031 if( x509_check_wildcard( cn, cn_len, buf, buflen ) == 0 )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003032 {
3033 return( 0 );
3034 }
3035
3036 return( -1 );
3037}
3038
Hanno Becker8b543b32019-02-21 11:50:44 +00003039/* Returns 1 on a match and 0 on a mismatch.
3040 * This is because this function is used as a callback for
3041 * mbedtls_x509_name_cmp_raw(), which continues the name
3042 * traversal as long as the callback returns 0. */
3043static int x509_crt_check_name( void *ctx,
3044 mbedtls_x509_buf *oid,
Hanno Becker6b378122019-02-23 10:20:14 +00003045 mbedtls_x509_buf *val,
3046 int next_merged )
Hanno Becker8b543b32019-02-21 11:50:44 +00003047{
3048 char const *cn = (char const*) ctx;
3049 size_t cn_len = strlen( cn );
Hanno Becker6b378122019-02-23 10:20:14 +00003050 ((void) next_merged);
Hanno Becker8b543b32019-02-21 11:50:44 +00003051
3052 if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, oid ) == 0 &&
Hanno Becker24926222019-02-21 13:10:55 +00003053 x509_crt_check_cn( val->p, val->len, cn, cn_len ) == 0 )
Hanno Becker8b543b32019-02-21 11:50:44 +00003054 {
3055 return( 1 );
3056 }
3057
3058 return( 0 );
3059}
3060
Hanno Beckerda410822019-02-21 13:36:59 +00003061/* Returns 1 on a match and 0 on a mismatch.
3062 * This is because this function is used as a callback for
3063 * mbedtls_asn1_traverse_sequence_of(), which continues the
3064 * traversal as long as the callback returns 0. */
3065static int x509_crt_subject_alt_check_name( void *ctx,
3066 int tag,
3067 unsigned char *data,
3068 size_t data_len )
3069{
3070 char const *cn = (char const*) ctx;
3071 size_t cn_len = strlen( cn );
Hanno Becker90b94082019-02-21 21:13:21 +00003072 ((void) tag);
Hanno Beckerda410822019-02-21 13:36:59 +00003073
3074 if( x509_crt_check_cn( data, data_len, cn, cn_len ) == 0 )
3075 return( 1 );
3076
3077 return( 0 );
3078}
3079
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003080/*
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003081 * Verify the requested CN - only call this if cn is not NULL!
3082 */
Hanno Becker082435c2019-02-25 18:14:40 +00003083static int x509_crt_verify_name( const mbedtls_x509_crt *crt,
3084 const char *cn,
3085 uint32_t *flags )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003086{
Hanno Beckerda410822019-02-21 13:36:59 +00003087 int ret;
Hanno Becker082435c2019-02-25 18:14:40 +00003088 mbedtls_x509_crt_frame *frame;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003089
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003090 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Becker082435c2019-02-25 18:14:40 +00003091 if( ret != 0 )
3092 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3093
3094 if( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003095 {
Hanno Becker90b94082019-02-21 21:13:21 +00003096 unsigned char *p =
Hanno Becker082435c2019-02-25 18:14:40 +00003097 frame->subject_alt_raw.p;
Hanno Beckerda410822019-02-21 13:36:59 +00003098 const unsigned char *end =
Hanno Becker082435c2019-02-25 18:14:40 +00003099 frame->subject_alt_raw.p + frame->subject_alt_raw.len;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003100
Hanno Becker90b94082019-02-21 21:13:21 +00003101 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
3102 MBEDTLS_ASN1_TAG_CLASS_MASK,
3103 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
3104 MBEDTLS_ASN1_TAG_VALUE_MASK,
3105 2 /* SubjectAlt DNS */,
3106 x509_crt_subject_alt_check_name,
3107 (void*) cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003108 }
3109 else
3110 {
Hanno Becker082435c2019-02-25 18:14:40 +00003111 ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
3112 &frame->subject_raw,
Hanno Becker8b543b32019-02-21 11:50:44 +00003113 x509_crt_check_name, (void*) cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003114 }
Hanno Beckerda410822019-02-21 13:36:59 +00003115
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003116 mbedtls_x509_crt_frame_release( crt, frame );
Hanno Becker082435c2019-02-25 18:14:40 +00003117
3118 /* x509_crt_check_name() and x509_crt_subject_alt_check_name()
3119 * return 1 when finding a name component matching `cn`. */
3120 if( ret == 1 )
3121 return( 0 );
3122
3123 if( ret != 0 )
3124 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
3125
3126 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
3127 return( ret );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003128}
3129
3130/*
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003131 * Merge the flags for all certs in the chain, after calling callback
3132 */
3133static int x509_crt_merge_flags_with_cb(
3134 uint32_t *flags,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003135 const mbedtls_x509_crt_verify_chain *ver_chain,
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003136 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3137 void *p_vrfy )
3138{
3139 int ret;
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02003140 unsigned i;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003141 uint32_t cur_flags;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003142 const mbedtls_x509_crt_verify_chain_item *cur;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003143
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003144 for( i = ver_chain->len; i != 0; --i )
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003145 {
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003146 cur = &ver_chain->items[i-1];
3147 cur_flags = cur->flags;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003148
3149 if( NULL != f_vrfy )
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02003150 if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003151 return( ret );
3152
3153 *flags |= cur_flags;
3154 }
3155
3156 return( 0 );
3157}
3158
3159/*
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003160 * Verify the certificate validity (default profile, not restartable)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003161 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003162int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
3163 mbedtls_x509_crt *trust_ca,
3164 mbedtls_x509_crl *ca_crl,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02003165 const char *cn, uint32_t *flags,
3166 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
Paul Bakkerddf26b42013-09-18 13:46:23 +02003167 void *p_vrfy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003168{
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003169 return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
3170 &mbedtls_x509_crt_profile_default, cn, flags,
3171 f_vrfy, p_vrfy, NULL ) );
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003172}
3173
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003174/*
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003175 * Verify the certificate validity (user-chosen profile, not restartable)
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003176 */
3177int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
3178 mbedtls_x509_crt *trust_ca,
3179 mbedtls_x509_crl *ca_crl,
3180 const mbedtls_x509_crt_profile *profile,
3181 const char *cn, uint32_t *flags,
3182 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3183 void *p_vrfy )
3184{
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003185 return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
3186 profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
3187}
3188
3189/*
3190 * Verify the certificate validity, with profile, restartable version
3191 *
3192 * This function:
3193 * - checks the requested CN (if any)
3194 * - checks the type and size of the EE cert's key,
3195 * as that isn't done as part of chain building/verification currently
3196 * - builds and verifies the chain
3197 * - then calls the callback and merges the flags
3198 */
3199int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
3200 mbedtls_x509_crt *trust_ca,
3201 mbedtls_x509_crl *ca_crl,
3202 const mbedtls_x509_crt_profile *profile,
3203 const char *cn, uint32_t *flags,
3204 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3205 void *p_vrfy,
3206 mbedtls_x509_crt_restart_ctx *rs_ctx )
3207{
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003208 int ret;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003209 mbedtls_x509_crt_verify_chain ver_chain;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003210 uint32_t ee_flags;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003211
3212 *flags = 0;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003213 ee_flags = 0;
3214 x509_crt_verify_chain_reset( &ver_chain );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003215
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003216 if( profile == NULL )
3217 {
3218 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
3219 goto exit;
3220 }
3221
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003222 /* check name if requested */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003223 if( cn != NULL )
Hanno Becker87233362019-02-25 18:15:33 +00003224 {
3225 ret = x509_crt_verify_name( crt, cn, &ee_flags );
3226 if( ret != 0 )
3227 return( ret );
3228 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003229
Hanno Becker87233362019-02-25 18:15:33 +00003230 {
3231 mbedtls_pk_context *pk;
3232 mbedtls_pk_type_t pk_type;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003233
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003234 ret = mbedtls_x509_crt_pk_acquire( crt, &pk );
Hanno Becker87233362019-02-25 18:15:33 +00003235 if( ret != 0 )
3236 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003237
Hanno Becker87233362019-02-25 18:15:33 +00003238 /* Check the type and size of the key */
3239 pk_type = mbedtls_pk_get_type( pk );
3240
3241 if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
3242 ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
3243
3244 if( x509_profile_check_key( profile, pk ) != 0 )
3245 ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
3246
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003247 mbedtls_x509_crt_pk_release( crt, pk );
Hanno Becker87233362019-02-25 18:15:33 +00003248 }
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003249
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003250 /* Check the chain */
Manuel Pégourié-Gonnard505c3952017-07-05 17:36:47 +02003251 ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003252 &ver_chain, rs_ctx );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003253
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02003254 if( ret != 0 )
3255 goto exit;
3256
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003257 /* Merge end-entity flags */
3258 ver_chain.items[0].flags |= ee_flags;
3259
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003260 /* Build final flags, calling callback on the way if any */
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003261 ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003262
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003263exit:
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003264#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3265 if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
3266 mbedtls_x509_crt_restart_free( rs_ctx );
3267#endif
3268
Manuel Pégourié-Gonnard9107b5f2017-07-06 12:16:25 +02003269 /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
3270 * the SSL module for authmode optional, but non-zero return from the
3271 * callback means a fatal error so it shouldn't be ignored */
Manuel Pégourié-Gonnard31458a12017-06-26 10:11:49 +02003272 if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
3273 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
3274
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003275 if( ret != 0 )
3276 {
3277 *flags = (uint32_t) -1;
3278 return( ret );
3279 }
3280
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003281 if( *flags != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003282 return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003283
3284 return( 0 );
3285}
3286
3287/*
Paul Bakker369d2eb2013-09-18 11:58:25 +02003288 * Initialize a certificate chain
3289 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003290void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
Paul Bakker369d2eb2013-09-18 11:58:25 +02003291{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003292 memset( crt, 0, sizeof(mbedtls_x509_crt) );
Paul Bakker369d2eb2013-09-18 11:58:25 +02003293}
3294
3295/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003296 * Unallocate all certificate data
3297 */
Hanno Beckercd03bb22019-02-15 17:15:53 +00003298
3299static void x509_free_sequence( mbedtls_x509_sequence *seq )
3300{
3301 while( seq != NULL )
3302 {
3303 mbedtls_x509_sequence *next = seq->next;
3304 mbedtls_platform_zeroize( seq, sizeof( *seq ) );
3305 mbedtls_free( seq );
3306 seq = next;
3307 }
3308}
3309
3310static void x509_free_name( mbedtls_x509_name *name )
3311{
3312 while( name != NULL )
3313 {
3314 mbedtls_x509_name *next = name->next;
3315 mbedtls_platform_zeroize( name, sizeof( *name ) );
3316 mbedtls_free( name );
3317 name = next;
3318 }
3319}
3320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003321void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003322{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003323 mbedtls_x509_crt *cert_cur = crt;
3324 mbedtls_x509_crt *cert_prv;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003325
3326 if( crt == NULL )
3327 return;
3328
3329 do
3330 {
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003331 x509_crt_cache_free( cert_cur->cache );
3332 mbedtls_free( cert_cur->cache );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003333 mbedtls_pk_free( &cert_cur->pk );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003335#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
3336 mbedtls_free( cert_cur->sig_opts );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +02003337#endif
3338
Hanno Beckercd03bb22019-02-15 17:15:53 +00003339 x509_free_name( cert_cur->issuer.next );
3340 x509_free_name( cert_cur->subject.next );
3341 x509_free_sequence( cert_cur->ext_key_usage.next );
3342 x509_free_sequence( cert_cur->subject_alt_names.next );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003343
Hanno Beckeraa8665a2019-01-31 08:57:44 +00003344 if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003345 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05003346 mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003347 mbedtls_free( cert_cur->raw.p );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003348 }
3349
3350 cert_cur = cert_cur->next;
3351 }
3352 while( cert_cur != NULL );
3353
3354 cert_cur = crt;
3355 do
3356 {
3357 cert_prv = cert_cur;
3358 cert_cur = cert_cur->next;
3359
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05003360 mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003361 if( cert_prv != crt )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003362 mbedtls_free( cert_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003363 }
3364 while( cert_cur != NULL );
3365}
3366
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003367#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3368/*
3369 * Initialize a restart context
3370 */
3371void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
3372{
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02003373 mbedtls_pk_restart_init( &ctx->pk );
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003374
3375 ctx->parent = NULL;
3376 ctx->fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02003377 ctx->fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003378
3379 ctx->parent_is_trusted = -1;
3380
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003381 ctx->in_progress = x509_crt_rs_none;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003382 ctx->self_cnt = 0;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003383 x509_crt_verify_chain_reset( &ctx->ver_chain );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003384}
3385
3386/*
3387 * Free the components of a restart context
3388 */
3389void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
3390{
3391 if( ctx == NULL )
3392 return;
3393
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02003394 mbedtls_pk_restart_free( &ctx->pk );
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003395 mbedtls_x509_crt_restart_init( ctx );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003396}
3397#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
3398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003399#endif /* MBEDTLS_X509_CRT_PARSE_C */