blob: fb5265a7fe3c822055919257017858ec2a8658ec [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 Beckerea32d8b2019-03-04 11:52:23 +000093static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +000094int mbedtls_x509_crt_cache_provide_frame( mbedtls_x509_crt const *crt )
Hanno Becker337088a2019-02-25 14:53:14 +000095{
Hanno Beckerb6c39fc2019-02-25 13:50:14 +000096 mbedtls_x509_crt_cache *cache = crt->cache;
Hanno Becker337088a2019-02-25 14:53:14 +000097 mbedtls_x509_crt_frame *frame;
98
99 frame = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_frame ) );
100 if( frame == NULL )
101 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000102 cache->frame = frame;
Hanno Becker337088a2019-02-25 14:53:14 +0000103
Hanno Beckerea32d8b2019-03-04 11:52:23 +0000104#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
105 /* This would work with !MBEDTLS_X509_ON_DEMAND_PARSING, too,
106 * but is inefficient compared to copying the respective fields
107 * from the legacy mbedtls_x509_crt. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000108 return( x509_crt_parse_frame( crt->raw.p,
109 crt->raw.p + crt->raw.len,
110 frame ) );
Hanno Beckerea32d8b2019-03-04 11:52:23 +0000111#else /* MBEDTLS_X509_ON_DEMAND_PARSING */
112 /* Make sure all extension related fields are properly initialized. */
113 frame->ca_istrue = 0;
114 frame->max_pathlen = 0;
115 frame->ext_types = 0;
116 frame->version = crt->version;
117 frame->sig_md = crt->sig_md;
118 frame->sig_pk = crt->sig_pk;
119 frame->valid_from = crt->valid_from;
120 frame->valid_to = crt->valid_to;
121 frame->raw.p = crt->raw.p;
122 frame->raw.len = crt->raw.len;
123 frame->tbs.p = crt->tbs.p;
124 frame->tbs.len = crt->tbs.len;
125 frame->serial.p = crt->serial.p;
126 frame->serial.len = crt->serial.len;
127 frame->pubkey_raw.p = crt->pk_raw.p;
128 frame->pubkey_raw.len = crt->pk_raw.len;
129 frame->issuer_raw = crt->issuer_raw_no_hdr;
130 frame->subject_raw = crt->subject_raw_no_hdr;
131 frame->issuer_id.p = crt->issuer_id.p;
132 frame->issuer_id.len = crt->issuer_id.len;
133 frame->subject_id.p = crt->subject_id.p;
134 frame->subject_id.len = crt->subject_id.len;
135 frame->sig.p = crt->sig.p;
136 frame->sig.len = crt->sig.len;
137 frame->v3_ext.p = crt->v3_ext.p;
138 frame->v3_ext.len = crt->v3_ext.len;
Hanno Beckerea32d8b2019-03-04 11:52:23 +0000139 frame->issuer_raw_with_hdr.p = crt->issuer_raw.p;
140 frame->issuer_raw_with_hdr.len = crt->issuer_raw.len;
141 frame->subject_raw_with_hdr.p = crt->subject_raw.p;
142 frame->subject_raw_with_hdr.len = crt->subject_raw.len;
143
144 /* The legacy CRT structure doesn't explicitly contain
145 * the `AlgorithmIdentifier` bounds; however, those can
146 * be inferred from the surrounding (mandatory) `SerialNumber`
147 * and `Issuer` fields. */
148 frame->sig_alg.p = crt->serial.p + crt->serial.len;
149 frame->sig_alg.len = crt->issuer_raw.p - frame->sig_alg.p;
150
151 return( x509_crt_frame_parse_ext( frame ) );
152#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000153}
Hanno Becker337088a2019-02-25 14:53:14 +0000154
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000155int mbedtls_x509_crt_cache_provide_pk( mbedtls_x509_crt const *crt )
156{
157 mbedtls_x509_crt_cache *cache = crt->cache;
158 mbedtls_pk_context *pk;
159
160 pk = mbedtls_calloc( 1, sizeof( mbedtls_pk_context ) );
161 if( pk == NULL )
162 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000163 cache->pk = pk;
Hanno Becker180f7bf2019-02-28 13:23:38 +0000164
165#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
166 *pk = crt->pk;
Hanno Becker337088a2019-02-25 14:53:14 +0000167 return( 0 );
Hanno Becker180f7bf2019-02-28 13:23:38 +0000168#else
169 {
170 mbedtls_x509_buf_raw pk_raw = cache->pk_raw;
171 return( mbedtls_pk_parse_subpubkey( &pk_raw.p,
172 pk_raw.p + pk_raw.len,
173 pk ) );
174 }
175#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Becker337088a2019-02-25 14:53:14 +0000176}
177
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000178static void x509_crt_cache_init( mbedtls_x509_crt_cache *cache )
Hanno Becker337088a2019-02-25 14:53:14 +0000179{
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000180 memset( cache, 0, sizeof( *cache ) );
181#if defined(MBEDTLS_THREADING_C)
182 mbedtls_mutex_init( &cache->frame_mutex );
183 mbedtls_mutex_init( &cache->pk_mutex );
184#endif
185}
186
187static void x509_crt_cache_clear_pk( mbedtls_x509_crt_cache *cache )
188{
Hanno Becker180f7bf2019-02-28 13:23:38 +0000189#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000190 /* The cache holds a shallow copy of the PK context
191 * in the legacy struct, so don't free PK context. */
192 mbedtls_free( cache->pk );
Hanno Becker180f7bf2019-02-28 13:23:38 +0000193#else
194 mbedtls_pk_free( cache->pk );
195 mbedtls_free( cache->pk );
196#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
197
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000198 cache->pk = NULL;
199}
200
201static void x509_crt_cache_clear_frame( mbedtls_x509_crt_cache *cache )
202{
203 mbedtls_free( cache->frame );
204 cache->frame = NULL;
205}
206
207static void x509_crt_cache_free( mbedtls_x509_crt_cache *cache )
208{
209 if( cache == NULL )
Hanno Becker337088a2019-02-25 14:53:14 +0000210 return;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000211
212#if defined(MBEDTLS_THREADING_C)
213 mbedtls_mutex_free( &cache->frame_mutex );
214 mbedtls_mutex_free( &cache->pk_mutex );
215#endif
216
217 x509_crt_cache_clear_frame( cache );
218 x509_crt_cache_clear_pk( cache );
219
220 memset( cache, 0, sizeof( *cache ) );
Hanno Becker337088a2019-02-25 14:53:14 +0000221}
222
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000223int mbedtls_x509_crt_flush_cache( mbedtls_x509_crt const *crt )
Hanno Becker337088a2019-02-25 14:53:14 +0000224{
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000225#if defined(MBEDTLS_THREADING_C)
226 if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
227 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
228 if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
229 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
230#endif
231 x509_crt_cache_clear_frame( crt->cache );
232 x509_crt_cache_clear_pk( crt->cache );
233#if defined(MBEDTLS_THREADING_C)
234 if( mbedtls_mutex_unlock( &crt->cache->frame_mutex ) != 0 )
235 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
236 if( mbedtls_mutex_unlock( &crt->cache->pk_mutex ) != 0 )
237 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
238#endif
239 return( 0 );
Hanno Becker337088a2019-02-25 14:53:14 +0000240}
241
Hanno Beckerab6c8ea2019-02-27 17:33:14 +0000242int mbedtls_x509_crt_get_subject_alt_names( mbedtls_x509_crt const *crt,
243 mbedtls_x509_sequence **subj_alt )
244{
245 int ret;
246 mbedtls_x509_crt_frame *frame;
247 mbedtls_x509_sequence *seq;
248
249 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
250 if( ret != 0 )
251 return( ret );
252
253 seq = mbedtls_calloc( 1, sizeof( mbedtls_x509_sequence ) );
254 if( seq == NULL )
255 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
256 else
257 ret = x509_crt_subject_alt_from_frame( frame, seq );
258
259 mbedtls_x509_crt_frame_release( crt, frame );
260
261 *subj_alt = seq;
262 return( ret );
263}
264
265int mbedtls_x509_crt_get_ext_key_usage( mbedtls_x509_crt const *crt,
266 mbedtls_x509_sequence **ext_key_usage )
267{
268 int ret;
269 mbedtls_x509_crt_frame *frame;
270 mbedtls_x509_sequence *seq;
271
272 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
273 if( ret != 0 )
274 return( ret );
275
276 seq = mbedtls_calloc( 1, sizeof( mbedtls_x509_sequence ) );
277 if( seq == NULL )
278 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
279 else
280 ret = x509_crt_ext_key_usage_from_frame( frame, seq );
281
282 mbedtls_x509_crt_frame_release( crt, frame );
283
284 *ext_key_usage = seq;
285 return( ret );
286}
287
Hanno Becker63e69982019-02-26 18:50:49 +0000288int mbedtls_x509_crt_get_subject( mbedtls_x509_crt const *crt,
289 mbedtls_x509_name **subject )
290{
291 int ret;
292 mbedtls_x509_crt_frame *frame;
293 mbedtls_x509_name *name;
294
295 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
296 if( ret != 0 )
297 return( ret );
298
299 name = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
300 if( name == NULL )
301 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
302 else
303 ret = x509_crt_subject_from_frame( frame, name );
304
305 mbedtls_x509_crt_frame_release( crt, frame );
306
307 *subject = name;
308 return( ret );
309}
310
311int mbedtls_x509_crt_get_issuer( mbedtls_x509_crt const *crt,
312 mbedtls_x509_name **issuer )
313{
314 int ret;
315 mbedtls_x509_crt_frame *frame;
316 mbedtls_x509_name *name;
317
318 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
319 if( ret != 0 )
320 return( ret );
321
322 name = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
323 if( name == NULL )
324 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
325 else
326 ret = x509_crt_issuer_from_frame( frame, name );
327
328 mbedtls_x509_crt_frame_release( crt, frame );
329
330 *issuer = name;
331 return( ret );
332}
333
Hanno Becker823efad2019-02-28 13:23:58 +0000334int mbedtls_x509_crt_get_frame( mbedtls_x509_crt const *crt,
335 mbedtls_x509_crt_frame *dst )
336{
337 int ret;
338 mbedtls_x509_crt_frame *frame;
339 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
340 if( ret != 0 )
341 return( ret );
342 *dst = *frame;
343 mbedtls_x509_crt_frame_release( crt, frame );
344 return( 0 );
345}
346
347int mbedtls_x509_crt_get_pk( mbedtls_x509_crt const *crt,
348 mbedtls_pk_context *dst )
349{
350#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
351 mbedtls_x509_buf_raw pk_raw = crt->cache->pk_raw;
352 return( mbedtls_pk_parse_subpubkey( &pk_raw.p,
353 pk_raw.p + pk_raw.len,
354 dst ) );
355#else /* !MBEDTLS_X509_ON_DEMAND_PARSING */
356 int ret;
357 mbedtls_pk_context *pk;
358 ret = mbedtls_x509_crt_pk_acquire( crt, &pk );
359 if( ret != 0 )
360 return( ret );
361
362 /* Move PK from CRT cache to destination pointer
363 * to avoid a copy. */
364 *dst = *pk;
365 mbedtls_free( crt->cache->pk );
366 crt->cache->pk = NULL;
367
368 mbedtls_x509_crt_pk_release( crt, pk );
369 return( 0 );
370#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
371}
372
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +0200373/*
374 * Item in a verification chain: cert and flags for it
375 */
376typedef struct {
377 mbedtls_x509_crt *crt;
378 uint32_t flags;
379} x509_crt_verify_chain_item;
380
381/*
382 * Max size of verification chain: end-entity + intermediates + trusted root
383 */
384#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
Paul Bakker34617722014-06-13 17:20:13 +0200385
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200386/*
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200387 * Default profile
388 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200389const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
390{
Gilles Peskine5d2511c2017-05-12 13:16:40 +0200391#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200392 /* Allow SHA-1 (weak, but still safe in controlled environments) */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200393 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200394#endif
395 /* Only SHA-2 hashes */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200396 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
397 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
398 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
399 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
400 0xFFFFFFF, /* Any PK alg */
401 0xFFFFFFF, /* Any curve */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200402 2048,
403};
404
405/*
406 * Next-default profile
407 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200408const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
409{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200410 /* Hashes from SHA-256 and above */
411 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
412 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
413 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
414 0xFFFFFFF, /* Any PK alg */
415#if defined(MBEDTLS_ECP_C)
416 /* Curves at or above 128-bit security level */
417 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
418 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
419 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
420 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
421 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
422 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
423 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
424#else
425 0,
426#endif
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200427 2048,
428};
429
430/*
431 * NSA Suite B Profile
432 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200433const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
434{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200435 /* Only SHA-256 and 384 */
436 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
437 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
438 /* Only ECDSA */
Ron Eldor85e1dcf2018-02-06 15:59:38 +0200439 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
440 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200441#if defined(MBEDTLS_ECP_C)
442 /* Only NIST P-256 and P-384 */
443 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
444 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
445#else
446 0,
447#endif
448 0,
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200449};
450
451/*
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200452 * Check md_alg against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200453 * Return 0 if md_alg is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200454 */
455static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
456 mbedtls_md_type_t md_alg )
457{
Philippe Antoineb5b25432018-05-11 11:06:29 +0200458 if( md_alg == MBEDTLS_MD_NONE )
459 return( -1 );
460
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200461 if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
462 return( 0 );
463
464 return( -1 );
465}
466
467/*
468 * Check pk_alg against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200469 * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200470 */
471static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
472 mbedtls_pk_type_t pk_alg )
473{
Philippe Antoineb5b25432018-05-11 11:06:29 +0200474 if( pk_alg == MBEDTLS_PK_NONE )
475 return( -1 );
476
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200477 if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
478 return( 0 );
479
480 return( -1 );
481}
482
483/*
484 * Check key against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200485 * Return 0 if pk is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200486 */
487static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200488 const mbedtls_pk_context *pk )
489{
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200490 const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk );
Manuel Pégourié-Gonnard19773ff2017-10-24 10:51:26 +0200491
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200492#if defined(MBEDTLS_RSA_C)
493 if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
494 {
Manuel Pégourié-Gonnard097c7bb2015-06-18 16:43:38 +0200495 if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200496 return( 0 );
497
498 return( -1 );
499 }
500#endif
501
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +0200502#if defined(MBEDTLS_ECP_C)
503 if( pk_alg == MBEDTLS_PK_ECDSA ||
504 pk_alg == MBEDTLS_PK_ECKEY ||
505 pk_alg == MBEDTLS_PK_ECKEY_DH )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200506 {
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200507 const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200508
Philippe Antoineb5b25432018-05-11 11:06:29 +0200509 if( gid == MBEDTLS_ECP_DP_NONE )
510 return( -1 );
511
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200512 if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
513 return( 0 );
514
515 return( -1 );
516 }
517#endif
518
519 return( -1 );
520}
521
522/*
Hanno Becker1f8527f2018-11-02 09:19:16 +0000523 * Return 0 if name matches wildcard, -1 otherwise
524 */
Hanno Becker24926222019-02-21 13:10:55 +0000525static int x509_check_wildcard( char const *cn,
526 size_t cn_len,
527 unsigned char const *buf,
528 size_t buf_len )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000529{
530 size_t i;
Hanno Becker24926222019-02-21 13:10:55 +0000531 size_t cn_idx = 0;
Hanno Becker1f8527f2018-11-02 09:19:16 +0000532
533 /* We can't have a match if there is no wildcard to match */
Hanno Becker24926222019-02-21 13:10:55 +0000534 if( buf_len < 3 || buf[0] != '*' || buf[1] != '.' )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000535 return( -1 );
536
537 for( i = 0; i < cn_len; ++i )
538 {
539 if( cn[i] == '.' )
540 {
541 cn_idx = i;
542 break;
543 }
544 }
545
546 if( cn_idx == 0 )
547 return( -1 );
548
Hanno Beckerb3def1d2019-02-22 11:46:06 +0000549 if( mbedtls_x509_memcasecmp( buf + 1, cn + cn_idx,
550 buf_len - 1, cn_len - cn_idx ) == 0 )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000551 {
552 return( 0 );
553 }
554
555 return( -1 );
556}
557
558/*
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +0200559 * Reset (init or clear) a verify_chain
560 */
561static void x509_crt_verify_chain_reset(
562 mbedtls_x509_crt_verify_chain *ver_chain )
563{
564 size_t i;
565
566 for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
567 {
568 ver_chain->items[i].crt = NULL;
Hanno Beckerd6ddcd62019-01-10 09:19:26 +0000569 ver_chain->items[i].flags = (uint32_t) -1;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +0200570 }
571
572 ver_chain->len = 0;
573}
574
575/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200576 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
577 */
578static int x509_get_version( unsigned char **p,
579 const unsigned char *end,
580 int *ver )
581{
582 int ret;
583 size_t len;
584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
586 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200587 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200589 {
590 *ver = 0;
591 return( 0 );
592 }
593
Hanno Becker2f472142019-02-12 11:52:10 +0000594 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200595 }
596
597 end = *p + len;
598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
600 return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200601
602 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 return( MBEDTLS_ERR_X509_INVALID_VERSION +
604 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200605
606 return( 0 );
607}
608
609/*
610 * Validity ::= SEQUENCE {
611 * notBefore Time,
612 * notAfter Time }
613 */
614static int x509_get_dates( unsigned char **p,
615 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 mbedtls_x509_time *from,
617 mbedtls_x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200618{
619 int ret;
620 size_t len;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
623 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
624 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200625
626 end = *p + len;
627
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200629 return( ret );
630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200632 return( ret );
633
634 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 return( MBEDTLS_ERR_X509_INVALID_DATE +
636 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200637
638 return( 0 );
639}
640
641/*
642 * X.509 v2/v3 unique identifier (not parsed)
643 */
644static int x509_get_uid( unsigned char **p,
645 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 mbedtls_x509_buf *uid, int n )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200647{
648 int ret;
649
650 if( *p == end )
651 return( 0 );
652
653 uid->tag = **p;
654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
656 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200657 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200659 return( 0 );
660
Hanno Becker2f472142019-02-12 11:52:10 +0000661 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200662 }
663
664 uid->p = *p;
665 *p += uid->len;
666
667 return( 0 );
668}
669
670static int x509_get_basic_constraints( unsigned char **p,
671 const unsigned char *end,
672 int *ca_istrue,
673 int *max_pathlen )
674{
675 int ret;
676 size_t len;
677
678 /*
679 * BasicConstraints ::= SEQUENCE {
680 * cA BOOLEAN DEFAULT FALSE,
681 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
682 */
683 *ca_istrue = 0; /* DEFAULT FALSE */
684 *max_pathlen = 0; /* endless */
685
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
687 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000688 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200689
690 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200691 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693 if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200694 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
696 ret = mbedtls_asn1_get_int( p, end, ca_istrue );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200697
698 if( ret != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000699 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200700
701 if( *ca_istrue != 0 )
702 *ca_istrue = 1;
703 }
704
705 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200706 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000709 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200710
711 if( *p != end )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000712 return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200713
714 (*max_pathlen)++;
715
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200716 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200717}
718
719static int x509_get_ns_cert_type( unsigned char **p,
720 const unsigned char *end,
721 unsigned char *ns_cert_type)
722{
723 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000727 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200728
729 if( bs.len != 1 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000730 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200731
732 /* Get actual bitstring */
733 *ns_cert_type = *bs.p;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200734 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200735}
736
737static int x509_get_key_usage( unsigned char **p,
738 const unsigned char *end,
Manuel Pégourié-Gonnard1d0ca1a2015-03-27 16:50:00 +0100739 unsigned int *key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200740{
741 int ret;
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200742 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000746 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200747
748 if( bs.len < 1 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000749 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200750
751 /* Get actual bitstring */
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200752 *key_usage = 0;
753 for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
754 {
755 *key_usage |= (unsigned int) bs.p[i] << (8*i);
756 }
757
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200758 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200759}
760
761/*
762 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
763 *
764 * KeyPurposeId ::= OBJECT IDENTIFIER
765 */
766static int x509_get_ext_key_usage( unsigned char **p,
767 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 mbedtls_x509_sequence *ext_key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200769{
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000770 return( mbedtls_asn1_get_sequence_of( p, end, ext_key_usage,
771 MBEDTLS_ASN1_OID ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200772}
773
774/*
775 * SubjectAltName ::= GeneralNames
776 *
777 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
778 *
779 * GeneralName ::= CHOICE {
780 * otherName [0] OtherName,
781 * rfc822Name [1] IA5String,
782 * dNSName [2] IA5String,
783 * x400Address [3] ORAddress,
784 * directoryName [4] Name,
785 * ediPartyName [5] EDIPartyName,
786 * uniformResourceIdentifier [6] IA5String,
787 * iPAddress [7] OCTET STRING,
788 * registeredID [8] OBJECT IDENTIFIER }
789 *
790 * OtherName ::= SEQUENCE {
791 * type-id OBJECT IDENTIFIER,
792 * value [0] EXPLICIT ANY DEFINED BY type-id }
793 *
794 * EDIPartyName ::= SEQUENCE {
795 * nameAssigner [0] DirectoryString OPTIONAL,
796 * partyName [1] DirectoryString }
797 *
Manuel Pégourié-Gonnardb4fe3cb2015-01-22 16:11:05 +0000798 * NOTE: we only parse and use dNSName at this point.
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200799 */
Hanno Beckerad462192019-02-21 13:32:31 +0000800static int x509_get_subject_alt_name_cb( void *ctx,
801 int tag,
802 unsigned char *data,
803 size_t data_len )
804{
805 mbedtls_asn1_sequence **cur_ptr = (mbedtls_asn1_sequence **) ctx;
806 mbedtls_asn1_sequence *cur = *cur_ptr;
807
Hanno Beckerad462192019-02-21 13:32:31 +0000808 /* Allocate and assign next pointer */
809 if( cur->buf.p != NULL )
810 {
811 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
812 if( cur->next == NULL )
Hanno Becker90b94082019-02-21 21:13:21 +0000813 return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
Hanno Beckerad462192019-02-21 13:32:31 +0000814 cur = cur->next;
815 }
816
817 cur->buf.tag = tag;
818 cur->buf.p = data;
819 cur->buf.len = data_len;
820
821 *cur_ptr = cur;
822 return( 0 );
823}
824
Hanno Becker5984d302019-02-21 14:46:54 +0000825static int x509_get_subject_alt_name( unsigned char *p,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200826 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200827 mbedtls_x509_sequence *subject_alt_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200828{
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000829 return( mbedtls_asn1_traverse_sequence_of( &p, end,
830 MBEDTLS_ASN1_TAG_CLASS_MASK,
831 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
832 MBEDTLS_ASN1_TAG_VALUE_MASK,
833 2 /* SubjectAlt DNS */,
834 x509_get_subject_alt_name_cb,
835 (void*) &subject_alt_name ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200836}
837
838/*
839 * X.509 v3 extensions
840 *
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200841 */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000842static int x509_crt_get_ext_cb( void *ctx,
843 int tag,
844 unsigned char *p,
845 size_t ext_len )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200846{
847 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +0000848 mbedtls_x509_crt_frame *frame = (mbedtls_x509_crt_frame *) ctx;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200849 size_t len;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000850 unsigned char *end, *end_ext_octet;
851 mbedtls_x509_buf extn_oid = { 0, 0, NULL };
852 int is_critical = 0; /* DEFAULT FALSE */
853 int ext_type = 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200854
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000855 ((void) tag);
Hanno Becker4e1bfc12019-02-12 17:22:36 +0000856
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000857 /*
858 * Extension ::= SEQUENCE {
859 * extnID OBJECT IDENTIFIER,
860 * critical BOOLEAN DEFAULT FALSE,
861 * extnValue OCTET STRING }
862 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200863
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000864 end = p + ext_len;
865
866 /* Get extension ID */
867 if( ( ret = mbedtls_asn1_get_tag( &p, end, &extn_oid.len,
868 MBEDTLS_ASN1_OID ) ) != 0 )
869 goto err;
870
871 extn_oid.tag = MBEDTLS_ASN1_OID;
872 extn_oid.p = p;
873 p += extn_oid.len;
874
875 /* Get optional critical */
876 if( ( ret = mbedtls_asn1_get_bool( &p, end, &is_critical ) ) != 0 &&
877 ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
878 goto err;
879
880 /* Data should be octet string type */
881 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
882 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
883 goto err;
884
885 end_ext_octet = p + len;
886 if( end_ext_octet != end )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200887 {
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000888 ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
889 goto err;
890 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200891
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000892 /*
893 * Detect supported extensions
894 */
895 ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
896 if( ret != 0 )
897 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000899 if( is_critical )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200900 {
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000901 /* Data is marked as critical: fail */
902 ret = MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
903 goto err;
904 }
905#endif
906 return( 0 );
907 }
908
909 /* Forbid repeated extensions */
Hanno Becker21f55672019-02-15 15:27:59 +0000910 if( ( frame->ext_types & ext_type ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000911 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
912
Hanno Becker21f55672019-02-15 15:27:59 +0000913 frame->ext_types |= ext_type;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000914 switch( ext_type )
915 {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100916 case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000917 {
918 int ca_istrue;
919 int max_pathlen;
920
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200921 /* Parse basic constraints */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000922 ret = x509_get_basic_constraints( &p, end_ext_octet,
923 &ca_istrue,
924 &max_pathlen );
925 if( ret != 0 )
926 goto err;
927
Hanno Becker21f55672019-02-15 15:27:59 +0000928 frame->ca_istrue = ca_istrue;
929 frame->max_pathlen = max_pathlen;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200930 break;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000931 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200933 case MBEDTLS_X509_EXT_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200934 /* Parse key usage */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000935 ret = x509_get_key_usage( &p, end_ext_octet,
Hanno Becker21f55672019-02-15 15:27:59 +0000936 &frame->key_usage );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000937 if( ret != 0 )
938 goto err;
939 break;
940
941 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
942 /* Copy reference to raw subject alt name data. */
Hanno Becker21f55672019-02-15 15:27:59 +0000943 frame->subject_alt_raw.p = p;
944 frame->subject_alt_raw.len = end_ext_octet - p;
945
946 ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
947 MBEDTLS_ASN1_TAG_CLASS_MASK,
948 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
949 MBEDTLS_ASN1_TAG_VALUE_MASK,
950 2 /* SubjectAlt DNS */,
951 NULL, NULL );
952 if( ret != 0 )
953 goto err;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200954 break;
955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200957 /* Parse extended key usage */
Hanno Becker21f55672019-02-15 15:27:59 +0000958 frame->ext_key_usage_raw.p = p;
959 frame->ext_key_usage_raw.len = end_ext_octet - p;
960 if( frame->ext_key_usage_raw.len == 0 )
Hanno Becker5984d302019-02-21 14:46:54 +0000961 {
Hanno Becker21f55672019-02-15 15:27:59 +0000962 ret = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
963 goto err;
Hanno Becker5984d302019-02-21 14:46:54 +0000964 }
Hanno Becker21f55672019-02-15 15:27:59 +0000965
966 /* Check structural sanity of extension. */
967 ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
968 0xFF, MBEDTLS_ASN1_OID,
969 0, 0, NULL, NULL );
970 if( ret != 0 )
971 goto err;
972
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200973 break;
974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200976 /* Parse netscape certificate type */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000977 ret = x509_get_ns_cert_type( &p, end_ext_octet,
Hanno Becker21f55672019-02-15 15:27:59 +0000978 &frame->ns_cert_type );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000979 if( ret != 0 )
980 goto err;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200981 break;
982
983 default:
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000984 /*
985 * If this is a non-critical extension, which the oid layer
986 * supports, but there isn't an X.509 parser for it,
987 * skip the extension.
988 */
989#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
990 if( is_critical )
991 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
992#endif
993 p = end_ext_octet;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200994 }
995
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200996 return( 0 );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000997
998err:
999 return( ret );
1000}
1001
Hanno Becker21f55672019-02-15 15:27:59 +00001002static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001003{
1004 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +00001005 unsigned char *p = frame->v3_ext.p;
1006 unsigned char *end = p + frame->v3_ext.len;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001007
Hanno Becker21f55672019-02-15 15:27:59 +00001008 if( p == end )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001009 return( 0 );
1010
Hanno Becker21f55672019-02-15 15:27:59 +00001011 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001012 0xFF, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED,
Hanno Becker21f55672019-02-15 15:27:59 +00001013 0, 0, x509_crt_get_ext_cb, frame );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001014
1015 if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
1016 return( ret );
1017 if( ret == MBEDTLS_ERR_X509_INVALID_EXTENSIONS )
1018 return( ret );
1019
1020 if( ret != 0 )
1021 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1022
1023 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001024}
1025
Hanno Becker21f55672019-02-15 15:27:59 +00001026static int x509_crt_parse_frame( unsigned char *start,
1027 unsigned char *end,
1028 mbedtls_x509_crt_frame *frame )
1029{
1030 int ret;
1031 unsigned char *p;
1032 size_t len;
1033
1034 mbedtls_x509_buf tmp;
1035 unsigned char *tbs_start;
1036
1037 mbedtls_x509_buf outer_sig_alg;
1038 size_t inner_sig_alg_len;
1039 unsigned char *inner_sig_alg_start;
1040
1041 memset( frame, 0, sizeof( *frame ) );
1042
1043 /*
1044 * Certificate ::= SEQUENCE {
1045 * tbsCertificate TBSCertificate,
1046 * signatureAlgorithm AlgorithmIdentifier,
1047 * signatureValue BIT STRING
1048 * }
1049 *
1050 */
1051 p = start;
1052
1053 frame->raw.p = p;
1054 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1055 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1056 {
1057 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
1058 }
1059
1060 /* NOTE: We are currently not checking that the `Certificate`
1061 * structure spans the entire buffer. */
1062 end = p + len;
1063 frame->raw.len = end - frame->raw.p;
1064
1065 /*
1066 * TBSCertificate ::= SEQUENCE { ...
1067 */
1068 frame->tbs.p = p;
1069 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1070 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1071 {
1072 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
1073 }
1074 tbs_start = p;
1075
1076 /* Breadth-first parsing: Jump over TBS for now. */
1077 p += len;
1078 frame->tbs.len = p - frame->tbs.p;
1079
1080 /*
1081 * AlgorithmIdentifier ::= SEQUENCE { ...
1082 */
1083 outer_sig_alg.p = p;
1084 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1085 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1086 {
1087 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
1088 }
1089 p += len;
1090 outer_sig_alg.len = p - outer_sig_alg.p;
1091
1092 /*
1093 * signatureValue BIT STRING
1094 */
1095 ret = mbedtls_x509_get_sig( &p, end, &tmp );
1096 if( ret != 0 )
1097 return( ret );
1098 frame->sig.p = tmp.p;
1099 frame->sig.len = tmp.len;
1100
1101 /* Check that we consumed the entire `Certificate` structure. */
1102 if( p != end )
1103 {
1104 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
1105 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
1106 }
1107
1108 /* Parse TBSCertificate structure
1109 *
1110 * TBSCertificate ::= SEQUENCE {
1111 * version [0] EXPLICIT Version DEFAULT v1,
1112 * serialNumber CertificateSerialNumber,
1113 * signature AlgorithmIdentifier,
1114 * issuer Name,
1115 * validity Validity,
1116 * subject Name,
1117 * subjectPublicKeyInfo SubjectPublicKeyInfo,
1118 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1119 * -- If present, version MUST be v2 or v3
1120 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1121 * -- If present, version MUST be v2 or v3
1122 * extensions [3] EXPLICIT Extensions OPTIONAL
1123 * -- If present, version MUST be v3
1124 * }
1125 */
1126 end = frame->tbs.p + frame->tbs.len;
1127 p = tbs_start;
1128
1129 /*
1130 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
1131 */
1132 {
1133 int version;
1134 ret = x509_get_version( &p, end, &version );
1135 if( ret != 0 )
1136 return( ret );
1137
1138 if( version < 0 || version > 2 )
1139 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
1140
1141 frame->version = version + 1;
1142 }
1143
1144 /*
1145 * CertificateSerialNumber ::= INTEGER
1146 */
1147 ret = mbedtls_x509_get_serial( &p, end, &tmp );
1148 if( ret != 0 )
1149 return( ret );
1150
1151 frame->serial.p = tmp.p;
1152 frame->serial.len = tmp.len;
1153
1154 /*
1155 * signature AlgorithmIdentifier
1156 */
1157 inner_sig_alg_start = p;
1158 ret = mbedtls_x509_get_sig_alg_raw( &p, end, &frame->sig_md,
1159 &frame->sig_pk, NULL );
1160 if( ret != 0 )
1161 return( ret );
1162 inner_sig_alg_len = p - inner_sig_alg_start;
1163
1164 frame->sig_alg.p = inner_sig_alg_start;
1165 frame->sig_alg.len = inner_sig_alg_len;
1166
1167 /* Consistency check:
1168 * Inner and outer AlgorithmIdentifier structures must coincide:
1169 *
1170 * Quoting RFC 5280, Section 4.1.1.2:
1171 * This field MUST contain the same algorithm identifier as the
1172 * signature field in the sequence tbsCertificate (Section 4.1.2.3).
1173 */
1174 if( outer_sig_alg.len != inner_sig_alg_len ||
1175 memcmp( outer_sig_alg.p, inner_sig_alg_start, inner_sig_alg_len ) != 0 )
1176 {
1177 return( MBEDTLS_ERR_X509_SIG_MISMATCH );
1178 }
1179
1180 /*
1181 * issuer Name
1182 *
1183 * Name ::= CHOICE { -- only one possibility for now --
1184 * rdnSequence RDNSequence }
1185 *
1186 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
1187 */
1188 frame->issuer_raw_with_hdr.p = p;
1189
1190 ret = mbedtls_asn1_get_tag( &p, end, &len,
1191 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1192 if( ret != 0 )
1193 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
1194 frame->issuer_raw.p = p;
1195 frame->issuer_raw.len = len;
1196 p += len;
1197
1198 ret = mbedtls_x509_name_cmp_raw( &frame->issuer_raw,
1199 &frame->issuer_raw,
1200 NULL, NULL );
1201 if( ret != 0 )
1202 return( ret );
1203
1204 frame->issuer_raw_with_hdr.len = p - frame->issuer_raw_with_hdr.p;
1205
1206 /*
1207 * Validity ::= SEQUENCE { ...
1208 */
1209 ret = x509_get_dates( &p, end, &frame->valid_from, &frame->valid_to );
1210 if( ret != 0 )
1211 return( ret );
1212
1213 /*
1214 * subject Name
1215 *
1216 * Name ::= CHOICE { -- only one possibility for now --
1217 * rdnSequence RDNSequence }
1218 *
1219 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
1220 */
1221 frame->subject_raw_with_hdr.p = p;
1222
1223 ret = mbedtls_asn1_get_tag( &p, end, &len,
1224 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1225 if( ret != 0 )
1226 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
1227 frame->subject_raw.p = p;
1228 frame->subject_raw.len = len;
1229 p += len;
1230
1231 ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
1232 &frame->subject_raw,
1233 NULL, NULL );
1234 if( ret != 0 )
1235 return( ret );
1236
1237 frame->subject_raw_with_hdr.len = p - frame->subject_raw_with_hdr.p;
1238
1239 /*
1240 * SubjectPublicKeyInfo
1241 */
1242 frame->pubkey_raw.p = p;
1243 ret = mbedtls_asn1_get_tag( &p, end, &len,
1244 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1245 if( ret != 0 )
1246 return( ret + MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
1247 p += len;
1248 frame->pubkey_raw.len = p - frame->pubkey_raw.p;
1249
1250 /*
1251 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1252 * -- If present, version shall be v2 or v3
1253 */
1254 if( frame->version == 2 || frame->version == 3 )
1255 {
1256 ret = x509_get_uid( &p, end, &tmp, 1 /* implicit tag */ );
1257 if( ret != 0 )
1258 return( ret );
1259
1260 frame->issuer_id.p = tmp.p;
1261 frame->issuer_id.len = tmp.len;
1262 }
1263
1264 /*
1265 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1266 * -- If present, version shall be v2 or v3
1267 */
1268 if( frame->version == 2 || frame->version == 3 )
1269 {
1270 ret = x509_get_uid( &p, end, &tmp, 2 /* implicit tag */ );
1271 if( ret != 0 )
1272 return( ret );
1273
1274 frame->subject_id.p = tmp.p;
1275 frame->subject_id.len = tmp.len;
1276 }
1277
1278 /*
1279 * extensions [3] EXPLICIT Extensions OPTIONAL
1280 * -- If present, version shall be v3
1281 */
1282#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
1283 if( frame->version == 3 )
1284#endif
1285 {
1286 if( p != end )
1287 {
1288 ret = mbedtls_asn1_get_tag( &p, end, &len,
1289 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
1290 MBEDTLS_ASN1_CONSTRUCTED | 3 );
1291 if( len == 0 )
1292 ret = MBEDTLS_ERR_ASN1_OUT_OF_DATA;
1293 if( ret != 0 )
1294 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
1295
1296 frame->v3_ext.p = p;
1297 frame->v3_ext.len = len;
1298
1299 p += len;
1300 }
1301
1302 ret = x509_crt_frame_parse_ext( frame );
1303 if( ret != 0 )
1304 return( ret );
1305 }
1306
1307 /* Wrapup: Check that we consumed the entire `TBSCertificate` structure. */
1308 if( p != end )
1309 {
1310 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
1311 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
1312 }
1313
1314 return( 0 );
1315}
1316
1317static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame *frame,
1318 mbedtls_x509_name *subject )
1319{
1320 unsigned char *p = frame->subject_raw.p;
1321 unsigned char *end = p + frame->subject_raw.len;
1322
1323 return( mbedtls_x509_get_name( &p, end, subject ) );
1324}
1325
1326static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame *frame,
1327 mbedtls_x509_name *issuer )
1328{
1329 unsigned char *p = frame->issuer_raw.p;
1330 unsigned char *end = p + frame->issuer_raw.len;
1331
1332 return( mbedtls_x509_get_name( &p, end, issuer ) );
1333}
1334
1335static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame *frame,
1336 mbedtls_x509_sequence *subject_alt )
1337{
1338 int ret;
1339 unsigned char *p = frame->subject_alt_raw.p;
1340 unsigned char *end = p + frame->subject_alt_raw.len;
1341
1342 memset( subject_alt, 0, sizeof( *subject_alt ) );
1343
1344 if( ( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) == 0 )
1345 return( 0 );
1346
1347 ret = x509_get_subject_alt_name( p, end, subject_alt );
1348 if( ret != 0 )
1349 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1350 return( ret );
1351}
1352
1353static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame *frame,
1354 mbedtls_x509_sequence *ext_key_usage )
1355{
1356 int ret;
1357 unsigned char *p = frame->ext_key_usage_raw.p;
1358 unsigned char *end = p + frame->ext_key_usage_raw.len;
1359
1360 memset( ext_key_usage, 0, sizeof( *ext_key_usage ) );
1361
1362 if( ( frame->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
1363 return( 0 );
1364
1365 ret = x509_get_ext_key_usage( &p, end, ext_key_usage );
1366 if( ret != 0 )
1367 {
1368 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1369 return( ret );
1370 }
1371
1372 return( 0 );
1373}
1374
Hanno Becker180f7bf2019-02-28 13:23:38 +00001375#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
Hanno Becker21f55672019-02-15 15:27:59 +00001376static int x509_crt_pk_from_frame( mbedtls_x509_crt_frame *frame,
1377 mbedtls_pk_context *pk )
1378{
1379 unsigned char *p = frame->pubkey_raw.p;
1380 unsigned char *end = p + frame->pubkey_raw.len;
1381 return( mbedtls_pk_parse_subpubkey( &p, end, pk ) );
1382}
Hanno Becker180f7bf2019-02-28 13:23:38 +00001383#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Becker21f55672019-02-15 15:27:59 +00001384
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001385/*
1386 * Parse and fill a single X.509 certificate in DER format
1387 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001388static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
1389 const unsigned char *buf,
1390 size_t buflen,
1391 int make_copy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001392{
1393 int ret;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001394 mbedtls_x509_crt_frame *frame;
1395 mbedtls_x509_crt_cache *cache;
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +01001396
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001397 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001399
Hanno Becker21f55672019-02-15 15:27:59 +00001400 if( make_copy == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001401 {
Hanno Becker21f55672019-02-15 15:27:59 +00001402 crt->raw.p = (unsigned char*) buf;
1403 crt->raw.len = buflen;
1404 crt->own_buffer = 0;
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001405 }
1406 else
1407 {
Hanno Becker21f55672019-02-15 15:27:59 +00001408 crt->raw.p = mbedtls_calloc( 1, buflen );
1409 if( crt->raw.p == NULL )
1410 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
1411 crt->raw.len = buflen;
1412 memcpy( crt->raw.p, buf, buflen );
1413
1414 crt->own_buffer = 1;
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001415 }
Janos Follathcc0e49d2016-02-17 14:34:12 +00001416
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001417 cache = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_cache ) );
1418 if( cache == NULL )
1419 {
1420 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
1421 goto exit;
1422 }
1423 crt->cache = cache;
1424 x509_crt_cache_init( cache );
1425
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001426#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
1427
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001428 ret = mbedtls_x509_crt_cache_provide_frame( crt );
Hanno Becker21f55672019-02-15 15:27:59 +00001429 if( ret != 0 )
1430 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001431
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001432 frame = mbedtls_x509_crt_cache_get_frame( crt->cache );
1433
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001434#else /* MBEDTLS_X509_ON_DEMAND_PARSING */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001435
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001436 frame = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_frame ) );
1437 if( frame == NULL )
1438 {
1439 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
1440 goto exit;
1441 }
1442 cache->frame = frame;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001443
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001444 ret = x509_crt_parse_frame( crt->raw.p,
1445 crt->raw.p + crt->raw.len,
1446 frame );
1447 if( ret != 0 )
1448 goto exit;
1449
Hanno Becker21f55672019-02-15 15:27:59 +00001450 /* Copy frame to legacy CRT structure -- that's inefficient, but if
1451 * memory matters, the new CRT structure should be used anyway. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001452 crt->tbs.p = frame->tbs.p;
1453 crt->tbs.len = frame->tbs.len;
1454 crt->serial.p = frame->serial.p;
1455 crt->serial.len = frame->serial.len;
1456 crt->issuer_raw.p = frame->issuer_raw_with_hdr.p;
1457 crt->issuer_raw.len = frame->issuer_raw_with_hdr.len;
1458 crt->subject_raw.p = frame->subject_raw_with_hdr.p;
1459 crt->subject_raw.len = frame->subject_raw_with_hdr.len;
1460 crt->issuer_raw_no_hdr = frame->issuer_raw;
1461 crt->subject_raw_no_hdr = frame->subject_raw;
1462 crt->issuer_id.p = frame->issuer_id.p;
1463 crt->issuer_id.len = frame->issuer_id.len;
1464 crt->subject_id.p = frame->subject_id.p;
1465 crt->subject_id.len = frame->subject_id.len;
1466 crt->pk_raw.p = frame->pubkey_raw.p;
1467 crt->pk_raw.len = frame->pubkey_raw.len;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001468 crt->sig.p = frame->sig.p;
1469 crt->sig.len = frame->sig.len;
1470 crt->valid_from = frame->valid_from;
1471 crt->valid_to = frame->valid_to;
1472 crt->v3_ext.p = frame->v3_ext.p;
1473 crt->v3_ext.len = frame->v3_ext.len;
1474 crt->version = frame->version;
1475 crt->ca_istrue = frame->ca_istrue;
1476 crt->max_pathlen = frame->max_pathlen;
1477 crt->ext_types = frame->ext_types;
1478 crt->key_usage = frame->key_usage;
1479 crt->ns_cert_type = frame->ns_cert_type;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001480
1481 /*
Hanno Becker21f55672019-02-15 15:27:59 +00001482 * Obtain the remaining fields from the frame.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001483 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001484
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001485 {
Hanno Becker21f55672019-02-15 15:27:59 +00001486 /* sig_oid: Previously, needed for convenience in
1487 * mbedtls_x509_crt_info(), now pure legacy burden. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001488 unsigned char *tmp = frame->sig_alg.p;
1489 unsigned char *end = tmp + frame->sig_alg.len;
Hanno Becker21f55672019-02-15 15:27:59 +00001490 mbedtls_x509_buf sig_oid, sig_params;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001491
Hanno Becker21f55672019-02-15 15:27:59 +00001492 ret = mbedtls_x509_get_alg( &tmp, end,
1493 &sig_oid, &sig_params );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001494 if( ret != 0 )
1495 {
Hanno Becker21f55672019-02-15 15:27:59 +00001496 /* This should never happen, because we check
1497 * the sanity of the AlgorithmIdentifier structure
1498 * during frame parsing. */
1499 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1500 goto exit;
1501 }
1502 crt->sig_oid = sig_oid;
1503
1504 /* Signature parameters */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001505 tmp = frame->sig_alg.p;
Hanno Becker21f55672019-02-15 15:27:59 +00001506 ret = mbedtls_x509_get_sig_alg_raw( &tmp, end,
1507 &crt->sig_md, &crt->sig_pk,
1508 &crt->sig_opts );
1509 if( ret != 0 )
1510 {
1511 /* Again, this should never happen. */
1512 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1513 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001514 }
1515 }
1516
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001517 ret = x509_crt_pk_from_frame( frame, &crt->pk );
Hanno Becker21f55672019-02-15 15:27:59 +00001518 if( ret != 0 )
1519 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001520
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001521 ret = x509_crt_subject_from_frame( frame, &crt->subject );
Hanno Becker21f55672019-02-15 15:27:59 +00001522 if( ret != 0 )
1523 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001524
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001525 ret = x509_crt_issuer_from_frame( frame, &crt->issuer );
Hanno Becker21f55672019-02-15 15:27:59 +00001526 if( ret != 0 )
1527 goto exit;
1528
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001529 ret = x509_crt_subject_alt_from_frame( frame, &crt->subject_alt_names );
Hanno Becker21f55672019-02-15 15:27:59 +00001530 if( ret != 0 )
1531 goto exit;
1532
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001533 ret = x509_crt_ext_key_usage_from_frame( frame, &crt->ext_key_usage );
1534 if( ret != 0 )
1535 goto exit;
Hanno Becker180f7bf2019-02-28 13:23:38 +00001536#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001537
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001538 /* Currently, we accept DER encoded CRTs with trailing garbage
1539 * and promise to not account for the garbage in the `raw` field.
1540 *
1541 * Note that this means that `crt->raw.len` is not necessarily the
1542 * full size of the heap buffer allocated at `crt->raw.p` in case
1543 * of copy-mode, but this is not a problem: freeing the buffer doesn't
1544 * need the size, and the garbage data doesn't need zeroization. */
1545 crt->raw.len = frame->raw.len;
1546
1547 cache->pk_raw = frame->pubkey_raw;
1548
Hanno Becker7a4de9c2019-02-27 13:12:24 +00001549 /* Free the frame before parsing the public key to
1550 * keep peak RAM usage low. This is slightly inefficient
1551 * because the frame will need to be parsed again on the
1552 * first usage of the CRT, but that seems acceptable.
1553 * As soon as the frame gets used multiple times, it
1554 * will be cached by default. */
1555 x509_crt_cache_clear_frame( crt->cache );
1556
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001557 /* The cache just references the PK structure from the legacy
1558 * implementation, so set up the latter first before setting up
Hanno Becker7a4de9c2019-02-27 13:12:24 +00001559 * the cache.
1560 *
1561 * We're not actually using the parsed PK context here;
1562 * we just parse it to check that it's well-formed. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001563 ret = mbedtls_x509_crt_cache_provide_pk( crt );
Hanno Becker21f55672019-02-15 15:27:59 +00001564 if( ret != 0 )
1565 goto exit;
Hanno Becker7a4de9c2019-02-27 13:12:24 +00001566 x509_crt_cache_clear_pk( crt->cache );
Hanno Becker21f55672019-02-15 15:27:59 +00001567
1568exit:
1569 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001571
Hanno Becker21f55672019-02-15 15:27:59 +00001572 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001573}
1574
1575/*
1576 * Parse one X.509 certificate in DER format from a buffer and add them to a
1577 * chained list
1578 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001579static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
1580 const unsigned char *buf,
1581 size_t buflen,
1582 int make_copy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001583{
1584 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 mbedtls_x509_crt *crt = chain, *prev = NULL;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001586
1587 /*
1588 * Check for valid input
1589 */
1590 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001592
Hanno Becker371e0e42019-02-25 18:08:59 +00001593 while( crt->raw.p != NULL && crt->next != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001594 {
1595 prev = crt;
1596 crt = crt->next;
1597 }
1598
1599 /*
1600 * Add new certificate on the end of the chain if needed.
1601 */
Hanno Becker371e0e42019-02-25 18:08:59 +00001602 if( crt->raw.p != NULL && crt->next == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001603 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001604 crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001605
1606 if( crt->next == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001607 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001608
1609 prev = crt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 mbedtls_x509_crt_init( crt->next );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001611 crt = crt->next;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001612 }
1613
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001614 if( ( ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001615 {
1616 if( prev )
1617 prev->next = NULL;
1618
1619 if( crt != chain )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 mbedtls_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001621
1622 return( ret );
1623 }
1624
1625 return( 0 );
1626}
1627
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001628int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain,
1629 const unsigned char *buf,
1630 size_t buflen )
1631{
1632 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0 ) );
1633}
1634
1635int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain,
1636 const unsigned char *buf,
1637 size_t buflen )
1638{
1639 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1 ) );
1640}
1641
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001642/*
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001643 * Parse one or more PEM certificates from a buffer and add them to the chained
1644 * list
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001645 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001646int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
1647 const unsigned char *buf,
1648 size_t buflen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001649{
Janos Follath98e28a72016-05-31 14:03:54 +01001650#if defined(MBEDTLS_PEM_PARSE_C)
Andres AGc0db5112016-12-07 15:05:53 +00001651 int success = 0, first_error = 0, total_failed = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652 int buf_format = MBEDTLS_X509_FORMAT_DER;
Janos Follath98e28a72016-05-31 14:03:54 +01001653#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001654
1655 /*
1656 * Check for valid input
1657 */
1658 if( chain == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001659 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001660
1661 /*
1662 * Determine buffer content. Buffer contains either one DER certificate or
1663 * one or more PEM certificates.
1664 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001666 if( buflen != 0 && buf[buflen - 1] == '\0' &&
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001667 strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
1668 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 buf_format = MBEDTLS_X509_FORMAT_PEM;
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001670 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001672 if( buf_format == MBEDTLS_X509_FORMAT_DER )
1673 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
Janos Follath98e28a72016-05-31 14:03:54 +01001674#else
1675 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
1676#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678#if defined(MBEDTLS_PEM_PARSE_C)
1679 if( buf_format == MBEDTLS_X509_FORMAT_PEM )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001680 {
1681 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001682 mbedtls_pem_context pem;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001683
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001684 /* 1 rather than 0 since the terminating NULL byte is counted in */
1685 while( buflen > 1 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001686 {
1687 size_t use_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 mbedtls_pem_init( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001689
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001690 /* If we get there, we know the string is null-terminated */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 ret = mbedtls_pem_read_buffer( &pem,
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001692 "-----BEGIN CERTIFICATE-----",
1693 "-----END CERTIFICATE-----",
1694 buf, NULL, 0, &use_len );
1695
1696 if( ret == 0 )
1697 {
1698 /*
1699 * Was PEM encoded
1700 */
1701 buflen -= use_len;
1702 buf += use_len;
1703 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001705 {
1706 return( ret );
1707 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001709 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001711
1712 /*
1713 * PEM header and footer were found
1714 */
1715 buflen -= use_len;
1716 buf += use_len;
1717
1718 if( first_error == 0 )
1719 first_error = ret;
1720
Paul Bakker5a5fa922014-09-26 14:53:04 +02001721 total_failed++;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001722 continue;
1723 }
1724 else
1725 break;
1726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001728
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001729 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001730
1731 if( ret != 0 )
1732 {
1733 /*
1734 * Quit parsing on a memory error
1735 */
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001736 if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001737 return( ret );
1738
1739 if( first_error == 0 )
1740 first_error = ret;
1741
1742 total_failed++;
1743 continue;
1744 }
1745
1746 success = 1;
1747 }
1748 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001749
1750 if( success )
1751 return( total_failed );
1752 else if( first_error )
1753 return( first_error );
1754 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
Janos Follath98e28a72016-05-31 14:03:54 +01001756#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001757}
1758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759#if defined(MBEDTLS_FS_IO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001760/*
1761 * Load one or more certificates and add them to the chained list
1762 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001764{
1765 int ret;
1766 size_t n;
1767 unsigned char *buf;
1768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001769 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001770 return( ret );
1771
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772 ret = mbedtls_x509_crt_parse( chain, buf, n );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001773
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001774 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001775 mbedtls_free( buf );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001776
1777 return( ret );
1778}
1779
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001780int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001781{
1782 int ret = 0;
Paul Bakkerfa6a6202013-10-28 18:48:30 +01001783#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001784 int w_ret;
1785 WCHAR szDir[MAX_PATH];
1786 char filename[MAX_PATH];
Paul Bakker9af723c2014-05-01 13:03:14 +02001787 char *p;
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001788 size_t len = strlen( path );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001789
Paul Bakker9af723c2014-05-01 13:03:14 +02001790 WIN32_FIND_DATAW file_data;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001791 HANDLE hFind;
1792
1793 if( len > MAX_PATH - 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001794 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001795
Paul Bakker9af723c2014-05-01 13:03:14 +02001796 memset( szDir, 0, sizeof(szDir) );
1797 memset( filename, 0, MAX_PATH );
1798 memcpy( filename, path, len );
1799 filename[len++] = '\\';
1800 p = filename + len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001801 filename[len++] = '*';
1802
Simon B3c6b18d2016-11-03 01:11:37 +00001803 w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001804 MAX_PATH - 3 );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001805 if( w_ret == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001807
1808 hFind = FindFirstFileW( szDir, &file_data );
Paul Bakker66d5d072014-06-17 16:39:18 +02001809 if( hFind == INVALID_HANDLE_VALUE )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001811
1812 len = MAX_PATH - len;
1813 do
1814 {
Paul Bakker9af723c2014-05-01 13:03:14 +02001815 memset( p, 0, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001816
1817 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
1818 continue;
1819
Paul Bakker9af723c2014-05-01 13:03:14 +02001820 w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
Paul Bakker66d5d072014-06-17 16:39:18 +02001821 lstrlenW( file_data.cFileName ),
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001822 p, (int) len - 1,
Paul Bakker9af723c2014-05-01 13:03:14 +02001823 NULL, NULL );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001824 if( w_ret == 0 )
Ron Eldor36d90422017-01-09 15:09:16 +02001825 {
1826 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
1827 goto cleanup;
1828 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001829
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830 w_ret = mbedtls_x509_crt_parse_file( chain, filename );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001831 if( w_ret < 0 )
1832 ret++;
1833 else
1834 ret += w_ret;
1835 }
1836 while( FindNextFileW( hFind, &file_data ) != 0 );
1837
Paul Bakker66d5d072014-06-17 16:39:18 +02001838 if( GetLastError() != ERROR_NO_MORE_FILES )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001840
Ron Eldor36d90422017-01-09 15:09:16 +02001841cleanup:
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001842 FindClose( hFind );
Paul Bakkerbe089b02013-10-14 15:51:50 +02001843#else /* _WIN32 */
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001844 int t_ret;
Andres AGf9113192016-09-02 14:06:04 +01001845 int snp_ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001846 struct stat sb;
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001847 struct dirent *entry;
Andres AGf9113192016-09-02 14:06:04 +01001848 char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001849 DIR *dir = opendir( path );
1850
Paul Bakker66d5d072014-06-17 16:39:18 +02001851 if( dir == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001853
Ron Eldor63140682017-01-09 19:27:59 +02001854#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02001855 if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02001856 {
1857 closedir( dir );
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001858 return( ret );
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02001859 }
Ron Eldor63140682017-01-09 19:27:59 +02001860#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001861
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001862 while( ( entry = readdir( dir ) ) != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001863 {
Andres AGf9113192016-09-02 14:06:04 +01001864 snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
1865 "%s/%s", path, entry->d_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001866
Andres AGf9113192016-09-02 14:06:04 +01001867 if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001868 {
Andres AGf9113192016-09-02 14:06:04 +01001869 ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1870 goto cleanup;
1871 }
1872 else if( stat( entry_name, &sb ) == -1 )
1873 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001875 goto cleanup;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001876 }
1877
1878 if( !S_ISREG( sb.st_mode ) )
1879 continue;
1880
1881 // Ignore parse errors
1882 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001883 t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001884 if( t_ret < 0 )
1885 ret++;
1886 else
1887 ret += t_ret;
1888 }
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001889
1890cleanup:
Andres AGf9113192016-09-02 14:06:04 +01001891 closedir( dir );
1892
Ron Eldor63140682017-01-09 19:27:59 +02001893#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02001894 if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
Ron Eldor63140682017-01-09 19:27:59 +02001896#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001897
Paul Bakkerbe089b02013-10-14 15:51:50 +02001898#endif /* _WIN32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001899
1900 return( ret );
1901}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902#endif /* MBEDTLS_FS_IO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001903
Hanno Becker02a21932019-06-10 15:08:43 +01001904#if !defined(MBEDTLS_X509_REMOVE_INFO)
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001905static int x509_info_subject_alt_name( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 const mbedtls_x509_sequence *subject_alt_name )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001907{
1908 size_t i;
1909 size_t n = *size;
1910 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 const mbedtls_x509_sequence *cur = subject_alt_name;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001912 const char *sep = "";
1913 size_t sep_len = 0;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001914
1915 while( cur != NULL )
1916 {
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001917 if( cur->buf.len + sep_len >= n )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001918 {
1919 *p = '\0';
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001920 return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001921 }
1922
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001923 n -= cur->buf.len + sep_len;
1924 for( i = 0; i < sep_len; i++ )
1925 *p++ = sep[i];
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001926 for( i = 0; i < cur->buf.len; i++ )
1927 *p++ = cur->buf.p[i];
1928
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001929 sep = ", ";
1930 sep_len = 2;
1931
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001932 cur = cur->next;
1933 }
1934
1935 *p = '\0';
1936
1937 *size = n;
1938 *buf = p;
1939
1940 return( 0 );
1941}
1942
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001943#define PRINT_ITEM(i) \
1944 { \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001945 ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001946 MBEDTLS_X509_SAFE_SNPRINTF; \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001947 sep = ", "; \
1948 }
1949
1950#define CERT_TYPE(type,name) \
Hanno Beckerd6028a12018-10-15 12:01:35 +01001951 if( ns_cert_type & (type) ) \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001952 PRINT_ITEM( name );
1953
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001954static int x509_info_cert_type( char **buf, size_t *size,
1955 unsigned char ns_cert_type )
1956{
1957 int ret;
1958 size_t n = *size;
1959 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001960 const char *sep = "";
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001963 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001964 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" );
1965 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" );
1966 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001967 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" );
1968 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" );
1969 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" );
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001970
1971 *size = n;
1972 *buf = p;
1973
1974 return( 0 );
1975}
1976
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001977#define KEY_USAGE(code,name) \
Hanno Beckerd6028a12018-10-15 12:01:35 +01001978 if( key_usage & (code) ) \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001979 PRINT_ITEM( name );
1980
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001981static int x509_info_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02001982 unsigned int key_usage )
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001983{
1984 int ret;
1985 size_t n = *size;
1986 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001987 const char *sep = "";
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001988
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001989 KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" );
1990 KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001991 KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" );
1992 KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" );
1993 KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001994 KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" );
1995 KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" );
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02001996 KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" );
1997 KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" );
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001998
1999 *size = n;
2000 *buf = p;
2001
2002 return( 0 );
2003}
2004
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002005static int x509_info_ext_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 const mbedtls_x509_sequence *extended_key_usage )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002007{
2008 int ret;
2009 const char *desc;
2010 size_t n = *size;
2011 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002012 const mbedtls_x509_sequence *cur = extended_key_usage;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002013 const char *sep = "";
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002014
2015 while( cur != NULL )
2016 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002017 if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002018 desc = "???";
2019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002020 ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002021 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002022
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002023 sep = ", ";
2024
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002025 cur = cur->next;
2026 }
2027
2028 *size = n;
2029 *buf = p;
2030
2031 return( 0 );
2032}
2033
Hanno Becker4f869ed2019-02-24 16:47:57 +00002034typedef struct mbedtls_x509_crt_sig_info
2035{
2036 mbedtls_md_type_t sig_md;
2037 mbedtls_pk_type_t sig_pk;
2038 void *sig_opts;
2039 uint8_t crt_hash[MBEDTLS_MD_MAX_SIZE];
2040 size_t crt_hash_len;
2041 mbedtls_x509_buf_raw sig;
2042 mbedtls_x509_buf_raw issuer_raw;
2043} mbedtls_x509_crt_sig_info;
2044
2045static void x509_crt_free_sig_info( mbedtls_x509_crt_sig_info *info )
2046{
2047#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
2048 mbedtls_free( info->sig_opts );
2049#else
2050 ((void) info);
2051#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
2052}
2053
2054static int x509_crt_get_sig_info( mbedtls_x509_crt_frame const *frame,
2055 mbedtls_x509_crt_sig_info *info )
2056{
2057 const mbedtls_md_info_t *md_info;
2058
2059 md_info = mbedtls_md_info_from_type( frame->sig_md );
2060 if( mbedtls_md( md_info, frame->tbs.p, frame->tbs.len,
2061 info->crt_hash ) != 0 )
2062 {
2063 /* Note: this can't happen except after an internal error */
2064 return( -1 );
2065 }
2066
2067 info->crt_hash_len = mbedtls_md_get_size( md_info );
2068
2069 /* Make sure that this function leaves the target structure
2070 * ready to be freed, regardless of success of failure. */
2071 info->sig_opts = NULL;
2072
2073#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
2074 {
2075 int ret;
2076 unsigned char *alg_start = frame->sig_alg.p;
2077 unsigned char *alg_end = alg_start + frame->sig_alg.len;
2078
2079 /* Get signature options -- currently only
2080 * necessary for RSASSA-PSS. */
2081 ret = mbedtls_x509_get_sig_alg_raw( &alg_start, alg_end, &info->sig_md,
2082 &info->sig_pk, &info->sig_opts );
2083 if( ret != 0 )
2084 {
2085 /* Note: this can't happen except after an internal error */
2086 return( -1 );
2087 }
2088 }
2089#else /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
2090 info->sig_md = frame->sig_md;
2091 info->sig_pk = frame->sig_pk;
2092#endif /* !MBEDTLS_X509_RSASSA_PSS_SUPPORT */
2093
2094 info->issuer_raw = frame->issuer_raw;
2095 info->sig = frame->sig;
2096 return( 0 );
2097}
2098
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002099/*
2100 * Return an informational string about the certificate.
2101 */
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002102#define BEFORE_COLON 18
2103#define BC "18"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002104int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
Hanno Becker5226c532019-02-27 17:38:40 +00002105 const mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002106{
2107 int ret;
2108 size_t n;
2109 char *p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002110 char key_size_str[BEFORE_COLON];
Hanno Becker5226c532019-02-27 17:38:40 +00002111 mbedtls_x509_crt_frame frame;
2112 mbedtls_pk_context pk;
Hanno Becker4f869ed2019-02-24 16:47:57 +00002113
Hanno Becker5226c532019-02-27 17:38:40 +00002114 mbedtls_x509_name *issuer = NULL, *subject = NULL;
2115 mbedtls_x509_sequence *ext_key_usage = NULL, *subject_alt_names = NULL;
Hanno Becker4f869ed2019-02-24 16:47:57 +00002116 mbedtls_x509_crt_sig_info sig_info;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002117
2118 p = buf;
2119 n = size;
2120
Hanno Becker4f869ed2019-02-24 16:47:57 +00002121 memset( &sig_info, 0, sizeof( mbedtls_x509_crt_sig_info ) );
Hanno Becker5226c532019-02-27 17:38:40 +00002122 mbedtls_pk_init( &pk );
2123
2124 if( NULL == crt )
Janos Follath98e28a72016-05-31 14:03:54 +01002125 {
2126 ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002127 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Janos Follath98e28a72016-05-31 14:03:54 +01002128
2129 return( (int) ( size - n ) );
2130 }
2131
Hanno Becker5226c532019-02-27 17:38:40 +00002132 ret = mbedtls_x509_crt_get_frame( crt, &frame );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002133 if( ret != 0 )
2134 {
2135 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2136 goto cleanup;
2137 }
2138
Hanno Becker5226c532019-02-27 17:38:40 +00002139 ret = mbedtls_x509_crt_get_subject( crt, &subject );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002140 if( ret != 0 )
2141 {
2142 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2143 goto cleanup;
2144 }
2145
Hanno Becker5226c532019-02-27 17:38:40 +00002146 ret = mbedtls_x509_crt_get_issuer( crt, &issuer );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002147 if( ret != 0 )
2148 {
2149 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2150 goto cleanup;
2151 }
2152
Hanno Becker5226c532019-02-27 17:38:40 +00002153 ret = mbedtls_x509_crt_get_subject_alt_names( crt, &subject_alt_names );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002154 if( ret != 0 )
2155 {
2156 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2157 goto cleanup;
2158 }
2159
Hanno Becker5226c532019-02-27 17:38:40 +00002160 ret = mbedtls_x509_crt_get_ext_key_usage( crt, &ext_key_usage );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002161 if( ret != 0 )
2162 {
2163 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2164 goto cleanup;
2165 }
2166
Hanno Becker5226c532019-02-27 17:38:40 +00002167 ret = mbedtls_x509_crt_get_pk( crt, &pk );
2168 if( ret != 0 )
2169 {
2170 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2171 goto cleanup;
2172 }
2173
2174 ret = x509_crt_get_sig_info( &frame, &sig_info );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002175 if( ret != 0 )
2176 {
2177 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2178 goto cleanup;
2179 }
2180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 ret = mbedtls_snprintf( p, n, "%scert. version : %d\n",
Hanno Becker5226c532019-02-27 17:38:40 +00002182 prefix, frame.version );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002183 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002184
Hanno Becker4f869ed2019-02-24 16:47:57 +00002185 {
2186 mbedtls_x509_buf serial;
Hanno Becker5226c532019-02-27 17:38:40 +00002187 serial.p = frame.serial.p;
2188 serial.len = frame.serial.len;
Hanno Becker4f869ed2019-02-24 16:47:57 +00002189 ret = mbedtls_snprintf( p, n, "%sserial number : ",
2190 prefix );
2191 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
2192 ret = mbedtls_x509_serial_gets( p, n, &serial );
2193 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
2194 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002197 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Hanno Becker5226c532019-02-27 17:38:40 +00002198 ret = mbedtls_x509_dn_gets( p, n, issuer );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002199 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201 ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002202 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Hanno Becker5226c532019-02-27 17:38:40 +00002203 ret = mbedtls_x509_dn_gets( p, n, subject );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002204 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002205
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002206 ret = mbedtls_snprintf( p, n, "\n%sissued on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002207 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
Hanno Becker5226c532019-02-27 17:38:40 +00002208 frame.valid_from.year, frame.valid_from.mon,
2209 frame.valid_from.day, frame.valid_from.hour,
2210 frame.valid_from.min, frame.valid_from.sec );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002211 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002214 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
Hanno Becker5226c532019-02-27 17:38:40 +00002215 frame.valid_to.year, frame.valid_to.mon,
2216 frame.valid_to.day, frame.valid_to.hour,
2217 frame.valid_to.min, frame.valid_to.sec );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002218 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002219
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002221 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002222
Hanno Becker83cd8672019-02-21 17:13:46 +00002223 ret = mbedtls_x509_sig_alg_gets( p, n, sig_info.sig_pk,
2224 sig_info.sig_md, sig_info.sig_opts );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002225 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002226
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002227 /* Key size */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
Hanno Becker5226c532019-02-27 17:38:40 +00002229 mbedtls_pk_get_name( &pk ) ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002230 {
2231 return( ret );
2232 }
2233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002234 ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
Hanno Becker5226c532019-02-27 17:38:40 +00002235 (int) mbedtls_pk_get_bitlen( &pk ) );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002236 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002237
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002238 /*
2239 * Optional extensions
2240 */
2241
Hanno Becker5226c532019-02-27 17:38:40 +00002242 if( frame.ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002243 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
Hanno Becker5226c532019-02-27 17:38:40 +00002245 frame.ca_istrue ? "true" : "false" );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002246 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002247
Hanno Becker5226c532019-02-27 17:38:40 +00002248 if( frame.max_pathlen > 0 )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002249 {
Hanno Becker5226c532019-02-27 17:38:40 +00002250 ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", frame.max_pathlen - 1 );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002251 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002252 }
2253 }
2254
Hanno Becker5226c532019-02-27 17:38:40 +00002255 if( frame.ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002256 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002258 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002259
2260 if( ( ret = x509_info_subject_alt_name( &p, &n,
Hanno Becker5226c532019-02-27 17:38:40 +00002261 subject_alt_names ) ) != 0 )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002262 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002263 }
2264
Hanno Becker5226c532019-02-27 17:38:40 +00002265 if( frame.ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002266 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002267 ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002268 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02002269
Hanno Becker5226c532019-02-27 17:38:40 +00002270 if( ( ret = x509_info_cert_type( &p, &n, frame.ns_cert_type ) ) != 0 )
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02002271 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002272 }
2273
Hanno Becker5226c532019-02-27 17:38:40 +00002274 if( frame.ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002275 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002277 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002278
Hanno Becker5226c532019-02-27 17:38:40 +00002279 if( ( ret = x509_info_key_usage( &p, &n, frame.key_usage ) ) != 0 )
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002280 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002281 }
2282
Hanno Becker5226c532019-02-27 17:38:40 +00002283 if( frame.ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002284 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002285 ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002286 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002287
2288 if( ( ret = x509_info_ext_key_usage( &p, &n,
Hanno Becker5226c532019-02-27 17:38:40 +00002289 ext_key_usage ) ) != 0 )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002290 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002291 }
2292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002293 ret = mbedtls_snprintf( p, n, "\n" );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002294 MBEDTLS_X509_SAFE_SNPRINTF_WITH_ERROR;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002295
Hanno Becker4f869ed2019-02-24 16:47:57 +00002296 ret = (int) ( size - n );
2297
2298cleanup:
2299
Hanno Becker4f869ed2019-02-24 16:47:57 +00002300 x509_crt_free_sig_info( &sig_info );
Hanno Becker5226c532019-02-27 17:38:40 +00002301 mbedtls_pk_free( &pk );
2302 mbedtls_x509_name_free( issuer );
2303 mbedtls_x509_name_free( subject );
2304 mbedtls_x509_sequence_free( ext_key_usage );
2305 mbedtls_x509_sequence_free( subject_alt_names );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002306
2307 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002308}
2309
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002310struct x509_crt_verify_string {
2311 int code;
2312 const char *string;
2313};
2314
2315static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002316 { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002317 { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
2318 { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" },
2319 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" },
2320 { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" },
2321 { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002322 { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" },
2323 { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" },
2324 { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002325 { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002326 { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" },
2327 { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" },
2328 { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
2329 { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" },
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002330 { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." },
2331 { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
2332 { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
2333 { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." },
2334 { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
2335 { 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 +01002336 { 0, NULL }
2337};
2338
2339int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02002340 uint32_t flags )
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002341{
2342 int ret;
2343 const struct x509_crt_verify_string *cur;
2344 char *p = buf;
2345 size_t n = size;
2346
2347 for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
2348 {
2349 if( ( flags & cur->code ) == 0 )
2350 continue;
2351
2352 ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002353 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002354 flags ^= cur->code;
2355 }
2356
2357 if( flags != 0 )
2358 {
2359 ret = mbedtls_snprintf( p, n, "%sUnknown reason "
2360 "(this should not happen)\n", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002361 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002362 }
2363
2364 return( (int) ( size - n ) );
2365}
Hanno Becker02a21932019-06-10 15:08:43 +01002366#endif /* !MBEDTLS_X509_REMOVE_INFO */
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Hanno Becker45eedf12019-02-25 13:55:33 +00002369static int x509_crt_check_key_usage_frame( const mbedtls_x509_crt_frame *crt,
2370 unsigned int usage )
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002371{
Manuel Pégourié-Gonnard655a9642015-06-23 10:48:44 +02002372 unsigned int usage_must, usage_may;
2373 unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
2374 | MBEDTLS_X509_KU_DECIPHER_ONLY;
2375
2376 if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
2377 return( 0 );
2378
2379 usage_must = usage & ~may_mask;
2380
2381 if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
2382 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
2383
2384 usage_may = usage & may_mask;
2385
2386 if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002388
2389 return( 0 );
2390}
Hanno Becker45eedf12019-02-25 13:55:33 +00002391
2392int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
2393 unsigned int usage )
2394{
2395 int ret;
2396 mbedtls_x509_crt_frame *frame;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002397 ret = mbedtls_x509_crt_frame_acquire( crt,
2398 (mbedtls_x509_crt_frame**) &frame );
Hanno Becker45eedf12019-02-25 13:55:33 +00002399 if( ret != 0 )
2400 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2401
2402 ret = x509_crt_check_key_usage_frame( frame, usage );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002403 mbedtls_x509_crt_frame_release( crt, (mbedtls_x509_crt_frame*) frame );
Hanno Becker45eedf12019-02-25 13:55:33 +00002404
2405 return( ret );
2406}
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002407#endif
2408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002409#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
Hanno Beckerc7c638e2019-02-21 21:10:51 +00002410typedef struct
2411{
2412 const char *oid;
2413 size_t oid_len;
2414} x509_crt_check_ext_key_usage_cb_ctx_t;
2415
2416static int x509_crt_check_ext_key_usage_cb( void *ctx,
2417 int tag,
2418 unsigned char *data,
2419 size_t data_len )
2420{
2421 x509_crt_check_ext_key_usage_cb_ctx_t *cb_ctx =
2422 (x509_crt_check_ext_key_usage_cb_ctx_t *) ctx;
2423 ((void) tag);
2424
2425 if( MBEDTLS_OID_CMP_RAW( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE,
2426 data, data_len ) == 0 )
2427 {
2428 return( 1 );
2429 }
2430
2431 if( data_len == cb_ctx->oid_len && memcmp( data, cb_ctx->oid,
2432 data_len ) == 0 )
2433 {
2434 return( 1 );
2435 }
2436
2437 return( 0 );
2438}
2439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002440int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
Hanno Beckere1956af2019-02-21 14:28:12 +00002441 const char *usage_oid,
2442 size_t usage_len )
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002443{
Hanno Beckere1956af2019-02-21 14:28:12 +00002444 int ret;
Hanno Beckere9718b42019-02-25 18:11:42 +00002445 mbedtls_x509_crt_frame *frame;
Hanno Beckere1956af2019-02-21 14:28:12 +00002446 unsigned ext_types;
2447 unsigned char *p, *end;
Hanno Beckerc7c638e2019-02-21 21:10:51 +00002448 x509_crt_check_ext_key_usage_cb_ctx_t cb_ctx = { usage_oid, usage_len };
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002449
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002450 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Beckere9718b42019-02-25 18:11:42 +00002451 if( ret != 0 )
2452 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2453
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002454 /* Extension is not mandatory, absent means no restriction */
Hanno Beckere9718b42019-02-25 18:11:42 +00002455 ext_types = frame->ext_types;
2456 if( ( ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) != 0 )
2457 {
2458 p = frame->ext_key_usage_raw.p;
2459 end = p + frame->ext_key_usage_raw.len;
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002460
Hanno Beckere9718b42019-02-25 18:11:42 +00002461 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
2462 0xFF, MBEDTLS_ASN1_OID, 0, 0,
2463 x509_crt_check_ext_key_usage_cb,
2464 &cb_ctx );
2465 if( ret == 1 )
2466 ret = 0;
2467 else
2468 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
2469 }
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002470
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002471 mbedtls_x509_crt_frame_release( crt, frame );
Hanno Beckere9718b42019-02-25 18:11:42 +00002472 return( ret );
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002473}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002474#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002476#if defined(MBEDTLS_X509_CRL_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002477/*
2478 * Return 1 if the certificate is revoked, or 0 otherwise.
2479 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002480static int x509_serial_is_revoked( unsigned char const *serial,
2481 size_t serial_len,
2482 const mbedtls_x509_crl *crl )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002483{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 const mbedtls_x509_crl_entry *cur = &crl->entry;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002485
2486 while( cur != NULL && cur->serial.len != 0 )
2487 {
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002488 if( serial_len == cur->serial.len &&
2489 memcmp( serial, cur->serial.p, serial_len ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002490 {
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002491 if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002492 return( 1 );
2493 }
2494
2495 cur = cur->next;
2496 }
2497
2498 return( 0 );
2499}
2500
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002501int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt,
2502 const mbedtls_x509_crl *crl )
2503{
Hanno Becker79ae5b62019-02-25 18:12:00 +00002504 int ret;
2505 mbedtls_x509_crt_frame *frame;
2506
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002507 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Becker79ae5b62019-02-25 18:12:00 +00002508 if( ret != 0 )
2509 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2510
2511 ret = x509_serial_is_revoked( frame->serial.p,
2512 frame->serial.len,
2513 crl );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002514 mbedtls_x509_crt_frame_release( crt, frame );
Hanno Becker79ae5b62019-02-25 18:12:00 +00002515 return( ret );
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002516}
2517
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002518/*
Manuel Pégourié-Gonnardeeef9472016-02-22 11:36:55 +01002519 * Check that the given certificate is not revoked according to the CRL.
Manuel Pégourié-Gonnard08eacec2017-10-18 14:20:24 +02002520 * Skip validation if no CRL for the given CA is present.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002521 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002522static int x509_crt_verifycrl( unsigned char *crt_serial,
2523 size_t crt_serial_len,
Hanno Beckerbb266132019-02-25 18:12:46 +00002524 mbedtls_x509_crt *ca_crt,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002525 mbedtls_x509_crl *crl_list,
2526 const mbedtls_x509_crt_profile *profile )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002527{
Hanno Beckerbb266132019-02-25 18:12:46 +00002528 int ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002529 int flags = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002530 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
2531 const mbedtls_md_info_t *md_info;
Hanno Beckerbb266132019-02-25 18:12:46 +00002532 mbedtls_x509_buf_raw ca_subject;
2533 mbedtls_pk_context *pk;
2534 int can_sign;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002535
Hanno Beckerbb266132019-02-25 18:12:46 +00002536 if( ca_crt == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002537 return( flags );
2538
Hanno Beckerbb266132019-02-25 18:12:46 +00002539 {
2540 mbedtls_x509_crt_frame *ca;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002541 ret = mbedtls_x509_crt_frame_acquire( ca_crt, &ca );
Hanno Beckerbb266132019-02-25 18:12:46 +00002542 if( ret != 0 )
2543 return( MBEDTLS_X509_BADCRL_NOT_TRUSTED );
2544
2545 ca_subject = ca->subject_raw;
2546
2547 can_sign = 0;
2548 if( x509_crt_check_key_usage_frame( ca,
2549 MBEDTLS_X509_KU_CRL_SIGN ) == 0 )
2550 {
2551 can_sign = 1;
2552 }
2553
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002554 mbedtls_x509_crt_frame_release( ca_crt, ca );
Hanno Beckerbb266132019-02-25 18:12:46 +00002555 }
2556
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002557 ret = mbedtls_x509_crt_pk_acquire( ca_crt, &pk );
Hanno Beckerbb266132019-02-25 18:12:46 +00002558 if( ret != 0 )
2559 return( MBEDTLS_X509_BADCRL_NOT_TRUSTED );
2560
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002561 while( crl_list != NULL )
2562 {
2563 if( crl_list->version == 0 ||
Hanno Becker7dee12a2019-02-21 13:58:38 +00002564 mbedtls_x509_name_cmp_raw( &crl_list->issuer_raw_no_hdr,
Hanno Beckerbb266132019-02-25 18:12:46 +00002565 &ca_subject, NULL, NULL ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002566 {
2567 crl_list = crl_list->next;
2568 continue;
2569 }
2570
2571 /*
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002572 * Check if the CA is configured to sign CRLs
2573 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Hanno Beckerbb266132019-02-25 18:12:46 +00002575 if( !can_sign )
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002576 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002578 break;
2579 }
2580#endif
2581
2582 /*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002583 * Check if CRL is correctly signed by the trusted CA
2584 */
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002585 if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
2586 flags |= MBEDTLS_X509_BADCRL_BAD_MD;
2587
2588 if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
2589 flags |= MBEDTLS_X509_BADCRL_BAD_PK;
2590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 md_info = mbedtls_md_info_from_type( crl_list->sig_md );
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02002592 if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002593 {
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02002594 /* Note: this can't happen except after an internal error */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002596 break;
2597 }
2598
Hanno Beckerbb266132019-02-25 18:12:46 +00002599 if( x509_profile_check_key( profile, pk ) != 0 )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002600 flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002601
Hanno Beckerbb266132019-02-25 18:12:46 +00002602 if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, pk,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002603 crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
Manuel Pégourié-Gonnard53882022014-06-05 17:53:52 +02002604 crl_list->sig.p, crl_list->sig.len ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002605 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002607 break;
2608 }
2609
2610 /*
2611 * Check for validity of CRL (Do not drop out)
2612 */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002613 if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 flags |= MBEDTLS_X509_BADCRL_EXPIRED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002615
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002616 if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002617 flags |= MBEDTLS_X509_BADCRL_FUTURE;
Manuel Pégourié-Gonnard95337652014-03-10 13:15:18 +01002618
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002619 /*
2620 * Check if certificate is revoked
2621 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002622 if( x509_serial_is_revoked( crt_serial, crt_serial_len,
2623 crl_list ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002624 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002625 flags |= MBEDTLS_X509_BADCERT_REVOKED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002626 break;
2627 }
2628
2629 crl_list = crl_list->next;
2630 }
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002631
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002632 mbedtls_x509_crt_pk_release( ca_crt, pk );
Paul Bakkerd8bb8262014-06-17 14:06:49 +02002633 return( flags );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002634}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635#endif /* MBEDTLS_X509_CRL_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002636
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02002637/*
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002638 * Check the signature of a certificate by its parent
2639 */
Hanno Becker5299cf82019-02-25 13:50:41 +00002640static int x509_crt_check_signature( const mbedtls_x509_crt_sig_info *sig_info,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002641 mbedtls_x509_crt *parent,
2642 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002643{
Hanno Beckere449e2d2019-02-25 14:45:31 +00002644 int ret;
2645 mbedtls_pk_context *pk;
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002646
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002647 ret = mbedtls_x509_crt_pk_acquire( parent, &pk );
Hanno Beckere449e2d2019-02-25 14:45:31 +00002648 if( ret != 0 )
2649 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2650
2651 /* Skip expensive computation on obvious mismatch */
2652 if( ! mbedtls_pk_can_do( pk, sig_info->sig_pk ) )
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002653 {
Hanno Beckere449e2d2019-02-25 14:45:31 +00002654 ret = -1;
2655 goto exit;
2656 }
2657
2658#if !( defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) )
2659 ((void) rs_ctx);
2660#else
2661 if( rs_ctx != NULL && sig_info->sig_pk == MBEDTLS_PK_ECDSA )
2662 {
2663 ret = mbedtls_pk_verify_restartable( pk,
Hanno Becker5299cf82019-02-25 13:50:41 +00002664 sig_info->sig_md,
2665 sig_info->crt_hash, sig_info->crt_hash_len,
2666 sig_info->sig.p, sig_info->sig.len,
Hanno Beckere449e2d2019-02-25 14:45:31 +00002667 &rs_ctx->pk );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002668 }
Hanno Beckere449e2d2019-02-25 14:45:31 +00002669 else
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002670#endif
Hanno Beckere449e2d2019-02-25 14:45:31 +00002671 {
2672 ret = mbedtls_pk_verify_ext( sig_info->sig_pk,
2673 sig_info->sig_opts,
2674 pk,
2675 sig_info->sig_md,
2676 sig_info->crt_hash, sig_info->crt_hash_len,
2677 sig_info->sig.p, sig_info->sig.len );
2678 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002679
Hanno Beckere449e2d2019-02-25 14:45:31 +00002680exit:
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002681 mbedtls_x509_crt_pk_release( parent, pk );
Hanno Beckere449e2d2019-02-25 14:45:31 +00002682 return( ret );
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002683}
2684
2685/*
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002686 * Check if 'parent' is a suitable parent (signing CA) for 'child'.
2687 * Return 0 if yes, -1 if not.
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002688 *
2689 * top means parent is a locally-trusted certificate
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002690 */
Hanno Becker43bf9002019-02-25 14:46:49 +00002691static int x509_crt_check_parent( const mbedtls_x509_crt_sig_info *sig_info,
2692 const mbedtls_x509_crt_frame *parent,
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002693 int top )
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002694{
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002695 int need_ca_bit;
2696
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02002697 /* Parent must be the issuer */
Hanno Becker43bf9002019-02-25 14:46:49 +00002698 if( mbedtls_x509_name_cmp_raw( &sig_info->issuer_raw,
2699 &parent->subject_raw,
Hanno Becker67284cc2019-02-21 14:31:51 +00002700 NULL, NULL ) != 0 )
Hanno Becker7dee12a2019-02-21 13:58:38 +00002701 {
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002702 return( -1 );
Hanno Becker7dee12a2019-02-21 13:58:38 +00002703 }
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002704
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002705 /* Parent must have the basicConstraints CA bit set as a general rule */
2706 need_ca_bit = 1;
2707
2708 /* Exception: v1/v2 certificates that are locally trusted. */
2709 if( top && parent->version < 3 )
2710 need_ca_bit = 0;
2711
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002712 if( need_ca_bit && ! parent->ca_istrue )
2713 return( -1 );
2714
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002715#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002716 if( need_ca_bit &&
Hanno Becker43bf9002019-02-25 14:46:49 +00002717 x509_crt_check_key_usage_frame( parent,
2718 MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02002719 {
2720 return( -1 );
2721 }
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002722#endif
2723
2724 return( 0 );
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002725}
2726
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002727/*
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002728 * Find a suitable parent for child in candidates, or return NULL.
2729 *
2730 * Here suitable is defined as:
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002731 * 1. subject name matches child's issuer
2732 * 2. if necessary, the CA bit is set and key usage allows signing certs
2733 * 3. for trusted roots, the signature is correct
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002734 * (for intermediates, the signature is checked and the result reported)
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002735 * 4. pathlen constraints are satisfied
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002736 *
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002737 * If there's a suitable candidate which is also time-valid, return the first
2738 * such. Otherwise, return the first suitable candidate (or NULL if there is
2739 * none).
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002740 *
2741 * The rationale for this rule is that someone could have a list of trusted
2742 * roots with two versions on the same root with different validity periods.
2743 * (At least one user reported having such a list and wanted it to just work.)
2744 * The reason we don't just require time-validity is that generally there is
2745 * only one version, and if it's expired we want the flags to state that
2746 * rather than NOT_TRUSTED, as would be the case if we required it here.
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002747 *
2748 * The rationale for rule 3 (signature for trusted roots) is that users might
2749 * have two versions of the same CA with different keys in their list, and the
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002750 * way we select the correct one is by checking the signature (as we don't
2751 * rely on key identifier extensions). (This is one way users might choose to
2752 * handle key rollover, another relies on self-issued certs, see [SIRO].)
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002753 *
2754 * Arguments:
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002755 * - [in] child: certificate for which we're looking for a parent
2756 * - [in] candidates: chained list of potential parents
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002757 * - [out] r_parent: parent found (or NULL)
2758 * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002759 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
2760 * of the chain, 0 otherwise
2761 * - [in] path_cnt: number of intermediates seen so far
2762 * - [in] self_cnt: number of self-signed intermediates seen so far
2763 * (will never be greater than path_cnt)
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002764 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002765 *
2766 * Return value:
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002767 * - 0 on success
2768 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002769 */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002770static int x509_crt_find_parent_in(
Hanno Becker5299cf82019-02-25 13:50:41 +00002771 mbedtls_x509_crt_sig_info const *child_sig,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002772 mbedtls_x509_crt *candidates,
2773 mbedtls_x509_crt **r_parent,
2774 int *r_signature_is_good,
2775 int top,
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002776 unsigned path_cnt,
2777 unsigned self_cnt,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002778 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002779{
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002780 int ret;
Hanno Becker43bf9002019-02-25 14:46:49 +00002781 mbedtls_x509_crt *parent_crt, *fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002782 int signature_is_good, fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002783
2784#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002785 /* did we have something in progress? */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002786 if( rs_ctx != NULL && rs_ctx->parent != NULL )
2787 {
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002788 /* restore saved state */
Hanno Becker43bf9002019-02-25 14:46:49 +00002789 parent_crt = rs_ctx->parent;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002790 fallback_parent = rs_ctx->fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002791 fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002792
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002793 /* clear saved state */
2794 rs_ctx->parent = NULL;
2795 rs_ctx->fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002796 rs_ctx->fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002797
2798 /* resume where we left */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002799 goto check_signature;
2800 }
2801#endif
2802
2803 fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002804 fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002805
Hanno Becker43bf9002019-02-25 14:46:49 +00002806 for( parent_crt = candidates; parent_crt != NULL;
2807 parent_crt = parent_crt->next )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002808 {
Hanno Beckera788cab2019-02-24 17:47:46 +00002809 int parent_valid, parent_match, path_len_ok;
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002810
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002811#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2812check_signature:
2813#endif
Hanno Beckera788cab2019-02-24 17:47:46 +00002814
2815 parent_valid = parent_match = path_len_ok = 0;
Hanno Beckera788cab2019-02-24 17:47:46 +00002816 {
Hanno Becker43bf9002019-02-25 14:46:49 +00002817 mbedtls_x509_crt_frame *parent;
Hanno Beckera788cab2019-02-24 17:47:46 +00002818
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002819 ret = mbedtls_x509_crt_frame_acquire( parent_crt, &parent );
Hanno Becker43bf9002019-02-25 14:46:49 +00002820 if( ret != 0 )
2821 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Hanno Beckera788cab2019-02-24 17:47:46 +00002822
Hanno Becker43bf9002019-02-25 14:46:49 +00002823 if( mbedtls_x509_time_is_past( &parent->valid_from ) &&
2824 mbedtls_x509_time_is_future( &parent->valid_to ) )
2825 {
2826 parent_valid = 1;
2827 }
2828
2829 /* basic parenting skills (name, CA bit, key usage) */
2830 if( x509_crt_check_parent( child_sig, parent, top ) == 0 )
2831 parent_match = 1;
2832
2833 /* +1 because the stored max_pathlen is 1 higher
2834 * than the actual value */
2835 if( !( parent->max_pathlen > 0 &&
2836 (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) )
2837 {
2838 path_len_ok = 1;
2839 }
2840
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002841 mbedtls_x509_crt_frame_release( parent_crt, parent );
Hanno Beckera788cab2019-02-24 17:47:46 +00002842 }
2843
2844 if( parent_match == 0 || path_len_ok == 0 )
2845 continue;
2846
2847 /* Signature */
Hanno Becker43bf9002019-02-25 14:46:49 +00002848 ret = x509_crt_check_signature( child_sig, parent_crt, rs_ctx );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002849
2850#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002851 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
2852 {
2853 /* save state */
Hanno Becker43bf9002019-02-25 14:46:49 +00002854 rs_ctx->parent = parent_crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002855 rs_ctx->fallback_parent = fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002856 rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002857
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002858 return( ret );
2859 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002860#else
2861 (void) ret;
2862#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002863
2864 signature_is_good = ret == 0;
2865 if( top && ! signature_is_good )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002866 continue;
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002867
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002868 /* optional time check */
Hanno Beckera788cab2019-02-24 17:47:46 +00002869 if( !parent_valid )
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002870 {
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002871 if( fallback_parent == NULL )
2872 {
Hanno Becker43bf9002019-02-25 14:46:49 +00002873 fallback_parent = parent_crt;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002874 fallback_signature_is_good = signature_is_good;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002875 }
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002876
2877 continue;
2878 }
2879
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002880 break;
2881 }
2882
Hanno Becker43bf9002019-02-25 14:46:49 +00002883 if( parent_crt != NULL )
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002884 {
Hanno Becker43bf9002019-02-25 14:46:49 +00002885 *r_parent = parent_crt;
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002886 *r_signature_is_good = signature_is_good;
2887 }
2888 else
2889 {
2890 *r_parent = fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002891 *r_signature_is_good = fallback_signature_is_good;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002892 }
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002893
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002894 return( 0 );
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002895}
2896
2897/*
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002898 * Find a parent in trusted CAs or the provided chain, or return NULL.
2899 *
2900 * Searches in trusted CAs first, and return the first suitable parent found
2901 * (see find_parent_in() for definition of suitable).
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002902 *
2903 * Arguments:
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002904 * - [in] child: certificate for which we're looking for a parent, followed
2905 * by a chain of possible intermediates
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002906 * - [in] trust_ca: list of locally trusted certificates
2907 * - [out] parent: parent found (or NULL)
2908 * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
2909 * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
2910 * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
2911 * - [in] self_cnt: number of self-signed certs in the chain so far
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002912 * (will always be no greater than path_cnt)
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002913 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002914 *
2915 * Return value:
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002916 * - 0 on success
2917 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002918 */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002919static int x509_crt_find_parent(
Hanno Becker5299cf82019-02-25 13:50:41 +00002920 mbedtls_x509_crt_sig_info const *child_sig,
Hanno Becker1e0677a2019-02-25 14:58:22 +00002921 mbedtls_x509_crt *rest,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002922 mbedtls_x509_crt *trust_ca,
2923 mbedtls_x509_crt **parent,
2924 int *parent_is_trusted,
2925 int *signature_is_good,
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002926 unsigned path_cnt,
2927 unsigned self_cnt,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002928 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002929{
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002930 int ret;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002931 mbedtls_x509_crt *search_list;
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002932
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002933 *parent_is_trusted = 1;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002934
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002935#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002936 /* restore then clear saved state if we have some stored */
2937 if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
2938 {
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002939 *parent_is_trusted = rs_ctx->parent_is_trusted;
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002940 rs_ctx->parent_is_trusted = -1;
2941 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002942#endif
2943
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002944 while( 1 ) {
Hanno Becker1e0677a2019-02-25 14:58:22 +00002945 search_list = *parent_is_trusted ? trust_ca : rest;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002946
Hanno Becker5299cf82019-02-25 13:50:41 +00002947 ret = x509_crt_find_parent_in( child_sig, search_list,
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002948 parent, signature_is_good,
2949 *parent_is_trusted,
2950 path_cnt, self_cnt, rs_ctx );
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002951
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002952#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002953 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
2954 {
2955 /* save state */
2956 rs_ctx->parent_is_trusted = *parent_is_trusted;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002957 return( ret );
2958 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002959#else
2960 (void) ret;
2961#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002962
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002963 /* stop here if found or already in second iteration */
2964 if( *parent != NULL || *parent_is_trusted == 0 )
2965 break;
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002966
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002967 /* prepare second iteration */
2968 *parent_is_trusted = 0;
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002969 }
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002970
2971 /* extra precaution against mistakes in the caller */
Krzysztof Stachowiakc388a8c2018-10-31 16:49:20 +01002972 if( *parent == NULL )
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002973 {
Manuel Pégourié-Gonnarda5a3e402018-10-16 11:27:23 +02002974 *parent_is_trusted = 0;
2975 *signature_is_good = 0;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002976 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002977
2978 return( 0 );
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002979}
2980
2981/*
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002982 * Check if an end-entity certificate is locally trusted
2983 *
2984 * Currently we require such certificates to be self-signed (actually only
2985 * check for self-issued as self-signatures are not checked)
2986 */
2987static int x509_crt_check_ee_locally_trusted(
Hanno Becker1e0677a2019-02-25 14:58:22 +00002988 mbedtls_x509_crt_frame const *crt,
2989 mbedtls_x509_crt const *trust_ca )
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002990{
Hanno Becker1e0677a2019-02-25 14:58:22 +00002991 mbedtls_x509_crt const *cur;
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002992
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002993 /* look for an exact match with trusted cert */
2994 for( cur = trust_ca; cur != NULL; cur = cur->next )
2995 {
2996 if( crt->raw.len == cur->raw.len &&
2997 memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
2998 {
2999 return( 0 );
3000 }
3001 }
3002
3003 /* too bad */
3004 return( -1 );
3005}
3006
3007/*
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003008 * Build and verify a certificate chain
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02003009 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003010 * Given a peer-provided list of certificates EE, C1, ..., Cn and
3011 * a list of trusted certs R1, ... Rp, try to build and verify a chain
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02003012 * EE, Ci1, ... Ciq [, Rj]
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003013 * such that every cert in the chain is a child of the next one,
3014 * jumping to a trusted root as early as possible.
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003015 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003016 * Verify that chain and return it with flags for all issues found.
3017 *
3018 * Special cases:
3019 * - EE == Rj -> return a one-element list containing it
3020 * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
3021 * -> return that chain with NOT_TRUSTED set on Ciq
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003022 *
Manuel Pégourié-Gonnardd19a41d2017-07-14 11:05:59 +02003023 * Tests for (aspects of) this function should include at least:
3024 * - trusted EE
3025 * - EE -> trusted root
3026 * - EE -> intermedate CA -> trusted root
3027 * - if relevant: EE untrusted
3028 * - if relevant: EE -> intermediate, untrusted
3029 * with the aspect under test checked at each relevant level (EE, int, root).
3030 * For some aspects longer chains are required, but usually length 2 is
3031 * enough (but length 1 is not in general).
3032 *
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003033 * Arguments:
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003034 * - [in] crt: the cert list EE, C1, ..., Cn
3035 * - [in] trust_ca: the trusted list R1, ..., Rp
3036 * - [in] ca_crl, profile: as in verify_with_profile()
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003037 * - [out] ver_chain: the built and verified chain
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02003038 * Only valid when return value is 0, may contain garbage otherwise!
3039 * Restart note: need not be the same when calling again to resume.
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02003040 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003041 *
3042 * Return value:
3043 * - non-zero if the chain could not be fully built and examined
3044 * - 0 is the chain was successfully built and examined,
3045 * even if it was found to be invalid
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02003046 */
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003047static int x509_crt_verify_chain(
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003048 mbedtls_x509_crt *crt,
3049 mbedtls_x509_crt *trust_ca,
3050 mbedtls_x509_crl *ca_crl,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003051 const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003052 mbedtls_x509_crt_verify_chain *ver_chain,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003053 mbedtls_x509_crt_restart_ctx *rs_ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003054{
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02003055 /* Don't initialize any of those variables here, so that the compiler can
3056 * catch potential issues with jumping ahead when restarting */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003057 int ret;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003058 uint32_t *flags;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003059 mbedtls_x509_crt_verify_chain_item *cur;
Hanno Becker1e0677a2019-02-25 14:58:22 +00003060 mbedtls_x509_crt *child_crt;
Hanno Becker58c35642019-02-25 18:13:46 +00003061 mbedtls_x509_crt *parent_crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003062 int parent_is_trusted;
3063 int child_is_trusted;
3064 int signature_is_good;
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02003065 unsigned self_cnt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003066
3067#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3068 /* resume if we had an operation in progress */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003069 if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003070 {
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02003071 /* restore saved state */
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02003072 *ver_chain = rs_ctx->ver_chain; /* struct copy */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003073 self_cnt = rs_ctx->self_cnt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003074
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003075 /* restore derived state */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003076 cur = &ver_chain->items[ver_chain->len - 1];
Hanno Becker1e0677a2019-02-25 14:58:22 +00003077 child_crt = cur->crt;
3078
3079 child_is_trusted = 0;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003080 goto find_parent;
3081 }
3082#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02003083
Hanno Becker1e0677a2019-02-25 14:58:22 +00003084 child_crt = crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003085 self_cnt = 0;
3086 parent_is_trusted = 0;
3087 child_is_trusted = 0;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003088
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003089 while( 1 ) {
Hanno Becker5299cf82019-02-25 13:50:41 +00003090#if defined(MBEDTLS_X509_CRL_PARSE_C)
3091 mbedtls_x509_buf_raw child_serial;
3092#endif /* MBEDTLS_X509_CRL_PARSE_C */
3093 int self_issued;
Hanno Becker1e0677a2019-02-25 14:58:22 +00003094
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003095 /* Add certificate to the verification chain */
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003096 cur = &ver_chain->items[ver_chain->len];
Hanno Becker1e0677a2019-02-25 14:58:22 +00003097 cur->crt = child_crt;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003098 cur->flags = 0;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003099 ver_chain->len++;
Hanno Becker10e6b9b2019-02-22 17:56:43 +00003100
3101#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3102find_parent:
3103#endif
3104
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003105 flags = &cur->flags;
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02003106
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003107 {
Hanno Becker5299cf82019-02-25 13:50:41 +00003108 mbedtls_x509_crt_sig_info child_sig;
3109 {
3110 mbedtls_x509_crt_frame *child;
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02003111
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003112 ret = mbedtls_x509_crt_frame_acquire( child_crt, &child );
Hanno Becker5299cf82019-02-25 13:50:41 +00003113 if( ret != 0 )
3114 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3115
3116 /* Check time-validity (all certificates) */
3117 if( mbedtls_x509_time_is_past( &child->valid_to ) )
3118 *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
3119 if( mbedtls_x509_time_is_future( &child->valid_from ) )
3120 *flags |= MBEDTLS_X509_BADCERT_FUTURE;
3121
3122 /* Stop here for trusted roots (but not for trusted EE certs) */
3123 if( child_is_trusted )
3124 {
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003125 mbedtls_x509_crt_frame_release( child_crt, child );
Hanno Becker5299cf82019-02-25 13:50:41 +00003126 return( 0 );
3127 }
3128
3129 self_issued = 0;
3130 if( mbedtls_x509_name_cmp_raw( &child->issuer_raw,
3131 &child->subject_raw,
3132 NULL, NULL ) == 0 )
3133 {
3134 self_issued = 1;
3135 }
3136
3137 /* Check signature algorithm: MD & PK algs */
3138 if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
3139 *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
3140
3141 if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
3142 *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
3143
3144 /* Special case: EE certs that are locally trusted */
3145 if( ver_chain->len == 1 && self_issued &&
3146 x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
3147 {
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003148 mbedtls_x509_crt_frame_release( child_crt, child );
Hanno Becker5299cf82019-02-25 13:50:41 +00003149 return( 0 );
3150 }
3151
3152#if defined(MBEDTLS_X509_CRL_PARSE_C)
3153 child_serial = child->serial;
3154#endif /* MBEDTLS_X509_CRL_PARSE_C */
3155
3156 ret = x509_crt_get_sig_info( child, &child_sig );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003157 mbedtls_x509_crt_frame_release( child_crt, child );
Hanno Becker5299cf82019-02-25 13:50:41 +00003158
Hanno Becker5299cf82019-02-25 13:50:41 +00003159 if( ret != 0 )
3160 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3161 }
3162
3163 /* Look for a parent in trusted CAs or up the chain */
3164 ret = x509_crt_find_parent( &child_sig, child_crt->next,
Hanno Becker58c35642019-02-25 18:13:46 +00003165 trust_ca, &parent_crt,
Hanno Becker5299cf82019-02-25 13:50:41 +00003166 &parent_is_trusted, &signature_is_good,
3167 ver_chain->len - 1, self_cnt, rs_ctx );
3168
3169 x509_crt_free_sig_info( &child_sig );
3170 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003171
3172#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003173 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
3174 {
3175 /* save state */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003176 rs_ctx->in_progress = x509_crt_rs_find_parent;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003177 rs_ctx->self_cnt = self_cnt;
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02003178 rs_ctx->ver_chain = *ver_chain; /* struct copy */
Hanno Becker5299cf82019-02-25 13:50:41 +00003179 return( ret );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003180 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003181#else
3182 (void) ret;
3183#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003184
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003185 /* No parent? We're done here */
Hanno Becker58c35642019-02-25 18:13:46 +00003186 if( parent_crt == NULL )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003187 {
3188 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
Hanno Becker5299cf82019-02-25 13:50:41 +00003189 return( 0 );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003190 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003191
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003192 /* Count intermediate self-issued (not necessarily self-signed) certs.
3193 * These can occur with some strategies for key rollover, see [SIRO],
3194 * and should be excluded from max_pathlen checks. */
Hanno Becker5299cf82019-02-25 13:50:41 +00003195 if( ver_chain->len != 1 && self_issued )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003196 self_cnt++;
Manuel Pégourié-Gonnardfd6c85c2014-11-20 16:34:20 +01003197
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003198 /* path_cnt is 0 for the first intermediate CA,
3199 * and if parent is trusted it's not an intermediate CA */
3200 if( ! parent_is_trusted &&
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003201 ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003202 {
3203 /* return immediately to avoid overflow the chain array */
Hanno Becker5299cf82019-02-25 13:50:41 +00003204 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003205 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003206
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02003207 /* signature was checked while searching parent */
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02003208 if( ! signature_is_good )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003209 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
3210
Hanno Becker58c35642019-02-25 18:13:46 +00003211 {
3212 mbedtls_pk_context *parent_pk;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003213 ret = mbedtls_x509_crt_pk_acquire( parent_crt, &parent_pk );
Hanno Becker58c35642019-02-25 18:13:46 +00003214 if( ret != 0 )
3215 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3216
3217 /* check size of signing key */
3218 if( x509_profile_check_key( profile, parent_pk ) != 0 )
3219 *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
3220
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003221 mbedtls_x509_crt_pk_release( parent_crt, parent_pk );
Hanno Becker58c35642019-02-25 18:13:46 +00003222 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003223
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003224#if defined(MBEDTLS_X509_CRL_PARSE_C)
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003225 /* Check trusted CA's CRL for the given crt */
Hanno Becker5299cf82019-02-25 13:50:41 +00003226 *flags |= x509_crt_verifycrl( child_serial.p,
3227 child_serial.len,
Hanno Becker58c35642019-02-25 18:13:46 +00003228 parent_crt, ca_crl, profile );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003229#else
3230 (void) ca_crl;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003231#endif
3232
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003233 /* prepare for next iteration */
Hanno Becker58c35642019-02-25 18:13:46 +00003234 child_crt = parent_crt;
3235 parent_crt = NULL;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003236 child_is_trusted = parent_is_trusted;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02003237 signature_is_good = 0;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003238 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003239}
3240
3241/*
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003242 * Check for CN match
3243 */
Hanno Becker24926222019-02-21 13:10:55 +00003244static int x509_crt_check_cn( unsigned char const *buf,
3245 size_t buflen,
3246 const char *cn,
3247 size_t cn_len )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003248{
Hanno Becker24926222019-02-21 13:10:55 +00003249 /* Try exact match */
Hanno Beckerb3def1d2019-02-22 11:46:06 +00003250 if( mbedtls_x509_memcasecmp( cn, buf, buflen, cn_len ) == 0 )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003251 return( 0 );
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003252
3253 /* try wildcard match */
Hanno Becker24926222019-02-21 13:10:55 +00003254 if( x509_check_wildcard( cn, cn_len, buf, buflen ) == 0 )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003255 {
3256 return( 0 );
3257 }
3258
3259 return( -1 );
3260}
3261
Hanno Becker8b543b32019-02-21 11:50:44 +00003262/* Returns 1 on a match and 0 on a mismatch.
3263 * This is because this function is used as a callback for
3264 * mbedtls_x509_name_cmp_raw(), which continues the name
3265 * traversal as long as the callback returns 0. */
3266static int x509_crt_check_name( void *ctx,
3267 mbedtls_x509_buf *oid,
Hanno Becker6b378122019-02-23 10:20:14 +00003268 mbedtls_x509_buf *val,
3269 int next_merged )
Hanno Becker8b543b32019-02-21 11:50:44 +00003270{
3271 char const *cn = (char const*) ctx;
3272 size_t cn_len = strlen( cn );
Hanno Becker6b378122019-02-23 10:20:14 +00003273 ((void) next_merged);
Hanno Becker8b543b32019-02-21 11:50:44 +00003274
3275 if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, oid ) == 0 &&
Hanno Becker24926222019-02-21 13:10:55 +00003276 x509_crt_check_cn( val->p, val->len, cn, cn_len ) == 0 )
Hanno Becker8b543b32019-02-21 11:50:44 +00003277 {
3278 return( 1 );
3279 }
3280
3281 return( 0 );
3282}
3283
Hanno Beckerda410822019-02-21 13:36:59 +00003284/* Returns 1 on a match and 0 on a mismatch.
3285 * This is because this function is used as a callback for
3286 * mbedtls_asn1_traverse_sequence_of(), which continues the
3287 * traversal as long as the callback returns 0. */
3288static int x509_crt_subject_alt_check_name( void *ctx,
3289 int tag,
3290 unsigned char *data,
3291 size_t data_len )
3292{
3293 char const *cn = (char const*) ctx;
3294 size_t cn_len = strlen( cn );
Hanno Becker90b94082019-02-21 21:13:21 +00003295 ((void) tag);
Hanno Beckerda410822019-02-21 13:36:59 +00003296
3297 if( x509_crt_check_cn( data, data_len, cn, cn_len ) == 0 )
3298 return( 1 );
3299
3300 return( 0 );
3301}
3302
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003303/*
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003304 * Verify the requested CN - only call this if cn is not NULL!
3305 */
Hanno Becker082435c2019-02-25 18:14:40 +00003306static int x509_crt_verify_name( const mbedtls_x509_crt *crt,
3307 const char *cn,
3308 uint32_t *flags )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003309{
Hanno Beckerda410822019-02-21 13:36:59 +00003310 int ret;
Hanno Becker082435c2019-02-25 18:14:40 +00003311 mbedtls_x509_crt_frame *frame;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003312
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003313 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Becker082435c2019-02-25 18:14:40 +00003314 if( ret != 0 )
3315 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3316
3317 if( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003318 {
Hanno Becker90b94082019-02-21 21:13:21 +00003319 unsigned char *p =
Hanno Becker082435c2019-02-25 18:14:40 +00003320 frame->subject_alt_raw.p;
Hanno Beckerda410822019-02-21 13:36:59 +00003321 const unsigned char *end =
Hanno Becker082435c2019-02-25 18:14:40 +00003322 frame->subject_alt_raw.p + frame->subject_alt_raw.len;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003323
Hanno Becker90b94082019-02-21 21:13:21 +00003324 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
3325 MBEDTLS_ASN1_TAG_CLASS_MASK,
3326 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
3327 MBEDTLS_ASN1_TAG_VALUE_MASK,
3328 2 /* SubjectAlt DNS */,
3329 x509_crt_subject_alt_check_name,
3330 (void*) cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003331 }
3332 else
3333 {
Hanno Becker082435c2019-02-25 18:14:40 +00003334 ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
3335 &frame->subject_raw,
Hanno Becker8b543b32019-02-21 11:50:44 +00003336 x509_crt_check_name, (void*) cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003337 }
Hanno Beckerda410822019-02-21 13:36:59 +00003338
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003339 mbedtls_x509_crt_frame_release( crt, frame );
Hanno Becker082435c2019-02-25 18:14:40 +00003340
3341 /* x509_crt_check_name() and x509_crt_subject_alt_check_name()
3342 * return 1 when finding a name component matching `cn`. */
3343 if( ret == 1 )
3344 return( 0 );
3345
3346 if( ret != 0 )
3347 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
3348
3349 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
3350 return( ret );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003351}
3352
3353/*
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003354 * Merge the flags for all certs in the chain, after calling callback
3355 */
3356static int x509_crt_merge_flags_with_cb(
3357 uint32_t *flags,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003358 const mbedtls_x509_crt_verify_chain *ver_chain,
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003359 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3360 void *p_vrfy )
3361{
3362 int ret;
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02003363 unsigned i;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003364 uint32_t cur_flags;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003365 const mbedtls_x509_crt_verify_chain_item *cur;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003366
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003367 for( i = ver_chain->len; i != 0; --i )
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003368 {
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003369 cur = &ver_chain->items[i-1];
3370 cur_flags = cur->flags;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003371
3372 if( NULL != f_vrfy )
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02003373 if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003374 return( ret );
3375
3376 *flags |= cur_flags;
3377 }
3378
3379 return( 0 );
3380}
3381
3382/*
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003383 * Verify the certificate validity (default profile, not restartable)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003384 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003385int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
3386 mbedtls_x509_crt *trust_ca,
3387 mbedtls_x509_crl *ca_crl,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02003388 const char *cn, uint32_t *flags,
3389 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
Paul Bakkerddf26b42013-09-18 13:46:23 +02003390 void *p_vrfy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003391{
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003392 return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
3393 &mbedtls_x509_crt_profile_default, cn, flags,
3394 f_vrfy, p_vrfy, NULL ) );
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003395}
3396
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003397/*
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003398 * Verify the certificate validity (user-chosen profile, not restartable)
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003399 */
3400int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
3401 mbedtls_x509_crt *trust_ca,
3402 mbedtls_x509_crl *ca_crl,
3403 const mbedtls_x509_crt_profile *profile,
3404 const char *cn, uint32_t *flags,
3405 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3406 void *p_vrfy )
3407{
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003408 return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
3409 profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
3410}
3411
3412/*
3413 * Verify the certificate validity, with profile, restartable version
3414 *
3415 * This function:
3416 * - checks the requested CN (if any)
3417 * - checks the type and size of the EE cert's key,
3418 * as that isn't done as part of chain building/verification currently
3419 * - builds and verifies the chain
3420 * - then calls the callback and merges the flags
3421 */
3422int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
3423 mbedtls_x509_crt *trust_ca,
3424 mbedtls_x509_crl *ca_crl,
3425 const mbedtls_x509_crt_profile *profile,
3426 const char *cn, uint32_t *flags,
3427 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3428 void *p_vrfy,
3429 mbedtls_x509_crt_restart_ctx *rs_ctx )
3430{
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003431 int ret;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003432 mbedtls_x509_crt_verify_chain ver_chain;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003433 uint32_t ee_flags;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003434
3435 *flags = 0;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003436 ee_flags = 0;
3437 x509_crt_verify_chain_reset( &ver_chain );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003438
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003439 if( profile == NULL )
3440 {
3441 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
3442 goto exit;
3443 }
3444
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003445 /* check name if requested */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003446 if( cn != NULL )
Hanno Becker87233362019-02-25 18:15:33 +00003447 {
3448 ret = x509_crt_verify_name( crt, cn, &ee_flags );
3449 if( ret != 0 )
3450 return( ret );
3451 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003452
Hanno Becker87233362019-02-25 18:15:33 +00003453 {
3454 mbedtls_pk_context *pk;
3455 mbedtls_pk_type_t pk_type;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003456
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003457 ret = mbedtls_x509_crt_pk_acquire( crt, &pk );
Hanno Becker87233362019-02-25 18:15:33 +00003458 if( ret != 0 )
3459 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003460
Hanno Becker87233362019-02-25 18:15:33 +00003461 /* Check the type and size of the key */
3462 pk_type = mbedtls_pk_get_type( pk );
3463
3464 if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
3465 ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
3466
3467 if( x509_profile_check_key( profile, pk ) != 0 )
3468 ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
3469
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003470 mbedtls_x509_crt_pk_release( crt, pk );
Hanno Becker87233362019-02-25 18:15:33 +00003471 }
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003472
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003473 /* Check the chain */
Manuel Pégourié-Gonnard505c3952017-07-05 17:36:47 +02003474 ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003475 &ver_chain, rs_ctx );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003476
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02003477 if( ret != 0 )
3478 goto exit;
3479
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003480 /* Merge end-entity flags */
3481 ver_chain.items[0].flags |= ee_flags;
3482
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003483 /* Build final flags, calling callback on the way if any */
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003484 ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003485
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003486exit:
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003487#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3488 if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
3489 mbedtls_x509_crt_restart_free( rs_ctx );
3490#endif
3491
Manuel Pégourié-Gonnard9107b5f2017-07-06 12:16:25 +02003492 /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
3493 * the SSL module for authmode optional, but non-zero return from the
3494 * callback means a fatal error so it shouldn't be ignored */
Manuel Pégourié-Gonnard31458a12017-06-26 10:11:49 +02003495 if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
3496 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
3497
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003498 if( ret != 0 )
3499 {
3500 *flags = (uint32_t) -1;
3501 return( ret );
3502 }
3503
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003504 if( *flags != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003505 return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003506
3507 return( 0 );
3508}
3509
3510/*
Paul Bakker369d2eb2013-09-18 11:58:25 +02003511 * Initialize a certificate chain
3512 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003513void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
Paul Bakker369d2eb2013-09-18 11:58:25 +02003514{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003515 memset( crt, 0, sizeof(mbedtls_x509_crt) );
Paul Bakker369d2eb2013-09-18 11:58:25 +02003516}
3517
3518/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003519 * Unallocate all certificate data
3520 */
Hanno Beckercd03bb22019-02-15 17:15:53 +00003521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003522void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003523{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003524 mbedtls_x509_crt *cert_cur = crt;
3525 mbedtls_x509_crt *cert_prv;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003526
3527 if( crt == NULL )
3528 return;
3529
3530 do
3531 {
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003532 x509_crt_cache_free( cert_cur->cache );
3533 mbedtls_free( cert_cur->cache );
Hanno Becker180f7bf2019-02-28 13:23:38 +00003534
3535#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003536 mbedtls_pk_free( &cert_cur->pk );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003538#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
3539 mbedtls_free( cert_cur->sig_opts );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +02003540#endif
3541
Hanno Becker2bcc7642019-02-26 19:01:00 +00003542 mbedtls_x509_name_free( cert_cur->issuer.next );
3543 mbedtls_x509_name_free( cert_cur->subject.next );
3544 mbedtls_x509_sequence_free( cert_cur->ext_key_usage.next );
3545 mbedtls_x509_sequence_free( cert_cur->subject_alt_names.next );
Hanno Becker180f7bf2019-02-28 13:23:38 +00003546#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003547
Hanno Beckeraa8665a2019-01-31 08:57:44 +00003548 if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003549 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05003550 mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003551 mbedtls_free( cert_cur->raw.p );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003552 }
3553
3554 cert_cur = cert_cur->next;
3555 }
3556 while( cert_cur != NULL );
3557
3558 cert_cur = crt;
3559 do
3560 {
3561 cert_prv = cert_cur;
3562 cert_cur = cert_cur->next;
3563
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05003564 mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003565 if( cert_prv != crt )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003566 mbedtls_free( cert_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003567 }
3568 while( cert_cur != NULL );
3569}
3570
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003571#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3572/*
3573 * Initialize a restart context
3574 */
3575void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
3576{
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02003577 mbedtls_pk_restart_init( &ctx->pk );
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003578
3579 ctx->parent = NULL;
3580 ctx->fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02003581 ctx->fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003582
3583 ctx->parent_is_trusted = -1;
3584
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003585 ctx->in_progress = x509_crt_rs_none;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003586 ctx->self_cnt = 0;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003587 x509_crt_verify_chain_reset( &ctx->ver_chain );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003588}
3589
3590/*
3591 * Free the components of a restart context
3592 */
3593void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
3594{
3595 if( ctx == NULL )
3596 return;
3597
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02003598 mbedtls_pk_restart_free( &ctx->pk );
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003599 mbedtls_x509_crt_restart_init( ctx );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003600}
3601#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
3602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003603#endif /* MBEDTLS_X509_CRT_PARSE_C */