blob: 18db3b23fab64711204e5aa698b5e9502bef4e69 [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"
Hanno Beckerf6bc8882019-05-02 13:05:58 +010043#include "mbedtls/x509_internal.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000044#include "mbedtls/oid.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050045#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard9ca11fc2019-11-28 12:07:01 +010046#include "mbedtls/platform.h"
Rich Evans00ab4702015-02-06 13:43:58 +000047
Rich Evans00ab4702015-02-06 13:43:58 +000048#include <string.h>
49
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000051#include "mbedtls/pem.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020052#endif
53
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000055#include "mbedtls/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020056#else
Simon Butcherd2642582018-10-03 15:11:19 +010057#include <stdio.h>
Rich Evans00ab4702015-02-06 13:43:58 +000058#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020060#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020061#define mbedtls_snprintf snprintf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020062#endif
63
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020064#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000065#include "mbedtls/threading.h"
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +010066#endif
67
Paul Bakkerfa6a6202013-10-28 18:48:30 +010068#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020069#include <windows.h>
70#else
71#include <time.h>
72#endif
73
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074#if defined(MBEDTLS_FS_IO)
Rich Evans00ab4702015-02-06 13:43:58 +000075#include <stdio.h>
Paul Bakker5ff3f912014-04-04 15:08:20 +020076#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020077#include <sys/types.h>
78#include <sys/stat.h>
79#include <dirent.h>
Rich Evans00ab4702015-02-06 13:43:58 +000080#endif /* !_WIN32 || EFIX64 || EFI32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +020081#endif
82
Hanno Becker38f0cb42019-03-04 15:13:45 +000083#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
84static void x509_buf_to_buf_raw( mbedtls_x509_buf_raw *dst,
85 mbedtls_x509_buf const *src )
86{
87 dst->p = src->p;
88 dst->len = src->len;
89}
90
91static void x509_buf_raw_to_buf( mbedtls_x509_buf *dst,
92 mbedtls_x509_buf_raw const *src )
93{
94 dst->p = src->p;
95 dst->len = src->len;
96}
97#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
98
Hanno Becker21f55672019-02-15 15:27:59 +000099static int x509_crt_parse_frame( unsigned char *start,
100 unsigned char *end,
101 mbedtls_x509_crt_frame *frame );
Hanno Becker12506232019-05-13 13:53:21 +0100102static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame const *frame,
Hanno Becker21f55672019-02-15 15:27:59 +0000103 mbedtls_x509_name *subject );
Hanno Becker12506232019-05-13 13:53:21 +0100104static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame const *frame,
Hanno Becker21f55672019-02-15 15:27:59 +0000105 mbedtls_x509_name *issuer );
Teppo Järvelin4009d8f2019-08-19 14:48:09 +0300106#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Becker12506232019-05-13 13:53:21 +0100107static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame const *frame,
Hanno Becker21f55672019-02-15 15:27:59 +0000108 mbedtls_x509_sequence *subject_alt );
Teppo Järvelin4009d8f2019-08-19 14:48:09 +0300109#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker12506232019-05-13 13:53:21 +0100110static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame const *frame,
Hanno Becker21f55672019-02-15 15:27:59 +0000111 mbedtls_x509_sequence *ext_key_usage );
112
Teppo Järvelinf69e6412019-09-03 16:50:17 +0300113static int mbedtls_x509_crt_flush_cache_pk( mbedtls_x509_crt const *crt )
Hanno Beckerbc685192019-03-05 15:35:31 +0000114{
115#if defined(MBEDTLS_THREADING_C)
116 if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
117 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
Hanno Beckera4bfaa82019-06-28 10:34:23 +0100118#endif
Hanno Beckerfc99a092019-06-28 14:45:26 +0100119
120#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
121 defined(MBEDTLS_THREADING_C)
122 /* Can only free the PK context if nobody is using it.
123 * If MBEDTLS_X509_ALWAYS_FLUSH is set, nested uses
124 * of xxx_acquire() are prohibited, and no reference
125 * counting is needed. Also, notice that the code-path
126 * below is safe if the cache isn't filled. */
Hanno Becker2ba9fbd2019-05-28 16:11:43 +0100127 if( crt->cache->pk_readers == 0 )
Hanno Beckerfc99a092019-06-28 14:45:26 +0100128#endif /* !MBEDTLS_X509_ALWAYS_FLUSH ||
129 MBEDTLS_THREADING_C */
Hanno Becker2ba9fbd2019-05-28 16:11:43 +0100130 {
Hanno Beckerbc685192019-03-05 15:35:31 +0000131#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
Hanno Becker2ba9fbd2019-05-28 16:11:43 +0100132 /* The cache holds a shallow copy of the PK context
133 * in the legacy struct, so don't free PK context. */
134 mbedtls_free( crt->cache->pk );
Hanno Beckerbc685192019-03-05 15:35:31 +0000135#else
Hanno Becker2ba9fbd2019-05-28 16:11:43 +0100136 mbedtls_pk_free( crt->cache->pk );
137 mbedtls_free( crt->cache->pk );
Hanno Beckerbc685192019-03-05 15:35:31 +0000138#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Becker2ba9fbd2019-05-28 16:11:43 +0100139 crt->cache->pk = NULL;
140 }
Hanno Beckerbc685192019-03-05 15:35:31 +0000141
142#if defined(MBEDTLS_THREADING_C)
143 if( mbedtls_mutex_unlock( &crt->cache->pk_mutex ) != 0 )
144 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
145#endif
146 return( 0 );
147}
148
Teppo Järvelinf69e6412019-09-03 16:50:17 +0300149static int mbedtls_x509_crt_flush_cache_frame( mbedtls_x509_crt const *crt )
Hanno Beckerbc685192019-03-05 15:35:31 +0000150{
151#if defined(MBEDTLS_THREADING_C)
152 if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
153 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
Hanno Beckera4bfaa82019-06-28 10:34:23 +0100154#endif
Hanno Beckerbc685192019-03-05 15:35:31 +0000155
Hanno Beckerfc99a092019-06-28 14:45:26 +0100156#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
157 defined(MBEDTLS_THREADING_C)
158 /* Can only free the PK context if nobody is using it.
159 * If MBEDTLS_X509_ALWAYS_FLUSH is set, nested uses
160 * of xxx_acquire() are prohibited, and no reference
161 * counting is needed. Also, notice that the code-path
162 * below is safe if the cache isn't filled. */
Hanno Becker2ba9fbd2019-05-28 16:11:43 +0100163 if( crt->cache->frame_readers == 0 )
Hanno Beckerfc99a092019-06-28 14:45:26 +0100164#endif /* !MBEDTLS_X509_ALWAYS_FLUSH ||
165 MBEDTLS_THREADING_C */
Hanno Becker2ba9fbd2019-05-28 16:11:43 +0100166 {
167 mbedtls_free( crt->cache->frame );
168 crt->cache->frame = NULL;
169 }
Hanno Beckerbc685192019-03-05 15:35:31 +0000170
171#if defined(MBEDTLS_THREADING_C)
172 if( mbedtls_mutex_unlock( &crt->cache->frame_mutex ) != 0 )
173 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
174#endif
175 return( 0 );
176}
177
178int mbedtls_x509_crt_flush_cache( mbedtls_x509_crt const *crt )
179{
180 int ret;
181 ret = mbedtls_x509_crt_flush_cache_frame( crt );
182 if( ret != 0 )
183 return( ret );
184 ret = mbedtls_x509_crt_flush_cache_pk( crt );
185 if( ret != 0 )
186 return( ret );
187 return( 0 );
188}
189
Hanno Beckerea32d8b2019-03-04 11:52:23 +0000190static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame );
Hanno Beckered058882019-06-28 10:46:43 +0100191
Teppo Järvelinf69e6412019-09-03 16:50:17 +0300192static int mbedtls_x509_crt_cache_provide_frame( mbedtls_x509_crt const *crt )
Hanno Becker337088a2019-02-25 14:53:14 +0000193{
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000194 mbedtls_x509_crt_cache *cache = crt->cache;
Hanno Becker337088a2019-02-25 14:53:14 +0000195 mbedtls_x509_crt_frame *frame;
196
Hanno Becker76428352019-03-05 15:29:23 +0000197 if( cache->frame != NULL )
Hanno Beckerfc99a092019-06-28 14:45:26 +0100198 {
Hanno Becker410322f2019-07-02 13:37:12 +0100199#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
200 defined(MBEDTLS_THREADING_C)
Hanno Becker76428352019-03-05 15:29:23 +0000201 return( 0 );
Hanno Beckerfc99a092019-06-28 14:45:26 +0100202#else
203 /* If MBEDTLS_X509_ALWAYS_FLUSH is set, we don't
204 * allow nested uses of acquire. */
205 return( MBEDTLS_ERR_X509_FATAL_ERROR );
206#endif
207 }
Hanno Becker76428352019-03-05 15:29:23 +0000208
Hanno Becker337088a2019-02-25 14:53:14 +0000209 frame = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_frame ) );
210 if( frame == NULL )
211 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000212 cache->frame = frame;
Hanno Becker337088a2019-02-25 14:53:14 +0000213
Hanno Beckerea32d8b2019-03-04 11:52:23 +0000214#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
215 /* This would work with !MBEDTLS_X509_ON_DEMAND_PARSING, too,
216 * but is inefficient compared to copying the respective fields
217 * from the legacy mbedtls_x509_crt. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000218 return( x509_crt_parse_frame( crt->raw.p,
219 crt->raw.p + crt->raw.len,
220 frame ) );
Hanno Beckerea32d8b2019-03-04 11:52:23 +0000221#else /* MBEDTLS_X509_ON_DEMAND_PARSING */
222 /* Make sure all extension related fields are properly initialized. */
223 frame->ca_istrue = 0;
224 frame->max_pathlen = 0;
225 frame->ext_types = 0;
226 frame->version = crt->version;
227 frame->sig_md = crt->sig_md;
228 frame->sig_pk = crt->sig_pk;
Hanno Becker843b71a2019-06-25 09:39:21 +0100229
230#if !defined(MBEDTLS_X509_CRT_REMOVE_TIME)
Hanno Beckerea32d8b2019-03-04 11:52:23 +0000231 frame->valid_from = crt->valid_from;
232 frame->valid_to = crt->valid_to;
Hanno Becker843b71a2019-06-25 09:39:21 +0100233#endif /* !MBEDTLS_X509_CRT_REMOVE_TIME */
234
Hanno Becker38f0cb42019-03-04 15:13:45 +0000235 x509_buf_to_buf_raw( &frame->raw, &crt->raw );
236 x509_buf_to_buf_raw( &frame->tbs, &crt->tbs );
237 x509_buf_to_buf_raw( &frame->serial, &crt->serial );
238 x509_buf_to_buf_raw( &frame->pubkey_raw, &crt->pk_raw );
239 x509_buf_to_buf_raw( &frame->issuer_raw, &crt->issuer_raw );
240 x509_buf_to_buf_raw( &frame->subject_raw, &crt->subject_raw );
Hanno Beckerd07614c2019-06-25 10:19:58 +0100241#if !defined(MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID)
Hanno Becker38f0cb42019-03-04 15:13:45 +0000242 x509_buf_to_buf_raw( &frame->subject_id, &crt->subject_id );
243 x509_buf_to_buf_raw( &frame->issuer_id, &crt->issuer_id );
Hanno Beckerd07614c2019-06-25 10:19:58 +0100244#endif /* !MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID */
Hanno Becker38f0cb42019-03-04 15:13:45 +0000245 x509_buf_to_buf_raw( &frame->sig, &crt->sig );
246 x509_buf_to_buf_raw( &frame->v3_ext, &crt->v3_ext );
Hanno Beckerea32d8b2019-03-04 11:52:23 +0000247
248 /* The legacy CRT structure doesn't explicitly contain
249 * the `AlgorithmIdentifier` bounds; however, those can
250 * be inferred from the surrounding (mandatory) `SerialNumber`
251 * and `Issuer` fields. */
252 frame->sig_alg.p = crt->serial.p + crt->serial.len;
253 frame->sig_alg.len = crt->issuer_raw.p - frame->sig_alg.p;
254
255 return( x509_crt_frame_parse_ext( frame ) );
256#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000257}
Hanno Becker337088a2019-02-25 14:53:14 +0000258
Teppo Järvelinf69e6412019-09-03 16:50:17 +0300259static int mbedtls_x509_crt_cache_provide_pk( mbedtls_x509_crt const *crt )
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000260{
261 mbedtls_x509_crt_cache *cache = crt->cache;
262 mbedtls_pk_context *pk;
263
Hanno Becker76428352019-03-05 15:29:23 +0000264 if( cache->pk != NULL )
Hanno Beckerfc99a092019-06-28 14:45:26 +0100265 {
Hanno Becker410322f2019-07-02 13:37:12 +0100266#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
267 defined(MBEDTLS_THREADING_C)
Hanno Becker76428352019-03-05 15:29:23 +0000268 return( 0 );
Hanno Beckerfc99a092019-06-28 14:45:26 +0100269#else
270 /* If MBEDTLS_X509_ALWAYS_FLUSH is set, we don't
271 * allow nested uses of acquire. */
272 return( MBEDTLS_ERR_X509_FATAL_ERROR );
273#endif
274 }
Hanno Becker76428352019-03-05 15:29:23 +0000275
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000276 pk = mbedtls_calloc( 1, sizeof( mbedtls_pk_context ) );
277 if( pk == NULL )
278 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000279 cache->pk = pk;
Hanno Becker180f7bf2019-02-28 13:23:38 +0000280
281#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
282 *pk = crt->pk;
Hanno Becker337088a2019-02-25 14:53:14 +0000283 return( 0 );
Hanno Becker180f7bf2019-02-28 13:23:38 +0000284#else
285 {
286 mbedtls_x509_buf_raw pk_raw = cache->pk_raw;
287 return( mbedtls_pk_parse_subpubkey( &pk_raw.p,
288 pk_raw.p + pk_raw.len,
289 pk ) );
290 }
291#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Becker337088a2019-02-25 14:53:14 +0000292}
293
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000294static void x509_crt_cache_init( mbedtls_x509_crt_cache *cache )
Hanno Becker337088a2019-02-25 14:53:14 +0000295{
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000296 memset( cache, 0, sizeof( *cache ) );
297#if defined(MBEDTLS_THREADING_C)
298 mbedtls_mutex_init( &cache->frame_mutex );
299 mbedtls_mutex_init( &cache->pk_mutex );
300#endif
301}
302
303static void x509_crt_cache_clear_pk( mbedtls_x509_crt_cache *cache )
304{
Hanno Becker180f7bf2019-02-28 13:23:38 +0000305#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000306 /* The cache holds a shallow copy of the PK context
307 * in the legacy struct, so don't free PK context. */
308 mbedtls_free( cache->pk );
Hanno Becker180f7bf2019-02-28 13:23:38 +0000309#else
310 mbedtls_pk_free( cache->pk );
311 mbedtls_free( cache->pk );
312#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
313
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000314 cache->pk = NULL;
315}
316
317static void x509_crt_cache_clear_frame( mbedtls_x509_crt_cache *cache )
318{
319 mbedtls_free( cache->frame );
320 cache->frame = NULL;
321}
322
323static void x509_crt_cache_free( mbedtls_x509_crt_cache *cache )
324{
325 if( cache == NULL )
Hanno Becker337088a2019-02-25 14:53:14 +0000326 return;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +0000327
328#if defined(MBEDTLS_THREADING_C)
329 mbedtls_mutex_free( &cache->frame_mutex );
330 mbedtls_mutex_free( &cache->pk_mutex );
331#endif
332
333 x509_crt_cache_clear_frame( cache );
334 x509_crt_cache_clear_pk( cache );
335
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +0200336 mbedtls_platform_memset( cache, 0, sizeof( *cache ) );
Hanno Becker337088a2019-02-25 14:53:14 +0000337}
338
Teppo Järvelin4009d8f2019-08-19 14:48:09 +0300339#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Beckerab6c8ea2019-02-27 17:33:14 +0000340int mbedtls_x509_crt_get_subject_alt_names( mbedtls_x509_crt const *crt,
341 mbedtls_x509_sequence **subj_alt )
342{
343 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +0100344 mbedtls_x509_crt_frame const *frame;
Hanno Beckerab6c8ea2019-02-27 17:33:14 +0000345 mbedtls_x509_sequence *seq;
346
347 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
348 if( ret != 0 )
349 return( ret );
350
351 seq = mbedtls_calloc( 1, sizeof( mbedtls_x509_sequence ) );
352 if( seq == NULL )
353 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
354 else
355 ret = x509_crt_subject_alt_from_frame( frame, seq );
356
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +0000357 mbedtls_x509_crt_frame_release( crt );
Hanno Beckerab6c8ea2019-02-27 17:33:14 +0000358
359 *subj_alt = seq;
360 return( ret );
361}
Teppo Järvelin4009d8f2019-08-19 14:48:09 +0300362#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Beckerab6c8ea2019-02-27 17:33:14 +0000363
364int mbedtls_x509_crt_get_ext_key_usage( mbedtls_x509_crt const *crt,
365 mbedtls_x509_sequence **ext_key_usage )
366{
367 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +0100368 mbedtls_x509_crt_frame const *frame;
Hanno Beckerab6c8ea2019-02-27 17:33:14 +0000369 mbedtls_x509_sequence *seq;
370
371 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
372 if( ret != 0 )
373 return( ret );
374
375 seq = mbedtls_calloc( 1, sizeof( mbedtls_x509_sequence ) );
376 if( seq == NULL )
377 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
378 else
379 ret = x509_crt_ext_key_usage_from_frame( frame, seq );
380
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +0000381 mbedtls_x509_crt_frame_release( crt );
Hanno Beckerab6c8ea2019-02-27 17:33:14 +0000382
383 *ext_key_usage = seq;
384 return( ret );
385}
386
Hanno Becker63e69982019-02-26 18:50:49 +0000387int mbedtls_x509_crt_get_subject( mbedtls_x509_crt const *crt,
388 mbedtls_x509_name **subject )
389{
390 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +0100391 mbedtls_x509_crt_frame const *frame;
Hanno Becker63e69982019-02-26 18:50:49 +0000392 mbedtls_x509_name *name;
393
394 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
395 if( ret != 0 )
396 return( ret );
397
398 name = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
399 if( name == NULL )
400 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
401 else
402 ret = x509_crt_subject_from_frame( frame, name );
403
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +0000404 mbedtls_x509_crt_frame_release( crt );
Hanno Becker63e69982019-02-26 18:50:49 +0000405
406 *subject = name;
407 return( ret );
408}
409
410int mbedtls_x509_crt_get_issuer( mbedtls_x509_crt const *crt,
411 mbedtls_x509_name **issuer )
412{
413 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +0100414 mbedtls_x509_crt_frame const *frame;
Hanno Becker63e69982019-02-26 18:50:49 +0000415 mbedtls_x509_name *name;
416
417 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
418 if( ret != 0 )
419 return( ret );
420
421 name = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
422 if( name == NULL )
423 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
424 else
425 ret = x509_crt_issuer_from_frame( frame, name );
426
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +0000427 mbedtls_x509_crt_frame_release( crt );
Hanno Becker63e69982019-02-26 18:50:49 +0000428
429 *issuer = name;
430 return( ret );
431}
432
Hanno Becker823efad2019-02-28 13:23:58 +0000433int mbedtls_x509_crt_get_frame( mbedtls_x509_crt const *crt,
434 mbedtls_x509_crt_frame *dst )
435{
436 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +0100437 mbedtls_x509_crt_frame const *frame;
Hanno Becker823efad2019-02-28 13:23:58 +0000438 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
439 if( ret != 0 )
440 return( ret );
441 *dst = *frame;
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +0000442 mbedtls_x509_crt_frame_release( crt );
Hanno Becker823efad2019-02-28 13:23:58 +0000443 return( 0 );
444}
445
446int mbedtls_x509_crt_get_pk( mbedtls_x509_crt const *crt,
447 mbedtls_pk_context *dst )
448{
449#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
450 mbedtls_x509_buf_raw pk_raw = crt->cache->pk_raw;
451 return( mbedtls_pk_parse_subpubkey( &pk_raw.p,
452 pk_raw.p + pk_raw.len,
453 dst ) );
454#else /* !MBEDTLS_X509_ON_DEMAND_PARSING */
455 int ret;
456 mbedtls_pk_context *pk;
457 ret = mbedtls_x509_crt_pk_acquire( crt, &pk );
458 if( ret != 0 )
459 return( ret );
460
461 /* Move PK from CRT cache to destination pointer
462 * to avoid a copy. */
463 *dst = *pk;
464 mbedtls_free( crt->cache->pk );
465 crt->cache->pk = NULL;
466
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +0000467 mbedtls_x509_crt_pk_release( crt );
Hanno Becker823efad2019-02-28 13:23:58 +0000468 return( 0 );
469#endif /* MBEDTLS_X509_ON_DEMAND_PARSING */
470}
471
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +0200472/*
473 * Item in a verification chain: cert and flags for it
474 */
475typedef struct {
476 mbedtls_x509_crt *crt;
477 uint32_t flags;
478} x509_crt_verify_chain_item;
479
480/*
481 * Max size of verification chain: end-entity + intermediates + trusted root
482 */
483#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
Paul Bakker34617722014-06-13 17:20:13 +0200484
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200485/*
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200486 * Default profile
487 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200488const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
489{
Gilles Peskine5d2511c2017-05-12 13:16:40 +0200490#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200491 /* Allow SHA-1 (weak, but still safe in controlled environments) */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200492 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200493#endif
494 /* Only SHA-2 hashes */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200495 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
496 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
497 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
498 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
499 0xFFFFFFF, /* Any PK alg */
500 0xFFFFFFF, /* Any curve */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200501 2048,
502};
503
504/*
505 * Next-default profile
506 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200507const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
508{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200509 /* Hashes from SHA-256 and above */
510 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
511 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
512 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
513 0xFFFFFFF, /* Any PK alg */
Hanno Becker59e7b082019-08-23 13:21:21 +0100514#if defined(MBEDTLS_USE_TINYCRYPT)
515 MBEDTLS_X509_ID_FLAG( MBEDTLS_UECC_DP_SECP256R1 ),
516#elif defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200517 /* Curves at or above 128-bit security level */
518 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
519 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
520 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
521 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
522 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
523 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
524 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
525#else
526 0,
527#endif
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200528 2048,
529};
530
531/*
532 * NSA Suite B Profile
533 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200534const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
535{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200536 /* Only SHA-256 and 384 */
537 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
538 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
539 /* Only ECDSA */
Ron Eldor85e1dcf2018-02-06 15:59:38 +0200540 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
541 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
Hanno Becker59e7b082019-08-23 13:21:21 +0100542#if defined(MBEDTLS_USE_TINYCRYPT)
543 MBEDTLS_X509_ID_FLAG( MBEDTLS_UECC_DP_SECP256R1 ),
544#elif defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200545 /* Only NIST P-256 and P-384 */
546 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
547 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
548#else
549 0,
550#endif
551 0,
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200552};
553
554/*
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200555 * Check md_alg against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200556 * Return 0 if md_alg is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200557 */
558static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
559 mbedtls_md_type_t md_alg )
560{
Philippe Antoineb5b25432018-05-11 11:06:29 +0200561 if( md_alg == MBEDTLS_MD_NONE )
562 return( -1 );
563
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200564 if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
565 return( 0 );
566
567 return( -1 );
568}
569
570/*
571 * Check pk_alg against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200572 * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200573 */
574static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
575 mbedtls_pk_type_t pk_alg )
576{
Philippe Antoineb5b25432018-05-11 11:06:29 +0200577 if( pk_alg == MBEDTLS_PK_NONE )
578 return( -1 );
579
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200580 if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
581 return( 0 );
582
583 return( -1 );
584}
585
586/*
587 * Check key against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200588 * Return 0 if pk is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200589 */
590static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200591 const mbedtls_pk_context *pk )
592{
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200593 const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk );
Manuel Pégourié-Gonnard19773ff2017-10-24 10:51:26 +0200594
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200595#if defined(MBEDTLS_RSA_C)
596 if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
597 {
Manuel Pégourié-Gonnard097c7bb2015-06-18 16:43:38 +0200598 if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200599 return( 0 );
600
601 return( -1 );
602 }
603#endif
604
Hanno Beckerd931ad22019-08-21 15:25:22 +0100605#if defined(MBEDTLS_USE_TINYCRYPT)
606 if( pk_alg == MBEDTLS_PK_ECKEY )
607 {
608 if( ( profile->allowed_curves & MBEDTLS_UECC_DP_SECP256R1 ) != 0 )
609 return( 0 );
610
611 return( -1 );
612 }
613#endif /* MBEDTLS_USE_TINYCRYPT */
614
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +0200615#if defined(MBEDTLS_ECP_C)
616 if( pk_alg == MBEDTLS_PK_ECDSA ||
617 pk_alg == MBEDTLS_PK_ECKEY ||
618 pk_alg == MBEDTLS_PK_ECKEY_DH )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200619 {
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200620 const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200621
Philippe Antoineb5b25432018-05-11 11:06:29 +0200622 if( gid == MBEDTLS_ECP_DP_NONE )
623 return( -1 );
624
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200625 if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
626 return( 0 );
627
628 return( -1 );
629 }
630#endif
631
632 return( -1 );
633}
634
Teppo Järvelin4009d8f2019-08-19 14:48:09 +0300635#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200636/*
Hanno Becker1f8527f2018-11-02 09:19:16 +0000637 * Return 0 if name matches wildcard, -1 otherwise
638 */
Hanno Becker24926222019-02-21 13:10:55 +0000639static int x509_check_wildcard( char const *cn,
640 size_t cn_len,
641 unsigned char const *buf,
642 size_t buf_len )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000643{
644 size_t i;
Hanno Becker24926222019-02-21 13:10:55 +0000645 size_t cn_idx = 0;
Hanno Becker1f8527f2018-11-02 09:19:16 +0000646
647 /* We can't have a match if there is no wildcard to match */
Hanno Becker24926222019-02-21 13:10:55 +0000648 if( buf_len < 3 || buf[0] != '*' || buf[1] != '.' )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000649 return( -1 );
650
651 for( i = 0; i < cn_len; ++i )
652 {
653 if( cn[i] == '.' )
654 {
655 cn_idx = i;
656 break;
657 }
658 }
659
660 if( cn_idx == 0 )
661 return( -1 );
662
Hanno Beckerb3def1d2019-02-22 11:46:06 +0000663 if( mbedtls_x509_memcasecmp( buf + 1, cn + cn_idx,
664 buf_len - 1, cn_len - cn_idx ) == 0 )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000665 {
666 return( 0 );
667 }
668
669 return( -1 );
670}
Teppo Järvelin4009d8f2019-08-19 14:48:09 +0300671#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker1f8527f2018-11-02 09:19:16 +0000672
673/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200674 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
675 */
676static int x509_get_version( unsigned char **p,
677 const unsigned char *end,
678 int *ver )
679{
680 int ret;
681 size_t len;
682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
684 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200685 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200687 {
688 *ver = 0;
689 return( 0 );
690 }
691
Hanno Becker2f472142019-02-12 11:52:10 +0000692 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200693 }
694
695 end = *p + len;
696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
698 return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200699
700 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 return( MBEDTLS_ERR_X509_INVALID_VERSION +
702 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200703
704 return( 0 );
705}
706
Hanno Becker843b71a2019-06-25 09:39:21 +0100707#if !defined(MBEDTLS_X509_CRT_REMOVE_TIME)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200708/*
709 * Validity ::= SEQUENCE {
710 * notBefore Time,
711 * notAfter Time }
712 */
713static int x509_get_dates( unsigned char **p,
714 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 mbedtls_x509_time *from,
716 mbedtls_x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200717{
718 int ret;
719 size_t len;
720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
722 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
723 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200724
725 end = *p + len;
726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200728 return( ret );
729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200731 return( ret );
732
733 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 return( MBEDTLS_ERR_X509_INVALID_DATE +
735 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200736
737 return( 0 );
738}
Hanno Becker843b71a2019-06-25 09:39:21 +0100739#else /* !MBEDTLS_X509_CRT_REMOVE_TIME */
740static int x509_skip_dates( unsigned char **p,
741 const unsigned char *end )
742{
743 int ret;
744 size_t len;
745
746 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
747 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
748 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
749
Manuel Pégourié-Gonnard0d1db202019-07-30 14:11:25 +0200750 /* skip contents of the sequence */
751 *p += len;
Hanno Becker843b71a2019-06-25 09:39:21 +0100752
753 return( 0 );
754}
755#endif /* MBEDTLS_X509_CRT_REMOVE_TIME */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200756
Hanno Beckerd07614c2019-06-25 10:19:58 +0100757#if !defined(MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200758/*
759 * X.509 v2/v3 unique identifier (not parsed)
760 */
761static int x509_get_uid( unsigned char **p,
762 const unsigned char *end,
Hanno Beckere9084122019-06-07 12:04:39 +0100763 mbedtls_x509_buf_raw *uid, int n )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200764{
765 int ret;
766
767 if( *p == end )
768 return( 0 );
769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
771 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200772 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200774 return( 0 );
775
Hanno Becker2f472142019-02-12 11:52:10 +0000776 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200777 }
778
779 uid->p = *p;
780 *p += uid->len;
781
782 return( 0 );
783}
Hanno Beckerd07614c2019-06-25 10:19:58 +0100784#else /* !MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID */
785static int x509_skip_uid( unsigned char **p,
786 const unsigned char *end,
787 int n )
788{
789 int ret;
790 size_t len;
791
792 if( *p == end )
793 return( 0 );
794
795 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
796 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
797 {
798 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
799 return( 0 );
800
801 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
802 }
803
804 *p += len;
805 return( 0 );
806}
807#endif /* MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200808
809static int x509_get_basic_constraints( unsigned char **p,
810 const unsigned char *end,
811 int *ca_istrue,
812 int *max_pathlen )
813{
814 int ret;
815 size_t len;
816
817 /*
818 * BasicConstraints ::= SEQUENCE {
819 * cA BOOLEAN DEFAULT FALSE,
820 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
821 */
822 *ca_istrue = 0; /* DEFAULT FALSE */
823 *max_pathlen = 0; /* endless */
824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
826 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000827 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200828
829 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200830 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832 if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200833 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200834 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
835 ret = mbedtls_asn1_get_int( p, end, ca_istrue );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200836
837 if( ret != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000838 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200839
840 if( *ca_istrue != 0 )
841 *ca_istrue = 1;
842 }
843
844 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200845 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847 if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000848 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200849
850 if( *p != end )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000851 return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200852
Andrzej Kurek825ebd42020-05-18 11:47:25 -0400853 /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer
854 * overflow, which is an undefined behavior. */
855 if( *max_pathlen == INT_MAX )
856 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
857
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200858 (*max_pathlen)++;
859
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200860 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200861}
862
863static int x509_get_ns_cert_type( unsigned char **p,
864 const unsigned char *end,
865 unsigned char *ns_cert_type)
866{
867 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200869
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000871 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200872
873 if( bs.len != 1 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000874 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200875
876 /* Get actual bitstring */
877 *ns_cert_type = *bs.p;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200878 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200879}
880
881static int x509_get_key_usage( unsigned char **p,
882 const unsigned char *end,
Hanno Beckerfd5c1852019-05-13 12:52:57 +0100883 uint16_t *key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200884{
885 int ret;
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200886 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200887 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200888
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000890 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200891
892 if( bs.len < 1 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000893 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200894
895 /* Get actual bitstring */
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200896 *key_usage = 0;
Hanno Beckerfd5c1852019-05-13 12:52:57 +0100897 for( i = 0; i < bs.len && i < sizeof( *key_usage ); i++ )
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200898 {
Hanno Beckerfd5c1852019-05-13 12:52:57 +0100899 *key_usage |= (uint16_t) bs.p[i] << ( 8*i );
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200900 }
901
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200902 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200903}
904
Hanno Becker529f25d2019-05-02 14:48:25 +0100905static int asn1_build_sequence_cb( void *ctx,
906 int tag,
907 unsigned char *data,
908 size_t data_len )
Hanno Becker15b73b42019-05-02 13:21:27 +0100909{
910 mbedtls_asn1_sequence **cur_ptr = (mbedtls_asn1_sequence **) ctx;
911 mbedtls_asn1_sequence *cur = *cur_ptr;
912
913 /* Allocate and assign next pointer */
914 if( cur->buf.p != NULL )
915 {
916 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
917 if( cur->next == NULL )
918 return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
919 cur = cur->next;
920 }
921
922 cur->buf.tag = tag;
923 cur->buf.p = data;
924 cur->buf.len = data_len;
925
926 *cur_ptr = cur;
927 return( 0 );
928}
929
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200930/*
Hanno Becker529f25d2019-05-02 14:48:25 +0100931 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
932 *
933 * KeyPurposeId ::= OBJECT IDENTIFIER
934 */
935static int x509_get_ext_key_usage( unsigned char **p,
936 const unsigned char *end,
937 mbedtls_x509_sequence *ext_key_usage)
938{
939 return( mbedtls_asn1_traverse_sequence_of( p, end,
940 0xFF, MBEDTLS_ASN1_OID,
941 0, 0,
942 asn1_build_sequence_cb,
Hanno Becker484caf02019-05-29 14:41:44 +0100943 (void *) &ext_key_usage ) );
Hanno Becker529f25d2019-05-02 14:48:25 +0100944}
945
Teppo Järvelin4009d8f2019-08-19 14:48:09 +0300946#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Becker529f25d2019-05-02 14:48:25 +0100947/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200948 * SubjectAltName ::= GeneralNames
949 *
950 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
951 *
952 * GeneralName ::= CHOICE {
953 * otherName [0] OtherName,
954 * rfc822Name [1] IA5String,
955 * dNSName [2] IA5String,
956 * x400Address [3] ORAddress,
957 * directoryName [4] Name,
958 * ediPartyName [5] EDIPartyName,
959 * uniformResourceIdentifier [6] IA5String,
960 * iPAddress [7] OCTET STRING,
961 * registeredID [8] OBJECT IDENTIFIER }
962 *
963 * OtherName ::= SEQUENCE {
964 * type-id OBJECT IDENTIFIER,
965 * value [0] EXPLICIT ANY DEFINED BY type-id }
966 *
967 * EDIPartyName ::= SEQUENCE {
968 * nameAssigner [0] DirectoryString OPTIONAL,
969 * partyName [1] DirectoryString }
970 *
Manuel Pégourié-Gonnardb4fe3cb2015-01-22 16:11:05 +0000971 * NOTE: we only parse and use dNSName at this point.
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200972 */
Hanno Becker5984d302019-02-21 14:46:54 +0000973static int x509_get_subject_alt_name( unsigned char *p,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200974 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975 mbedtls_x509_sequence *subject_alt_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200976{
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000977 return( mbedtls_asn1_traverse_sequence_of( &p, end,
978 MBEDTLS_ASN1_TAG_CLASS_MASK,
979 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
980 MBEDTLS_ASN1_TAG_VALUE_MASK,
981 2 /* SubjectAlt DNS */,
Hanno Becker529f25d2019-05-02 14:48:25 +0100982 asn1_build_sequence_cb,
Hanno Becker484caf02019-05-29 14:41:44 +0100983 (void *) &subject_alt_name ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200984}
Teppo Järvelin4009d8f2019-08-19 14:48:09 +0300985#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200986
987/*
988 * X.509 v3 extensions
989 *
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200990 */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000991static int x509_crt_get_ext_cb( void *ctx,
992 int tag,
993 unsigned char *p,
994 size_t ext_len )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200995{
996 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +0000997 mbedtls_x509_crt_frame *frame = (mbedtls_x509_crt_frame *) ctx;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200998 size_t len;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000999 unsigned char *end, *end_ext_octet;
1000 mbedtls_x509_buf extn_oid = { 0, 0, NULL };
1001 int is_critical = 0; /* DEFAULT FALSE */
1002 int ext_type = 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001003
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001004 ((void) tag);
Hanno Becker4e1bfc12019-02-12 17:22:36 +00001005
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001006 /*
1007 * Extension ::= SEQUENCE {
1008 * extnID OBJECT IDENTIFIER,
1009 * critical BOOLEAN DEFAULT FALSE,
1010 * extnValue OCTET STRING }
1011 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001012
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001013 end = p + ext_len;
1014
1015 /* Get extension ID */
1016 if( ( ret = mbedtls_asn1_get_tag( &p, end, &extn_oid.len,
1017 MBEDTLS_ASN1_OID ) ) != 0 )
1018 goto err;
1019
1020 extn_oid.tag = MBEDTLS_ASN1_OID;
1021 extn_oid.p = p;
1022 p += extn_oid.len;
1023
1024 /* Get optional critical */
1025 if( ( ret = mbedtls_asn1_get_bool( &p, end, &is_critical ) ) != 0 &&
1026 ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
1027 goto err;
1028
1029 /* Data should be octet string type */
1030 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1031 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
1032 goto err;
1033
1034 end_ext_octet = p + len;
1035 if( end_ext_octet != end )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001036 {
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001037 ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
1038 goto err;
1039 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001040
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001041 /*
1042 * Detect supported extensions
1043 */
1044 ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
1045 if( ret != 0 )
1046 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001048 if( is_critical )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001049 {
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001050 /* Data is marked as critical: fail */
1051 ret = MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
1052 goto err;
1053 }
Hanno Beckerb36a2452019-05-29 14:43:17 +01001054#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001055 return( 0 );
1056 }
1057
1058 /* Forbid repeated extensions */
Hanno Becker21f55672019-02-15 15:27:59 +00001059 if( ( frame->ext_types & ext_type ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001060 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
1061
Hanno Becker21f55672019-02-15 15:27:59 +00001062 frame->ext_types |= ext_type;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001063 switch( ext_type )
1064 {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001065 case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001066 {
1067 int ca_istrue;
1068 int max_pathlen;
1069
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001070 /* Parse basic constraints */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001071 ret = x509_get_basic_constraints( &p, end_ext_octet,
1072 &ca_istrue,
1073 &max_pathlen );
1074 if( ret != 0 )
1075 goto err;
1076
Hanno Becker21f55672019-02-15 15:27:59 +00001077 frame->ca_istrue = ca_istrue;
1078 frame->max_pathlen = max_pathlen;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001079 break;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001080 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001081
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 case MBEDTLS_X509_EXT_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001083 /* Parse key usage */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001084 ret = x509_get_key_usage( &p, end_ext_octet,
Hanno Becker21f55672019-02-15 15:27:59 +00001085 &frame->key_usage );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001086 if( ret != 0 )
1087 goto err;
1088 break;
1089
1090 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03001091#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001092 /* Copy reference to raw subject alt name data. */
Hanno Becker21f55672019-02-15 15:27:59 +00001093 frame->subject_alt_raw.p = p;
1094 frame->subject_alt_raw.len = end_ext_octet - p;
Hanno Becker21f55672019-02-15 15:27:59 +00001095 ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
1096 MBEDTLS_ASN1_TAG_CLASS_MASK,
1097 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
1098 MBEDTLS_ASN1_TAG_VALUE_MASK,
1099 2 /* SubjectAlt DNS */,
1100 NULL, NULL );
1101 if( ret != 0 )
1102 goto err;
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03001103#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001104 break;
1105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001106 case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001107 /* Parse extended key usage */
Hanno Becker21f55672019-02-15 15:27:59 +00001108 frame->ext_key_usage_raw.p = p;
1109 frame->ext_key_usage_raw.len = end_ext_octet - p;
1110 if( frame->ext_key_usage_raw.len == 0 )
Hanno Becker5984d302019-02-21 14:46:54 +00001111 {
Hanno Becker21f55672019-02-15 15:27:59 +00001112 ret = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
1113 goto err;
Hanno Becker5984d302019-02-21 14:46:54 +00001114 }
Hanno Becker21f55672019-02-15 15:27:59 +00001115
1116 /* Check structural sanity of extension. */
1117 ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
1118 0xFF, MBEDTLS_ASN1_OID,
1119 0, 0, NULL, NULL );
1120 if( ret != 0 )
1121 goto err;
1122
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001123 break;
1124
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001126 /* Parse netscape certificate type */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001127 ret = x509_get_ns_cert_type( &p, end_ext_octet,
Hanno Becker21f55672019-02-15 15:27:59 +00001128 &frame->ns_cert_type );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001129 if( ret != 0 )
1130 goto err;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001131 break;
1132
1133 default:
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001134 /*
1135 * If this is a non-critical extension, which the oid layer
1136 * supports, but there isn't an X.509 parser for it,
1137 * skip the extension.
1138 */
1139#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
1140 if( is_critical )
1141 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
1142#endif
1143 p = end_ext_octet;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001144 }
1145
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001146 return( 0 );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001147
1148err:
1149 return( ret );
1150}
1151
Hanno Becker21f55672019-02-15 15:27:59 +00001152static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001153{
1154 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +00001155 unsigned char *p = frame->v3_ext.p;
1156 unsigned char *end = p + frame->v3_ext.len;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001157
Hanno Becker21f55672019-02-15 15:27:59 +00001158 if( p == end )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001159 return( 0 );
1160
Hanno Becker21f55672019-02-15 15:27:59 +00001161 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001162 0xFF, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED,
Hanno Becker21f55672019-02-15 15:27:59 +00001163 0, 0, x509_crt_get_ext_cb, frame );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +00001164
1165 if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
1166 return( ret );
1167 if( ret == MBEDTLS_ERR_X509_INVALID_EXTENSIONS )
1168 return( ret );
1169
1170 if( ret != 0 )
1171 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1172
1173 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001174}
1175
Hanno Becker21f55672019-02-15 15:27:59 +00001176static int x509_crt_parse_frame( unsigned char *start,
1177 unsigned char *end,
1178 mbedtls_x509_crt_frame *frame )
1179{
1180 int ret;
1181 unsigned char *p;
1182 size_t len;
1183
1184 mbedtls_x509_buf tmp;
1185 unsigned char *tbs_start;
1186
1187 mbedtls_x509_buf outer_sig_alg;
1188 size_t inner_sig_alg_len;
1189 unsigned char *inner_sig_alg_start;
1190
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +02001191 mbedtls_platform_memset( frame, 0, sizeof( *frame ) );
Hanno Becker21f55672019-02-15 15:27:59 +00001192
1193 /*
1194 * Certificate ::= SEQUENCE {
1195 * tbsCertificate TBSCertificate,
1196 * signatureAlgorithm AlgorithmIdentifier,
1197 * signatureValue BIT STRING
1198 * }
1199 *
1200 */
1201 p = start;
1202
1203 frame->raw.p = p;
1204 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1205 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1206 {
1207 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
1208 }
1209
1210 /* NOTE: We are currently not checking that the `Certificate`
1211 * structure spans the entire buffer. */
1212 end = p + len;
1213 frame->raw.len = end - frame->raw.p;
1214
1215 /*
1216 * TBSCertificate ::= SEQUENCE { ...
1217 */
1218 frame->tbs.p = p;
1219 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1220 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1221 {
1222 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
1223 }
1224 tbs_start = p;
1225
1226 /* Breadth-first parsing: Jump over TBS for now. */
1227 p += len;
1228 frame->tbs.len = p - frame->tbs.p;
1229
1230 /*
1231 * AlgorithmIdentifier ::= SEQUENCE { ...
1232 */
1233 outer_sig_alg.p = p;
1234 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
1235 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
1236 {
1237 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
1238 }
1239 p += len;
1240 outer_sig_alg.len = p - outer_sig_alg.p;
1241
1242 /*
1243 * signatureValue BIT STRING
1244 */
1245 ret = mbedtls_x509_get_sig( &p, end, &tmp );
1246 if( ret != 0 )
1247 return( ret );
1248 frame->sig.p = tmp.p;
1249 frame->sig.len = tmp.len;
1250
1251 /* Check that we consumed the entire `Certificate` structure. */
1252 if( p != end )
1253 {
1254 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
1255 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
1256 }
1257
1258 /* Parse TBSCertificate structure
1259 *
1260 * TBSCertificate ::= SEQUENCE {
1261 * version [0] EXPLICIT Version DEFAULT v1,
1262 * serialNumber CertificateSerialNumber,
1263 * signature AlgorithmIdentifier,
1264 * issuer Name,
1265 * validity Validity,
1266 * subject Name,
1267 * subjectPublicKeyInfo SubjectPublicKeyInfo,
1268 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1269 * -- If present, version MUST be v2 or v3
1270 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1271 * -- If present, version MUST be v2 or v3
1272 * extensions [3] EXPLICIT Extensions OPTIONAL
1273 * -- If present, version MUST be v3
1274 * }
1275 */
1276 end = frame->tbs.p + frame->tbs.len;
1277 p = tbs_start;
1278
1279 /*
1280 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
1281 */
1282 {
1283 int version;
1284 ret = x509_get_version( &p, end, &version );
1285 if( ret != 0 )
1286 return( ret );
1287
1288 if( version < 0 || version > 2 )
1289 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
1290
1291 frame->version = version + 1;
1292 }
1293
1294 /*
1295 * CertificateSerialNumber ::= INTEGER
1296 */
1297 ret = mbedtls_x509_get_serial( &p, end, &tmp );
1298 if( ret != 0 )
1299 return( ret );
1300
1301 frame->serial.p = tmp.p;
1302 frame->serial.len = tmp.len;
1303
1304 /*
1305 * signature AlgorithmIdentifier
1306 */
1307 inner_sig_alg_start = p;
1308 ret = mbedtls_x509_get_sig_alg_raw( &p, end, &frame->sig_md,
1309 &frame->sig_pk, NULL );
1310 if( ret != 0 )
1311 return( ret );
1312 inner_sig_alg_len = p - inner_sig_alg_start;
1313
1314 frame->sig_alg.p = inner_sig_alg_start;
1315 frame->sig_alg.len = inner_sig_alg_len;
1316
1317 /* Consistency check:
1318 * Inner and outer AlgorithmIdentifier structures must coincide:
1319 *
1320 * Quoting RFC 5280, Section 4.1.1.2:
1321 * This field MUST contain the same algorithm identifier as the
1322 * signature field in the sequence tbsCertificate (Section 4.1.2.3).
1323 */
1324 if( outer_sig_alg.len != inner_sig_alg_len ||
Piotr Nowickie3c4ee52020-06-23 12:59:56 +02001325 mbedtls_platform_memequal( outer_sig_alg.p, inner_sig_alg_start, inner_sig_alg_len ) != 0 )
Hanno Becker21f55672019-02-15 15:27:59 +00001326 {
1327 return( MBEDTLS_ERR_X509_SIG_MISMATCH );
1328 }
1329
1330 /*
1331 * issuer Name
1332 *
1333 * Name ::= CHOICE { -- only one possibility for now --
1334 * rdnSequence RDNSequence }
1335 *
1336 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
1337 */
Hanno Becker1e11f212019-03-04 14:43:43 +00001338 frame->issuer_raw.p = p;
Hanno Becker21f55672019-02-15 15:27:59 +00001339
1340 ret = mbedtls_asn1_get_tag( &p, end, &len,
1341 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1342 if( ret != 0 )
1343 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
Hanno Becker21f55672019-02-15 15:27:59 +00001344 p += len;
Hanno Becker1e11f212019-03-04 14:43:43 +00001345 frame->issuer_raw.len = p - frame->issuer_raw.p;
Hanno Becker21f55672019-02-15 15:27:59 +00001346
Hanno Becker3aa12162019-07-02 16:47:40 +01001347 /* Comparing the raw buffer to itself amounts to structural validation. */
Hanno Becker21f55672019-02-15 15:27:59 +00001348 ret = mbedtls_x509_name_cmp_raw( &frame->issuer_raw,
1349 &frame->issuer_raw,
1350 NULL, NULL );
1351 if( ret != 0 )
1352 return( ret );
1353
Hanno Becker21f55672019-02-15 15:27:59 +00001354 /*
1355 * Validity ::= SEQUENCE { ...
1356 */
Hanno Becker843b71a2019-06-25 09:39:21 +01001357#if !defined(MBEDTLS_X509_CRT_REMOVE_TIME)
Hanno Becker21f55672019-02-15 15:27:59 +00001358 ret = x509_get_dates( &p, end, &frame->valid_from, &frame->valid_to );
1359 if( ret != 0 )
1360 return( ret );
Hanno Becker843b71a2019-06-25 09:39:21 +01001361#else /* !MBEDTLS_X509_CRT_REMOVE_TIME */
1362 ret = x509_skip_dates( &p, end );
1363 if( ret != 0 )
1364 return( ret );
1365#endif /* MBEDTLS_X509_CRT_REMOVE_TIME */
Hanno Becker21f55672019-02-15 15:27:59 +00001366
1367 /*
1368 * subject Name
1369 *
1370 * Name ::= CHOICE { -- only one possibility for now --
1371 * rdnSequence RDNSequence }
1372 *
1373 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
1374 */
Hanno Becker1e11f212019-03-04 14:43:43 +00001375 frame->subject_raw.p = p;
Hanno Becker21f55672019-02-15 15:27:59 +00001376
1377 ret = mbedtls_asn1_get_tag( &p, end, &len,
1378 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1379 if( ret != 0 )
1380 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
Hanno Becker21f55672019-02-15 15:27:59 +00001381 p += len;
Hanno Becker1e11f212019-03-04 14:43:43 +00001382 frame->subject_raw.len = p - frame->subject_raw.p;
Hanno Becker21f55672019-02-15 15:27:59 +00001383
Hanno Becker3aa12162019-07-02 16:47:40 +01001384 /* Comparing the raw buffer to itself amounts to structural validation. */
Hanno Becker21f55672019-02-15 15:27:59 +00001385 ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
1386 &frame->subject_raw,
1387 NULL, NULL );
1388 if( ret != 0 )
1389 return( ret );
1390
Hanno Becker21f55672019-02-15 15:27:59 +00001391 /*
1392 * SubjectPublicKeyInfo
1393 */
1394 frame->pubkey_raw.p = p;
1395 ret = mbedtls_asn1_get_tag( &p, end, &len,
1396 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
1397 if( ret != 0 )
1398 return( ret + MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
1399 p += len;
1400 frame->pubkey_raw.len = p - frame->pubkey_raw.p;
1401
Hanno Becker97aa4362019-06-08 07:38:20 +01001402 if( frame->version != 1 )
Hanno Becker21f55672019-02-15 15:27:59 +00001403 {
Hanno Beckerd07614c2019-06-25 10:19:58 +01001404#if !defined(MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID)
Hanno Beckerfd64f142019-06-07 11:47:12 +01001405 /*
1406 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
1407 * -- If present, version shall be v2 or v3
1408 */
Hanno Beckere9084122019-06-07 12:04:39 +01001409 ret = x509_get_uid( &p, end, &frame->issuer_id, 1 /* implicit tag */ );
Hanno Becker21f55672019-02-15 15:27:59 +00001410 if( ret != 0 )
1411 return( ret );
1412
Hanno Beckerfd64f142019-06-07 11:47:12 +01001413 /*
1414 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
1415 * -- If present, version shall be v2 or v3
1416 */
Hanno Beckere9084122019-06-07 12:04:39 +01001417 ret = x509_get_uid( &p, end, &frame->subject_id, 2 /* implicit tag */ );
Hanno Becker21f55672019-02-15 15:27:59 +00001418 if( ret != 0 )
1419 return( ret );
Hanno Beckerd07614c2019-06-25 10:19:58 +01001420#else /* !MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID */
1421 ret = x509_skip_uid( &p, end, 1 /* implicit tag */ );
1422 if( ret != 0 )
1423 return( ret );
1424 ret = x509_skip_uid( &p, end, 2 /* implicit tag */ );
1425 if( ret != 0 )
1426 return( ret );
1427#endif /* MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID */
Hanno Becker21f55672019-02-15 15:27:59 +00001428 }
1429
1430 /*
1431 * extensions [3] EXPLICIT Extensions OPTIONAL
1432 * -- If present, version shall be v3
1433 */
1434#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
1435 if( frame->version == 3 )
1436#endif
1437 {
1438 if( p != end )
1439 {
1440 ret = mbedtls_asn1_get_tag( &p, end, &len,
1441 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
1442 MBEDTLS_ASN1_CONSTRUCTED | 3 );
1443 if( len == 0 )
1444 ret = MBEDTLS_ERR_ASN1_OUT_OF_DATA;
1445 if( ret != 0 )
1446 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
1447
1448 frame->v3_ext.p = p;
1449 frame->v3_ext.len = len;
1450
1451 p += len;
1452 }
1453
1454 ret = x509_crt_frame_parse_ext( frame );
1455 if( ret != 0 )
1456 return( ret );
1457 }
1458
1459 /* Wrapup: Check that we consumed the entire `TBSCertificate` structure. */
1460 if( p != end )
1461 {
1462 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
1463 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
1464 }
1465
1466 return( 0 );
1467}
1468
Hanno Becker12506232019-05-13 13:53:21 +01001469static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame const *frame,
Hanno Becker21f55672019-02-15 15:27:59 +00001470 mbedtls_x509_name *subject )
1471{
Hanno Becker1e11f212019-03-04 14:43:43 +00001472 return( mbedtls_x509_get_name( frame->subject_raw.p,
1473 frame->subject_raw.len,
1474 subject ) );
Hanno Becker21f55672019-02-15 15:27:59 +00001475}
1476
Hanno Becker12506232019-05-13 13:53:21 +01001477static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame const *frame,
Hanno Becker21f55672019-02-15 15:27:59 +00001478 mbedtls_x509_name *issuer )
1479{
Hanno Becker1e11f212019-03-04 14:43:43 +00001480 return( mbedtls_x509_get_name( frame->issuer_raw.p,
1481 frame->issuer_raw.len,
1482 issuer ) );
Hanno Becker21f55672019-02-15 15:27:59 +00001483}
1484
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03001485#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Becker12506232019-05-13 13:53:21 +01001486static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame const *frame,
Hanno Becker21f55672019-02-15 15:27:59 +00001487 mbedtls_x509_sequence *subject_alt )
1488{
1489 int ret;
1490 unsigned char *p = frame->subject_alt_raw.p;
1491 unsigned char *end = p + frame->subject_alt_raw.len;
1492
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +02001493 mbedtls_platform_memset( subject_alt, 0, sizeof( *subject_alt ) );
Hanno Becker21f55672019-02-15 15:27:59 +00001494
1495 if( ( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) == 0 )
1496 return( 0 );
1497
1498 ret = x509_get_subject_alt_name( p, end, subject_alt );
1499 if( ret != 0 )
1500 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1501 return( ret );
1502}
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03001503#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker21f55672019-02-15 15:27:59 +00001504
Hanno Becker12506232019-05-13 13:53:21 +01001505static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame const *frame,
Hanno Becker21f55672019-02-15 15:27:59 +00001506 mbedtls_x509_sequence *ext_key_usage )
1507{
1508 int ret;
1509 unsigned char *p = frame->ext_key_usage_raw.p;
1510 unsigned char *end = p + frame->ext_key_usage_raw.len;
1511
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +02001512 mbedtls_platform_memset( ext_key_usage, 0, sizeof( *ext_key_usage ) );
Hanno Becker21f55672019-02-15 15:27:59 +00001513
1514 if( ( frame->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
1515 return( 0 );
1516
1517 ret = x509_get_ext_key_usage( &p, end, ext_key_usage );
1518 if( ret != 0 )
1519 {
1520 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1521 return( ret );
1522 }
1523
1524 return( 0 );
1525}
1526
Hanno Becker180f7bf2019-02-28 13:23:38 +00001527#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
Hanno Becker21f55672019-02-15 15:27:59 +00001528static int x509_crt_pk_from_frame( mbedtls_x509_crt_frame *frame,
1529 mbedtls_pk_context *pk )
1530{
1531 unsigned char *p = frame->pubkey_raw.p;
1532 unsigned char *end = p + frame->pubkey_raw.len;
1533 return( mbedtls_pk_parse_subpubkey( &p, end, pk ) );
1534}
Hanno Becker180f7bf2019-02-28 13:23:38 +00001535#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Becker21f55672019-02-15 15:27:59 +00001536
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001537/*
1538 * Parse and fill a single X.509 certificate in DER format
1539 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001540static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
1541 const unsigned char *buf,
1542 size_t buflen,
1543 int make_copy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001544{
1545 int ret;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001546 mbedtls_x509_crt_frame *frame;
1547 mbedtls_x509_crt_cache *cache;
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +01001548
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001549 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001551
Hanno Becker21f55672019-02-15 15:27:59 +00001552 if( make_copy == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001553 {
Hanno Becker21f55672019-02-15 15:27:59 +00001554 crt->raw.p = (unsigned char*) buf;
1555 crt->raw.len = buflen;
1556 crt->own_buffer = 0;
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001557 }
1558 else
1559 {
Hanno Becker7b8e11e2019-05-03 12:37:12 +01001560 /* Call mbedtls_calloc with buflen + 1 in order to avoid potential
1561 * return of NULL in case of length 0 certificates, which we want
1562 * to cleanly fail with MBEDTLS_ERR_X509_INVALID_FORMAT in the
1563 * core parsing routine, but not here. */
1564 crt->raw.p = mbedtls_calloc( 1, buflen + 1 );
Hanno Becker21f55672019-02-15 15:27:59 +00001565 if( crt->raw.p == NULL )
1566 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
1567 crt->raw.len = buflen;
Teppo Järvelin91d79382019-10-02 09:09:31 +03001568 mbedtls_platform_memcpy( crt->raw.p, buf, buflen );
Hanno Becker21f55672019-02-15 15:27:59 +00001569
1570 crt->own_buffer = 1;
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001571 }
Janos Follathcc0e49d2016-02-17 14:34:12 +00001572
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001573 cache = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_cache ) );
1574 if( cache == NULL )
1575 {
1576 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
1577 goto exit;
1578 }
1579 crt->cache = cache;
1580 x509_crt_cache_init( cache );
1581
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001582#if defined(MBEDTLS_X509_ON_DEMAND_PARSING)
1583
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001584 ret = mbedtls_x509_crt_cache_provide_frame( crt );
Hanno Becker21f55672019-02-15 15:27:59 +00001585 if( ret != 0 )
1586 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001587
Hanno Becker76428352019-03-05 15:29:23 +00001588 frame = crt->cache->frame;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001589
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001590#else /* MBEDTLS_X509_ON_DEMAND_PARSING */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001591
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001592 frame = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt_frame ) );
1593 if( frame == NULL )
1594 {
1595 ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
1596 goto exit;
1597 }
1598 cache->frame = frame;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001599
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001600 ret = x509_crt_parse_frame( crt->raw.p,
1601 crt->raw.p + crt->raw.len,
1602 frame );
1603 if( ret != 0 )
1604 goto exit;
1605
Hanno Becker21f55672019-02-15 15:27:59 +00001606 /* Copy frame to legacy CRT structure -- that's inefficient, but if
1607 * memory matters, the new CRT structure should be used anyway. */
Hanno Becker38f0cb42019-03-04 15:13:45 +00001608 x509_buf_raw_to_buf( &crt->tbs, &frame->tbs );
1609 x509_buf_raw_to_buf( &crt->serial, &frame->serial );
1610 x509_buf_raw_to_buf( &crt->issuer_raw, &frame->issuer_raw );
1611 x509_buf_raw_to_buf( &crt->subject_raw, &frame->subject_raw );
Hanno Beckerd07614c2019-06-25 10:19:58 +01001612#if !defined(MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID)
Hanno Becker38f0cb42019-03-04 15:13:45 +00001613 x509_buf_raw_to_buf( &crt->issuer_id, &frame->issuer_id );
1614 x509_buf_raw_to_buf( &crt->subject_id, &frame->subject_id );
Hanno Beckerd07614c2019-06-25 10:19:58 +01001615#endif /* !MBEDTLS_X509_CRT_REMOVE_SUBJECT_ISSUER_ID */
Hanno Becker38f0cb42019-03-04 15:13:45 +00001616 x509_buf_raw_to_buf( &crt->pk_raw, &frame->pubkey_raw );
1617 x509_buf_raw_to_buf( &crt->sig, &frame->sig );
1618 x509_buf_raw_to_buf( &crt->v3_ext, &frame->v3_ext );
Hanno Becker843b71a2019-06-25 09:39:21 +01001619
1620#if !defined(MBEDTLS_X509_CRT_REMOVE_TIME)
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001621 crt->valid_from = frame->valid_from;
1622 crt->valid_to = frame->valid_to;
Hanno Becker843b71a2019-06-25 09:39:21 +01001623#endif /* !MBEDTLS_X509_CRT_REMOVE_TIME */
1624
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001625 crt->version = frame->version;
1626 crt->ca_istrue = frame->ca_istrue;
1627 crt->max_pathlen = frame->max_pathlen;
1628 crt->ext_types = frame->ext_types;
1629 crt->key_usage = frame->key_usage;
1630 crt->ns_cert_type = frame->ns_cert_type;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001631
1632 /*
Hanno Becker21f55672019-02-15 15:27:59 +00001633 * Obtain the remaining fields from the frame.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001634 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001635
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001636 {
Hanno Becker21f55672019-02-15 15:27:59 +00001637 /* sig_oid: Previously, needed for convenience in
1638 * mbedtls_x509_crt_info(), now pure legacy burden. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001639 unsigned char *tmp = frame->sig_alg.p;
1640 unsigned char *end = tmp + frame->sig_alg.len;
Hanno Becker21f55672019-02-15 15:27:59 +00001641 mbedtls_x509_buf sig_oid, sig_params;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001642
Hanno Becker21f55672019-02-15 15:27:59 +00001643 ret = mbedtls_x509_get_alg( &tmp, end,
1644 &sig_oid, &sig_params );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001645 if( ret != 0 )
1646 {
Hanno Becker21f55672019-02-15 15:27:59 +00001647 /* This should never happen, because we check
1648 * the sanity of the AlgorithmIdentifier structure
1649 * during frame parsing. */
1650 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1651 goto exit;
1652 }
1653 crt->sig_oid = sig_oid;
1654
1655 /* Signature parameters */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001656 tmp = frame->sig_alg.p;
Hanno Becker21f55672019-02-15 15:27:59 +00001657 ret = mbedtls_x509_get_sig_alg_raw( &tmp, end,
1658 &crt->sig_md, &crt->sig_pk,
1659 &crt->sig_opts );
1660 if( ret != 0 )
1661 {
1662 /* Again, this should never happen. */
1663 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1664 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001665 }
1666 }
1667
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001668 ret = x509_crt_pk_from_frame( frame, &crt->pk );
Hanno Becker21f55672019-02-15 15:27:59 +00001669 if( ret != 0 )
1670 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001671
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001672 ret = x509_crt_subject_from_frame( frame, &crt->subject );
Hanno Becker21f55672019-02-15 15:27:59 +00001673 if( ret != 0 )
1674 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001675
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001676 ret = x509_crt_issuer_from_frame( frame, &crt->issuer );
Hanno Becker21f55672019-02-15 15:27:59 +00001677 if( ret != 0 )
1678 goto exit;
1679
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03001680#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001681 ret = x509_crt_subject_alt_from_frame( frame, &crt->subject_alt_names );
Hanno Becker21f55672019-02-15 15:27:59 +00001682 if( ret != 0 )
1683 goto exit;
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03001684#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker21f55672019-02-15 15:27:59 +00001685
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001686 ret = x509_crt_ext_key_usage_from_frame( frame, &crt->ext_key_usage );
1687 if( ret != 0 )
1688 goto exit;
Hanno Becker180f7bf2019-02-28 13:23:38 +00001689#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001690
Hanno Beckerea32d8b2019-03-04 11:52:23 +00001691 /* Currently, we accept DER encoded CRTs with trailing garbage
1692 * and promise to not account for the garbage in the `raw` field.
1693 *
1694 * Note that this means that `crt->raw.len` is not necessarily the
1695 * full size of the heap buffer allocated at `crt->raw.p` in case
1696 * of copy-mode, but this is not a problem: freeing the buffer doesn't
1697 * need the size, and the garbage data doesn't need zeroization. */
1698 crt->raw.len = frame->raw.len;
1699
1700 cache->pk_raw = frame->pubkey_raw;
1701
Hanno Becker7a4de9c2019-02-27 13:12:24 +00001702 /* Free the frame before parsing the public key to
1703 * keep peak RAM usage low. This is slightly inefficient
1704 * because the frame will need to be parsed again on the
1705 * first usage of the CRT, but that seems acceptable.
1706 * As soon as the frame gets used multiple times, it
1707 * will be cached by default. */
1708 x509_crt_cache_clear_frame( crt->cache );
1709
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001710 /* The cache just references the PK structure from the legacy
1711 * implementation, so set up the latter first before setting up
Hanno Becker7a4de9c2019-02-27 13:12:24 +00001712 * the cache.
1713 *
1714 * We're not actually using the parsed PK context here;
1715 * we just parse it to check that it's well-formed. */
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00001716 ret = mbedtls_x509_crt_cache_provide_pk( crt );
Hanno Becker21f55672019-02-15 15:27:59 +00001717 if( ret != 0 )
1718 goto exit;
Hanno Becker7a4de9c2019-02-27 13:12:24 +00001719 x509_crt_cache_clear_pk( crt->cache );
Hanno Becker21f55672019-02-15 15:27:59 +00001720
1721exit:
1722 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001724
Hanno Becker21f55672019-02-15 15:27:59 +00001725 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001726}
1727
1728/*
1729 * Parse one X.509 certificate in DER format from a buffer and add them to a
1730 * chained list
1731 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001732static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
1733 const unsigned char *buf,
1734 size_t buflen,
1735 int make_copy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001736{
1737 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 mbedtls_x509_crt *crt = chain, *prev = NULL;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001739
1740 /*
1741 * Check for valid input
1742 */
1743 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001744 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001745
Hanno Becker371e0e42019-02-25 18:08:59 +00001746 while( crt->raw.p != NULL && crt->next != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001747 {
1748 prev = crt;
1749 crt = crt->next;
1750 }
1751
1752 /*
1753 * Add new certificate on the end of the chain if needed.
1754 */
Hanno Becker371e0e42019-02-25 18:08:59 +00001755 if( crt->raw.p != NULL && crt->next == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001756 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001757 crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001758
1759 if( crt->next == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001760 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001761
1762 prev = crt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763 mbedtls_x509_crt_init( crt->next );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001764 crt = crt->next;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001765 }
1766
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001767 if( ( ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001768 {
1769 if( prev )
1770 prev->next = NULL;
1771
1772 if( crt != chain )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001773 mbedtls_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001774
1775 return( ret );
1776 }
1777
1778 return( 0 );
1779}
1780
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001781int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain,
1782 const unsigned char *buf,
1783 size_t buflen )
1784{
1785 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0 ) );
1786}
1787
1788int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain,
1789 const unsigned char *buf,
1790 size_t buflen )
1791{
1792 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1 ) );
1793}
1794
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001795/*
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001796 * Parse one or more PEM certificates from a buffer and add them to the chained
1797 * list
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001798 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001799int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
1800 const unsigned char *buf,
1801 size_t buflen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001802{
Janos Follath98e28a72016-05-31 14:03:54 +01001803#if defined(MBEDTLS_PEM_PARSE_C)
Andres AGc0db5112016-12-07 15:05:53 +00001804 int success = 0, first_error = 0, total_failed = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 int buf_format = MBEDTLS_X509_FORMAT_DER;
Janos Follath98e28a72016-05-31 14:03:54 +01001806#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001807
1808 /*
1809 * Check for valid input
1810 */
1811 if( chain == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001813
1814 /*
1815 * Determine buffer content. Buffer contains either one DER certificate or
1816 * one or more PEM certificates.
1817 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001818#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001819 if( buflen != 0 && buf[buflen - 1] == '\0' &&
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001820 strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
1821 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001822 buf_format = MBEDTLS_X509_FORMAT_PEM;
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001823 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 if( buf_format == MBEDTLS_X509_FORMAT_DER )
1826 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
Janos Follath98e28a72016-05-31 14:03:54 +01001827#else
1828 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
1829#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001830
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831#if defined(MBEDTLS_PEM_PARSE_C)
1832 if( buf_format == MBEDTLS_X509_FORMAT_PEM )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001833 {
1834 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 mbedtls_pem_context pem;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001836
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001837 /* 1 rather than 0 since the terminating NULL byte is counted in */
1838 while( buflen > 1 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001839 {
1840 size_t use_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 mbedtls_pem_init( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001842
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001843 /* If we get there, we know the string is null-terminated */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 ret = mbedtls_pem_read_buffer( &pem,
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001845 "-----BEGIN CERTIFICATE-----",
1846 "-----END CERTIFICATE-----",
1847 buf, NULL, 0, &use_len );
1848
1849 if( ret == 0 )
1850 {
1851 /*
1852 * Was PEM encoded
1853 */
1854 buflen -= use_len;
1855 buf += use_len;
1856 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001857 else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001858 {
1859 return( ret );
1860 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001862 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001864
1865 /*
1866 * PEM header and footer were found
1867 */
1868 buflen -= use_len;
1869 buf += use_len;
1870
1871 if( first_error == 0 )
1872 first_error = ret;
1873
Paul Bakker5a5fa922014-09-26 14:53:04 +02001874 total_failed++;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001875 continue;
1876 }
1877 else
1878 break;
1879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001881
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001883
1884 if( ret != 0 )
1885 {
1886 /*
1887 * Quit parsing on a memory error
1888 */
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001889 if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001890 return( ret );
1891
1892 if( first_error == 0 )
1893 first_error = ret;
1894
1895 total_failed++;
1896 continue;
1897 }
1898
1899 success = 1;
1900 }
1901 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001902
1903 if( success )
1904 return( total_failed );
1905 else if( first_error )
1906 return( first_error );
1907 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001908 return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
Janos Follath98e28a72016-05-31 14:03:54 +01001909#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001910}
1911
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001912#if defined(MBEDTLS_FS_IO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001913/*
1914 * Load one or more certificates and add them to the chained list
1915 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001917{
1918 int ret;
1919 size_t n;
1920 unsigned char *buf;
1921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001923 return( ret );
1924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 ret = mbedtls_x509_crt_parse( chain, buf, n );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001926
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001927 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 mbedtls_free( buf );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001929
1930 return( ret );
1931}
1932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001933int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001934{
1935 int ret = 0;
Paul Bakkerfa6a6202013-10-28 18:48:30 +01001936#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001937 int w_ret;
1938 WCHAR szDir[MAX_PATH];
1939 char filename[MAX_PATH];
Paul Bakker9af723c2014-05-01 13:03:14 +02001940 char *p;
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001941 size_t len = strlen( path );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001942
Paul Bakker9af723c2014-05-01 13:03:14 +02001943 WIN32_FIND_DATAW file_data;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001944 HANDLE hFind;
1945
1946 if( len > MAX_PATH - 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001948
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +02001949 mbedtls_platform_memset( szDir, 0, sizeof(szDir) );
1950 mbedtls_platform_memset( filename, 0, MAX_PATH );
Teppo Järvelin91d79382019-10-02 09:09:31 +03001951 mbedtls_platform_memcpy( filename, path, len );
Paul Bakker9af723c2014-05-01 13:03:14 +02001952 filename[len++] = '\\';
1953 p = filename + len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001954 filename[len++] = '*';
1955
Simon B3c6b18d2016-11-03 01:11:37 +00001956 w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001957 MAX_PATH - 3 );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001958 if( w_ret == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001960
1961 hFind = FindFirstFileW( szDir, &file_data );
Paul Bakker66d5d072014-06-17 16:39:18 +02001962 if( hFind == INVALID_HANDLE_VALUE )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001964
1965 len = MAX_PATH - len;
1966 do
1967 {
Manuel Pégourié-Gonnard7a346b82019-10-02 14:47:01 +02001968 mbedtls_platform_memset( p, 0, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001969
1970 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
1971 continue;
1972
Paul Bakker9af723c2014-05-01 13:03:14 +02001973 w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
Paul Bakker66d5d072014-06-17 16:39:18 +02001974 lstrlenW( file_data.cFileName ),
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001975 p, (int) len - 1,
Paul Bakker9af723c2014-05-01 13:03:14 +02001976 NULL, NULL );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001977 if( w_ret == 0 )
Ron Eldor36d90422017-01-09 15:09:16 +02001978 {
1979 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
1980 goto cleanup;
1981 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001983 w_ret = mbedtls_x509_crt_parse_file( chain, filename );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001984 if( w_ret < 0 )
1985 ret++;
1986 else
1987 ret += w_ret;
1988 }
1989 while( FindNextFileW( hFind, &file_data ) != 0 );
1990
Paul Bakker66d5d072014-06-17 16:39:18 +02001991 if( GetLastError() != ERROR_NO_MORE_FILES )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001992 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001993
Ron Eldor36d90422017-01-09 15:09:16 +02001994cleanup:
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001995 FindClose( hFind );
Paul Bakkerbe089b02013-10-14 15:51:50 +02001996#else /* _WIN32 */
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001997 int t_ret;
Andres AGf9113192016-09-02 14:06:04 +01001998 int snp_ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001999 struct stat sb;
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01002000 struct dirent *entry;
Andres AGf9113192016-09-02 14:06:04 +01002001 char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002002 DIR *dir = opendir( path );
2003
Paul Bakker66d5d072014-06-17 16:39:18 +02002004 if( dir == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002006
Ron Eldor63140682017-01-09 19:27:59 +02002007#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02002008 if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02002009 {
2010 closedir( dir );
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01002011 return( ret );
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02002012 }
Ron Eldor63140682017-01-09 19:27:59 +02002013#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01002014
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01002015 while( ( entry = readdir( dir ) ) != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002016 {
Andres AGf9113192016-09-02 14:06:04 +01002017 snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
2018 "%s/%s", path, entry->d_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002019
Andres AGf9113192016-09-02 14:06:04 +01002020 if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002021 {
Andres AGf9113192016-09-02 14:06:04 +01002022 ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
2023 goto cleanup;
2024 }
2025 else if( stat( entry_name, &sb ) == -1 )
2026 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01002028 goto cleanup;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002029 }
2030
2031 if( !S_ISREG( sb.st_mode ) )
2032 continue;
2033
2034 // Ignore parse errors
2035 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002037 if( t_ret < 0 )
2038 ret++;
2039 else
2040 ret += t_ret;
2041 }
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01002042
2043cleanup:
Andres AGf9113192016-09-02 14:06:04 +01002044 closedir( dir );
2045
Ron Eldor63140682017-01-09 19:27:59 +02002046#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02002047 if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
Ron Eldor63140682017-01-09 19:27:59 +02002049#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01002050
Paul Bakkerbe089b02013-10-14 15:51:50 +02002051#endif /* _WIN32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002052
2053 return( ret );
2054}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055#endif /* MBEDTLS_FS_IO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002056
Hanno Becker08d34122019-06-25 09:42:57 +01002057typedef struct mbedtls_x509_crt_sig_info
2058{
2059 mbedtls_md_type_t sig_md;
2060 mbedtls_pk_type_t sig_pk;
2061 void *sig_opts;
Hanno Becker08d34122019-06-25 09:42:57 +01002062 size_t crt_hash_len;
2063 mbedtls_x509_buf_raw sig;
2064 mbedtls_x509_buf_raw issuer_raw;
Teppo Järvelinc3e57162019-08-30 11:25:15 +03002065 uint8_t crt_hash[MBEDTLS_MD_MAX_SIZE];
Hanno Becker08d34122019-06-25 09:42:57 +01002066} mbedtls_x509_crt_sig_info;
2067
2068static void x509_crt_free_sig_info( mbedtls_x509_crt_sig_info *info )
2069{
2070#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
2071 mbedtls_free( info->sig_opts );
2072#else
2073 ((void) info);
2074#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
2075}
2076
2077static int x509_crt_get_sig_info( mbedtls_x509_crt_frame const *frame,
2078 mbedtls_x509_crt_sig_info *info )
2079{
Hanno Beckera5cedbc2019-07-17 11:21:02 +01002080 mbedtls_md_handle_t md_info;
Hanno Becker08d34122019-06-25 09:42:57 +01002081
2082 md_info = mbedtls_md_info_from_type( frame->sig_md );
2083 if( mbedtls_md( md_info, frame->tbs.p, frame->tbs.len,
2084 info->crt_hash ) != 0 )
2085 {
2086 /* Note: this can't happen except after an internal error */
2087 return( -1 );
2088 }
2089
2090 info->crt_hash_len = mbedtls_md_get_size( md_info );
2091
2092 /* Make sure that this function leaves the target structure
2093 * ready to be freed, regardless of success of failure. */
2094 info->sig_opts = NULL;
2095
2096#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
2097 {
2098 int ret;
2099 unsigned char *alg_start = frame->sig_alg.p;
2100 unsigned char *alg_end = alg_start + frame->sig_alg.len;
2101
2102 /* Get signature options -- currently only
2103 * necessary for RSASSA-PSS. */
2104 ret = mbedtls_x509_get_sig_alg_raw( &alg_start, alg_end, &info->sig_md,
2105 &info->sig_pk, &info->sig_opts );
2106 if( ret != 0 )
2107 {
2108 /* Note: this can't happen except after an internal error */
2109 return( -1 );
2110 }
2111 }
2112#else /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
2113 info->sig_md = frame->sig_md;
2114 info->sig_pk = frame->sig_pk;
2115#endif /* !MBEDTLS_X509_RSASSA_PSS_SUPPORT */
2116
2117 info->issuer_raw = frame->issuer_raw;
2118 info->sig = frame->sig;
2119 return( 0 );
2120}
2121
Hanno Becker02a21932019-06-10 15:08:43 +01002122#if !defined(MBEDTLS_X509_REMOVE_INFO)
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002123#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002124static int x509_info_subject_alt_name( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 const mbedtls_x509_sequence *subject_alt_name )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002126{
2127 size_t i;
2128 size_t n = *size;
2129 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002130 const mbedtls_x509_sequence *cur = subject_alt_name;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002131 const char *sep = "";
2132 size_t sep_len = 0;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002133
2134 while( cur != NULL )
2135 {
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002136 if( cur->buf.len + sep_len >= n )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002137 {
2138 *p = '\0';
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002139 return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002140 }
2141
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002142 n -= cur->buf.len + sep_len;
2143 for( i = 0; i < sep_len; i++ )
2144 *p++ = sep[i];
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002145 for( i = 0; i < cur->buf.len; i++ )
2146 *p++ = cur->buf.p[i];
2147
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002148 sep = ", ";
2149 sep_len = 2;
2150
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002151 cur = cur->next;
2152 }
2153
2154 *p = '\0';
2155
2156 *size = n;
2157 *buf = p;
2158
2159 return( 0 );
2160}
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002161#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002162
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02002163#define PRINT_ITEM(i) \
2164 { \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002166 MBEDTLS_X509_SAFE_SNPRINTF; \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02002167 sep = ", "; \
2168 }
2169
2170#define CERT_TYPE(type,name) \
Hanno Beckerd6028a12018-10-15 12:01:35 +01002171 if( ns_cert_type & (type) ) \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02002172 PRINT_ITEM( name );
2173
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02002174static int x509_info_cert_type( char **buf, size_t *size,
2175 unsigned char ns_cert_type )
2176{
2177 int ret;
2178 size_t n = *size;
2179 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002180 const char *sep = "";
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02002181
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002183 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" );
2185 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" );
2186 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002187 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" );
2188 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" );
2189 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" );
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02002190
2191 *size = n;
2192 *buf = p;
2193
2194 return( 0 );
2195}
2196
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02002197#define KEY_USAGE(code,name) \
Hanno Beckerd6028a12018-10-15 12:01:35 +01002198 if( key_usage & (code) ) \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02002199 PRINT_ITEM( name );
2200
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002201static int x509_info_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02002202 unsigned int key_usage )
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002203{
2204 int ret;
2205 size_t n = *size;
2206 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002207 const char *sep = "";
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" );
2210 KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002211 KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" );
2212 KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" );
2213 KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002214 KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" );
2215 KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" );
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02002216 KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" );
2217 KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" );
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002218
2219 *size = n;
2220 *buf = p;
2221
2222 return( 0 );
2223}
2224
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002225static int x509_info_ext_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002226 const mbedtls_x509_sequence *extended_key_usage )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002227{
2228 int ret;
2229 const char *desc;
2230 size_t n = *size;
2231 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002232 const mbedtls_x509_sequence *cur = extended_key_usage;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002233 const char *sep = "";
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002234
2235 while( cur != NULL )
2236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002238 desc = "???";
2239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002241 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002242
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02002243 sep = ", ";
2244
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002245 cur = cur->next;
2246 }
2247
2248 *size = n;
2249 *buf = p;
2250
2251 return( 0 );
2252}
2253
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002254/*
2255 * Return an informational string about the certificate.
2256 */
Teppo Järvelinffaba552019-09-03 12:33:16 +03002257#define BEFORE_COLON_CRT 18
2258#define BC_CRT "18"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002259int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
Hanno Becker5226c532019-02-27 17:38:40 +00002260 const mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002261{
2262 int ret;
2263 size_t n;
2264 char *p;
Teppo Järvelinffaba552019-09-03 12:33:16 +03002265 char key_size_str[BEFORE_COLON_CRT];
Hanno Becker5226c532019-02-27 17:38:40 +00002266 mbedtls_x509_crt_frame frame;
2267 mbedtls_pk_context pk;
Hanno Becker4f869ed2019-02-24 16:47:57 +00002268
Hanno Becker5226c532019-02-27 17:38:40 +00002269 mbedtls_x509_name *issuer = NULL, *subject = NULL;
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002270 mbedtls_x509_sequence *ext_key_usage = NULL;
2271#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
2272 mbedtls_x509_sequence *subject_alt_names = NULL;
2273#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
2274
Hanno Becker4f869ed2019-02-24 16:47:57 +00002275 mbedtls_x509_crt_sig_info sig_info;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002276
2277 p = buf;
2278 n = size;
2279
Hanno Becker4f869ed2019-02-24 16:47:57 +00002280 memset( &sig_info, 0, sizeof( mbedtls_x509_crt_sig_info ) );
Hanno Becker5226c532019-02-27 17:38:40 +00002281 mbedtls_pk_init( &pk );
2282
2283 if( NULL == crt )
Janos Follath98e28a72016-05-31 14:03:54 +01002284 {
2285 ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002286 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Janos Follath98e28a72016-05-31 14:03:54 +01002287
2288 return( (int) ( size - n ) );
2289 }
2290
Hanno Becker5226c532019-02-27 17:38:40 +00002291 ret = mbedtls_x509_crt_get_frame( crt, &frame );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002292 if( ret != 0 )
2293 {
2294 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2295 goto cleanup;
2296 }
2297
Hanno Becker5226c532019-02-27 17:38:40 +00002298 ret = mbedtls_x509_crt_get_subject( crt, &subject );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002299 if( ret != 0 )
2300 {
2301 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2302 goto cleanup;
2303 }
2304
Hanno Becker5226c532019-02-27 17:38:40 +00002305 ret = mbedtls_x509_crt_get_issuer( crt, &issuer );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002306 if( ret != 0 )
2307 {
2308 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2309 goto cleanup;
2310 }
2311
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002312#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Becker5226c532019-02-27 17:38:40 +00002313 ret = mbedtls_x509_crt_get_subject_alt_names( crt, &subject_alt_names );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002314 if( ret != 0 )
2315 {
2316 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2317 goto cleanup;
2318 }
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002319#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker4f869ed2019-02-24 16:47:57 +00002320
Hanno Becker5226c532019-02-27 17:38:40 +00002321 ret = mbedtls_x509_crt_get_ext_key_usage( crt, &ext_key_usage );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002322 if( ret != 0 )
2323 {
2324 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2325 goto cleanup;
2326 }
2327
Hanno Becker5226c532019-02-27 17:38:40 +00002328 ret = mbedtls_x509_crt_get_pk( crt, &pk );
2329 if( ret != 0 )
2330 {
2331 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2332 goto cleanup;
2333 }
2334
2335 ret = x509_crt_get_sig_info( &frame, &sig_info );
Hanno Becker4f869ed2019-02-24 16:47:57 +00002336 if( ret != 0 )
2337 {
2338 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2339 goto cleanup;
2340 }
2341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 ret = mbedtls_snprintf( p, n, "%scert. version : %d\n",
Hanno Becker5226c532019-02-27 17:38:40 +00002343 prefix, frame.version );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002344 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002345
Hanno Becker4f869ed2019-02-24 16:47:57 +00002346 {
2347 mbedtls_x509_buf serial;
Hanno Becker5226c532019-02-27 17:38:40 +00002348 serial.p = frame.serial.p;
2349 serial.len = frame.serial.len;
Hanno Becker4f869ed2019-02-24 16:47:57 +00002350 ret = mbedtls_snprintf( p, n, "%sserial number : ",
2351 prefix );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002352 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Hanno Becker4f869ed2019-02-24 16:47:57 +00002353 ret = mbedtls_x509_serial_gets( p, n, &serial );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002354 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Hanno Becker4f869ed2019-02-24 16:47:57 +00002355 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357 ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002358 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Hanno Becker5226c532019-02-27 17:38:40 +00002359 ret = mbedtls_x509_dn_gets( p, n, issuer );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002360 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002363 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Hanno Becker5226c532019-02-27 17:38:40 +00002364 ret = mbedtls_x509_dn_gets( p, n, subject );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002365 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002366
Hanno Becker843b71a2019-06-25 09:39:21 +01002367#if !defined(MBEDTLS_X509_CRT_REMOVE_TIME)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 ret = mbedtls_snprintf( p, n, "\n%sissued on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002369 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
Hanno Becker5226c532019-02-27 17:38:40 +00002370 frame.valid_from.year, frame.valid_from.mon,
2371 frame.valid_from.day, frame.valid_from.hour,
2372 frame.valid_from.min, frame.valid_from.sec );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002373 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002376 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
Hanno Becker5226c532019-02-27 17:38:40 +00002377 frame.valid_to.year, frame.valid_to.mon,
2378 frame.valid_to.day, frame.valid_to.hour,
2379 frame.valid_to.min, frame.valid_to.sec );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002380 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Hanno Becker843b71a2019-06-25 09:39:21 +01002381#endif /* MBEDTLS_X509_CRT_REMOVE_TIME */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002384 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002385
Hanno Becker83cd8672019-02-21 17:13:46 +00002386 ret = mbedtls_x509_sig_alg_gets( p, n, sig_info.sig_pk,
2387 sig_info.sig_md, sig_info.sig_opts );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002388 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002389
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002390 /* Key size */
Teppo Järvelinffaba552019-09-03 12:33:16 +03002391 if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON_CRT,
Hanno Becker5226c532019-02-27 17:38:40 +00002392 mbedtls_pk_get_name( &pk ) ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002393 {
2394 return( ret );
2395 }
2396
Teppo Järvelinffaba552019-09-03 12:33:16 +03002397 ret = mbedtls_snprintf( p, n, "\n%s%-" BC_CRT "s: %d bits", prefix, key_size_str,
Hanno Becker5226c532019-02-27 17:38:40 +00002398 (int) mbedtls_pk_get_bitlen( &pk ) );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002399 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002400
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002401 /*
2402 * Optional extensions
2403 */
2404
Hanno Becker5226c532019-02-27 17:38:40 +00002405 if( frame.ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002406 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002407 ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
Hanno Becker5226c532019-02-27 17:38:40 +00002408 frame.ca_istrue ? "true" : "false" );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002409 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002410
Hanno Becker5226c532019-02-27 17:38:40 +00002411 if( frame.max_pathlen > 0 )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002412 {
Hanno Becker5226c532019-02-27 17:38:40 +00002413 ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", frame.max_pathlen - 1 );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002414 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002415 }
2416 }
2417
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002418#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Becker5226c532019-02-27 17:38:40 +00002419 if( frame.ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002420 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002421 ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002422 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002423
2424 if( ( ret = x509_info_subject_alt_name( &p, &n,
Hanno Becker5226c532019-02-27 17:38:40 +00002425 subject_alt_names ) ) != 0 )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02002426 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002427 }
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002428#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002429
Hanno Becker5226c532019-02-27 17:38:40 +00002430 if( frame.ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002431 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002432 ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002433 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02002434
Hanno Becker5226c532019-02-27 17:38:40 +00002435 if( ( ret = x509_info_cert_type( &p, &n, frame.ns_cert_type ) ) != 0 )
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02002436 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002437 }
2438
Hanno Becker5226c532019-02-27 17:38:40 +00002439 if( frame.ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002440 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002442 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002443
Hanno Becker5226c532019-02-27 17:38:40 +00002444 if( ( ret = x509_info_key_usage( &p, &n, frame.key_usage ) ) != 0 )
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02002445 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002446 }
2447
Hanno Becker5226c532019-02-27 17:38:40 +00002448 if( frame.ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002449 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002450 ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002451 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002452
2453 if( ( ret = x509_info_ext_key_usage( &p, &n,
Hanno Becker5226c532019-02-27 17:38:40 +00002454 ext_key_usage ) ) != 0 )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02002455 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002456 }
2457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 ret = mbedtls_snprintf( p, n, "\n" );
Hanno Becker54f1c2c2019-05-13 11:58:47 +01002459 MBEDTLS_X509_SAFE_SNPRINTF_WITH_CLEANUP;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02002460
Hanno Becker4f869ed2019-02-24 16:47:57 +00002461 ret = (int) ( size - n );
2462
2463cleanup:
2464
Hanno Becker4f869ed2019-02-24 16:47:57 +00002465 x509_crt_free_sig_info( &sig_info );
Hanno Becker5226c532019-02-27 17:38:40 +00002466 mbedtls_pk_free( &pk );
2467 mbedtls_x509_name_free( issuer );
2468 mbedtls_x509_name_free( subject );
2469 mbedtls_x509_sequence_free( ext_key_usage );
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002470#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Becker5226c532019-02-27 17:38:40 +00002471 mbedtls_x509_sequence_free( subject_alt_names );
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03002472#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker4f869ed2019-02-24 16:47:57 +00002473
2474 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002475}
2476
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002477struct x509_crt_verify_string {
2478 int code;
2479 const char *string;
2480};
2481
2482static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002483 { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002484 { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
2485 { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" },
2486 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" },
2487 { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" },
2488 { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002489 { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" },
2490 { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" },
2491 { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002492 { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002493 { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" },
2494 { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" },
2495 { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
2496 { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" },
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002497 { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." },
2498 { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
2499 { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
2500 { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." },
2501 { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
2502 { 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 +01002503 { 0, NULL }
2504};
2505
2506int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02002507 uint32_t flags )
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002508{
2509 int ret;
2510 const struct x509_crt_verify_string *cur;
2511 char *p = buf;
2512 size_t n = size;
2513
2514 for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
2515 {
2516 if( ( flags & cur->code ) == 0 )
2517 continue;
2518
2519 ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002520 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002521 flags ^= cur->code;
2522 }
2523
2524 if( flags != 0 )
2525 {
2526 ret = mbedtls_snprintf( p, n, "%sUnknown reason "
2527 "(this should not happen)\n", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02002528 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002529 }
2530
2531 return( (int) ( size - n ) );
2532}
Hanno Becker02a21932019-06-10 15:08:43 +01002533#endif /* !MBEDTLS_X509_REMOVE_INFO */
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01002534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002535#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Hanno Becker45eedf12019-02-25 13:55:33 +00002536static int x509_crt_check_key_usage_frame( const mbedtls_x509_crt_frame *crt,
2537 unsigned int usage )
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002538{
Manuel Pégourié-Gonnard655a9642015-06-23 10:48:44 +02002539 unsigned int usage_must, usage_may;
2540 unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
2541 | MBEDTLS_X509_KU_DECIPHER_ONLY;
2542
2543 if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
2544 return( 0 );
2545
2546 usage_must = usage & ~may_mask;
2547
2548 if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
2549 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
2550
2551 usage_may = usage & may_mask;
2552
2553 if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002554 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002555
2556 return( 0 );
2557}
Hanno Becker45eedf12019-02-25 13:55:33 +00002558
2559int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
2560 unsigned int usage )
2561{
2562 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +01002563 mbedtls_x509_crt_frame const *frame;
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00002564 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Becker45eedf12019-02-25 13:55:33 +00002565 if( ret != 0 )
2566 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2567
2568 ret = x509_crt_check_key_usage_frame( frame, usage );
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00002569 mbedtls_x509_crt_frame_release( crt );
Hanno Becker45eedf12019-02-25 13:55:33 +00002570
2571 return( ret );
2572}
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02002573#endif
2574
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002575#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
Hanno Beckerc7c638e2019-02-21 21:10:51 +00002576typedef struct
2577{
2578 const char *oid;
2579 size_t oid_len;
2580} x509_crt_check_ext_key_usage_cb_ctx_t;
2581
2582static int x509_crt_check_ext_key_usage_cb( void *ctx,
2583 int tag,
2584 unsigned char *data,
2585 size_t data_len )
2586{
2587 x509_crt_check_ext_key_usage_cb_ctx_t *cb_ctx =
2588 (x509_crt_check_ext_key_usage_cb_ctx_t *) ctx;
2589 ((void) tag);
2590
2591 if( MBEDTLS_OID_CMP_RAW( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE,
2592 data, data_len ) == 0 )
2593 {
2594 return( 1 );
2595 }
2596
Piotr Nowickie3c4ee52020-06-23 12:59:56 +02002597 if( data_len == cb_ctx->oid_len && mbedtls_platform_memequal( data, cb_ctx->oid,
Hanno Beckerc7c638e2019-02-21 21:10:51 +00002598 data_len ) == 0 )
2599 {
2600 return( 1 );
2601 }
2602
2603 return( 0 );
2604}
2605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
Hanno Beckere1956af2019-02-21 14:28:12 +00002607 const char *usage_oid,
2608 size_t usage_len )
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002609{
Hanno Beckere1956af2019-02-21 14:28:12 +00002610 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +01002611 mbedtls_x509_crt_frame const *frame;
Hanno Beckere1956af2019-02-21 14:28:12 +00002612 unsigned ext_types;
2613 unsigned char *p, *end;
Hanno Beckerc7c638e2019-02-21 21:10:51 +00002614 x509_crt_check_ext_key_usage_cb_ctx_t cb_ctx = { usage_oid, usage_len };
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002615
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002616 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Beckere9718b42019-02-25 18:11:42 +00002617 if( ret != 0 )
2618 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2619
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002620 /* Extension is not mandatory, absent means no restriction */
Hanno Beckere9718b42019-02-25 18:11:42 +00002621 ext_types = frame->ext_types;
2622 if( ( ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) != 0 )
2623 {
2624 p = frame->ext_key_usage_raw.p;
2625 end = p + frame->ext_key_usage_raw.len;
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002626
Hanno Beckere9718b42019-02-25 18:11:42 +00002627 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
2628 0xFF, MBEDTLS_ASN1_OID, 0, 0,
2629 x509_crt_check_ext_key_usage_cb,
2630 &cb_ctx );
2631 if( ret == 1 )
2632 ret = 0;
2633 else
2634 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
2635 }
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002636
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00002637 mbedtls_x509_crt_frame_release( crt );
Hanno Beckere9718b42019-02-25 18:11:42 +00002638 return( ret );
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002639}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002640#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02002641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002642#if defined(MBEDTLS_X509_CRL_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002643/*
2644 * Return 1 if the certificate is revoked, or 0 otherwise.
2645 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002646static int x509_serial_is_revoked( unsigned char const *serial,
2647 size_t serial_len,
2648 const mbedtls_x509_crl *crl )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002649{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002650 const mbedtls_x509_crl_entry *cur = &crl->entry;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002651
2652 while( cur != NULL && cur->serial.len != 0 )
2653 {
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002654 if( serial_len == cur->serial.len &&
Piotr Nowickie3c4ee52020-06-23 12:59:56 +02002655 mbedtls_platform_memequal( serial, cur->serial.p, serial_len ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002656 {
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002657 if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002658 return( 1 );
2659 }
2660
2661 cur = cur->next;
2662 }
2663
2664 return( 0 );
2665}
2666
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002667int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt,
2668 const mbedtls_x509_crl *crl )
2669{
Hanno Becker79ae5b62019-02-25 18:12:00 +00002670 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +01002671 mbedtls_x509_crt_frame const *frame;
Hanno Becker79ae5b62019-02-25 18:12:00 +00002672
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002673 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Becker79ae5b62019-02-25 18:12:00 +00002674 if( ret != 0 )
2675 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2676
2677 ret = x509_serial_is_revoked( frame->serial.p,
2678 frame->serial.len,
2679 crl );
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00002680 mbedtls_x509_crt_frame_release( crt );
Hanno Becker79ae5b62019-02-25 18:12:00 +00002681 return( ret );
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002682}
2683
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002684/*
Manuel Pégourié-Gonnardeeef9472016-02-22 11:36:55 +01002685 * Check that the given certificate is not revoked according to the CRL.
Manuel Pégourié-Gonnard08eacec2017-10-18 14:20:24 +02002686 * Skip validation if no CRL for the given CA is present.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002687 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002688static int x509_crt_verifycrl( unsigned char *crt_serial,
2689 size_t crt_serial_len,
Hanno Beckerbb266132019-02-25 18:12:46 +00002690 mbedtls_x509_crt *ca_crt,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002691 mbedtls_x509_crl *crl_list,
2692 const mbedtls_x509_crt_profile *profile )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002693{
Hanno Beckerbb266132019-02-25 18:12:46 +00002694 int ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002695 int flags = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002696 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Hanno Beckera5cedbc2019-07-17 11:21:02 +01002697 mbedtls_md_handle_t md_info;
Hanno Beckerbb266132019-02-25 18:12:46 +00002698 mbedtls_x509_buf_raw ca_subject;
2699 mbedtls_pk_context *pk;
2700 int can_sign;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002701
Hanno Beckerbb266132019-02-25 18:12:46 +00002702 if( ca_crt == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002703 return( flags );
2704
Hanno Beckerbb266132019-02-25 18:12:46 +00002705 {
Hanno Becker5f268b32019-05-20 16:26:34 +01002706 mbedtls_x509_crt_frame const *ca;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002707 ret = mbedtls_x509_crt_frame_acquire( ca_crt, &ca );
Hanno Beckerbb266132019-02-25 18:12:46 +00002708 if( ret != 0 )
2709 return( MBEDTLS_X509_BADCRL_NOT_TRUSTED );
2710
2711 ca_subject = ca->subject_raw;
2712
2713 can_sign = 0;
2714 if( x509_crt_check_key_usage_frame( ca,
2715 MBEDTLS_X509_KU_CRL_SIGN ) == 0 )
2716 {
2717 can_sign = 1;
2718 }
2719
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00002720 mbedtls_x509_crt_frame_release( ca_crt );
Hanno Beckerbb266132019-02-25 18:12:46 +00002721 }
2722
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002723 ret = mbedtls_x509_crt_pk_acquire( ca_crt, &pk );
Hanno Beckerbb266132019-02-25 18:12:46 +00002724 if( ret != 0 )
2725 return( MBEDTLS_X509_BADCRL_NOT_TRUSTED );
2726
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002727 while( crl_list != NULL )
2728 {
2729 if( crl_list->version == 0 ||
Hanno Becker1e11f212019-03-04 14:43:43 +00002730 mbedtls_x509_name_cmp_raw( &crl_list->issuer_raw,
Hanno Beckerbb266132019-02-25 18:12:46 +00002731 &ca_subject, NULL, NULL ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002732 {
2733 crl_list = crl_list->next;
2734 continue;
2735 }
2736
2737 /*
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002738 * Check if the CA is configured to sign CRLs
2739 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002740#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Hanno Beckerbb266132019-02-25 18:12:46 +00002741 if( !can_sign )
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002742 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002743 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002744 break;
2745 }
2746#endif
2747
2748 /*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002749 * Check if CRL is correctly signed by the trusted CA
2750 */
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002751 if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
2752 flags |= MBEDTLS_X509_BADCRL_BAD_MD;
2753
2754 if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
2755 flags |= MBEDTLS_X509_BADCRL_BAD_PK;
2756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002757 md_info = mbedtls_md_info_from_type( crl_list->sig_md );
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02002758 if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002759 {
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02002760 /* Note: this can't happen except after an internal error */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002761 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002762 break;
2763 }
2764
Hanno Beckerbb266132019-02-25 18:12:46 +00002765 if( x509_profile_check_key( profile, pk ) != 0 )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002766 flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002767
Hanno Beckerbb266132019-02-25 18:12:46 +00002768 if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, pk,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002769 crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
Manuel Pégourié-Gonnard53882022014-06-05 17:53:52 +02002770 crl_list->sig.p, crl_list->sig.len ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002771 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002772 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002773 break;
2774 }
2775
2776 /*
2777 * Check for validity of CRL (Do not drop out)
2778 */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002779 if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780 flags |= MBEDTLS_X509_BADCRL_EXPIRED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002781
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002782 if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002783 flags |= MBEDTLS_X509_BADCRL_FUTURE;
Manuel Pégourié-Gonnard95337652014-03-10 13:15:18 +01002784
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002785 /*
2786 * Check if certificate is revoked
2787 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002788 if( x509_serial_is_revoked( crt_serial, crt_serial_len,
2789 crl_list ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002790 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002791 flags |= MBEDTLS_X509_BADCERT_REVOKED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002792 break;
2793 }
2794
2795 crl_list = crl_list->next;
2796 }
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002797
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00002798 mbedtls_x509_crt_pk_release( ca_crt );
Paul Bakkerd8bb8262014-06-17 14:06:49 +02002799 return( flags );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002800}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002801#endif /* MBEDTLS_X509_CRL_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002802
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02002803/*
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002804 * Check the signature of a certificate by its parent
2805 */
Hanno Becker5299cf82019-02-25 13:50:41 +00002806static int x509_crt_check_signature( const mbedtls_x509_crt_sig_info *sig_info,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002807 mbedtls_x509_crt *parent,
2808 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002809{
Hanno Beckere449e2d2019-02-25 14:45:31 +00002810 int ret;
2811 mbedtls_pk_context *pk;
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002812
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00002813 ret = mbedtls_x509_crt_pk_acquire( parent, &pk );
Hanno Beckere449e2d2019-02-25 14:45:31 +00002814 if( ret != 0 )
2815 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2816
2817 /* Skip expensive computation on obvious mismatch */
2818 if( ! mbedtls_pk_can_do( pk, sig_info->sig_pk ) )
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002819 {
Hanno Beckere449e2d2019-02-25 14:45:31 +00002820 ret = -1;
2821 goto exit;
2822 }
2823
2824#if !( defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) )
2825 ((void) rs_ctx);
2826#else
2827 if( rs_ctx != NULL && sig_info->sig_pk == MBEDTLS_PK_ECDSA )
2828 {
2829 ret = mbedtls_pk_verify_restartable( pk,
Hanno Becker5299cf82019-02-25 13:50:41 +00002830 sig_info->sig_md,
2831 sig_info->crt_hash, sig_info->crt_hash_len,
2832 sig_info->sig.p, sig_info->sig.len,
Hanno Beckere449e2d2019-02-25 14:45:31 +00002833 &rs_ctx->pk );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002834 }
Hanno Beckere449e2d2019-02-25 14:45:31 +00002835 else
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002836#endif
Hanno Beckere449e2d2019-02-25 14:45:31 +00002837 {
2838 ret = mbedtls_pk_verify_ext( sig_info->sig_pk,
2839 sig_info->sig_opts,
2840 pk,
2841 sig_info->sig_md,
2842 sig_info->crt_hash, sig_info->crt_hash_len,
2843 sig_info->sig.p, sig_info->sig.len );
2844 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002845
Hanno Beckere449e2d2019-02-25 14:45:31 +00002846exit:
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00002847 mbedtls_x509_crt_pk_release( parent );
Hanno Beckere449e2d2019-02-25 14:45:31 +00002848 return( ret );
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002849}
2850
2851/*
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002852 * Check if 'parent' is a suitable parent (signing CA) for 'child'.
2853 * Return 0 if yes, -1 if not.
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002854 *
2855 * top means parent is a locally-trusted certificate
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002856 */
Hanno Becker43bf9002019-02-25 14:46:49 +00002857static int x509_crt_check_parent( const mbedtls_x509_crt_sig_info *sig_info,
2858 const mbedtls_x509_crt_frame *parent,
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002859 int top )
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002860{
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002861 int need_ca_bit;
2862
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02002863 /* Parent must be the issuer */
Hanno Becker43bf9002019-02-25 14:46:49 +00002864 if( mbedtls_x509_name_cmp_raw( &sig_info->issuer_raw,
2865 &parent->subject_raw,
Hanno Becker67284cc2019-02-21 14:31:51 +00002866 NULL, NULL ) != 0 )
Hanno Becker7dee12a2019-02-21 13:58:38 +00002867 {
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002868 return( -1 );
Hanno Becker7dee12a2019-02-21 13:58:38 +00002869 }
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002870
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002871 /* Parent must have the basicConstraints CA bit set as a general rule */
2872 need_ca_bit = 1;
2873
2874 /* Exception: v1/v2 certificates that are locally trusted. */
2875 if( top && parent->version < 3 )
2876 need_ca_bit = 0;
2877
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002878 if( need_ca_bit && ! parent->ca_istrue )
2879 return( -1 );
2880
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002881#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002882 if( need_ca_bit &&
Hanno Becker43bf9002019-02-25 14:46:49 +00002883 x509_crt_check_key_usage_frame( parent,
2884 MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02002885 {
2886 return( -1 );
2887 }
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002888#endif
2889
2890 return( 0 );
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002891}
2892
Manuel Pégourié-Gonnardf66657a2019-11-08 11:14:09 +01002893/* This value is different enough from 0 that it's hard for an active physical
2894 * attacker to reach it just by flipping a few bits. */
2895#define X509_SIGNATURE_IS_GOOD 0x7f5a5a5a
2896
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002897/*
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002898 * Find a suitable parent for child in candidates, or return NULL.
2899 *
2900 * Here suitable is defined as:
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002901 * 1. subject name matches child's issuer
2902 * 2. if necessary, the CA bit is set and key usage allows signing certs
2903 * 3. for trusted roots, the signature is correct
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002904 * (for intermediates, the signature is checked and the result reported)
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002905 * 4. pathlen constraints are satisfied
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002906 *
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002907 * If there's a suitable candidate which is also time-valid, return the first
2908 * such. Otherwise, return the first suitable candidate (or NULL if there is
2909 * none).
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002910 *
2911 * The rationale for this rule is that someone could have a list of trusted
2912 * roots with two versions on the same root with different validity periods.
2913 * (At least one user reported having such a list and wanted it to just work.)
2914 * The reason we don't just require time-validity is that generally there is
2915 * only one version, and if it's expired we want the flags to state that
2916 * rather than NOT_TRUSTED, as would be the case if we required it here.
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002917 *
2918 * The rationale for rule 3 (signature for trusted roots) is that users might
2919 * have two versions of the same CA with different keys in their list, and the
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002920 * way we select the correct one is by checking the signature (as we don't
2921 * rely on key identifier extensions). (This is one way users might choose to
2922 * handle key rollover, another relies on self-issued certs, see [SIRO].)
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002923 *
2924 * Arguments:
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002925 * - [in] child: certificate for which we're looking for a parent
2926 * - [in] candidates: chained list of potential parents
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002927 * - [out] r_parent: parent found (or NULL)
Manuel Pégourié-Gonnardf66657a2019-11-08 11:14:09 +01002928 * - [out] r_signature_is_good: set to X509_SIGNATURE_IS_GOOD if
2929 * child signature by parent is valid, or to 0
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002930 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
2931 * of the chain, 0 otherwise
2932 * - [in] path_cnt: number of intermediates seen so far
2933 * - [in] self_cnt: number of self-signed intermediates seen so far
2934 * (will never be greater than path_cnt)
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002935 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002936 *
2937 * Return value:
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002938 * - 0 on success
Piotr Nowickie048b912020-06-05 17:59:28 +02002939 * - MBEDTLS_ERR_ECP_IN_PROGRESS or MBEDTLS_ERR_PLATFORM_FAULT_DETECTED otherwise
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002940 */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002941static int x509_crt_find_parent_in(
Hanno Becker5299cf82019-02-25 13:50:41 +00002942 mbedtls_x509_crt_sig_info const *child_sig,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002943 mbedtls_x509_crt *candidates,
2944 mbedtls_x509_crt **r_parent,
2945 int *r_signature_is_good,
2946 int top,
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002947 unsigned path_cnt,
2948 unsigned self_cnt,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002949 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002950{
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002951 int ret;
Manuel Pégourié-Gonnard6bdc6802019-11-28 10:29:41 +01002952 volatile int ret_fi = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01002953 mbedtls_x509_crt *parent_crt;
Manuel Pégourié-Gonnard6bdc6802019-11-28 10:29:41 +01002954 int signature_is_good = 0;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01002955
2956#if defined(MBEDTLS_HAVE_TIME_DATE)
2957 mbedtls_x509_crt *fallback_parent;
2958 int fallback_signature_is_good;
2959#endif /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002960
2961#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002962 /* did we have something in progress? */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002963 if( rs_ctx != NULL && rs_ctx->parent != NULL )
2964 {
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002965 /* restore saved state */
Hanno Becker43bf9002019-02-25 14:46:49 +00002966 parent_crt = rs_ctx->parent;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01002967#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002968 fallback_parent = rs_ctx->fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002969 fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01002970#endif /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002971
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002972 /* clear saved state */
2973 rs_ctx->parent = NULL;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01002974#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002975 rs_ctx->fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002976 rs_ctx->fallback_signature_is_good = 0;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01002977#endif /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002978
2979 /* resume where we left */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002980 goto check_signature;
2981 }
2982#endif
2983
Hanno Becker6f61b7b2019-06-10 11:12:33 +01002984#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002985 fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002986 fallback_signature_is_good = 0;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01002987#endif /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002988
Hanno Becker43bf9002019-02-25 14:46:49 +00002989 for( parent_crt = candidates; parent_crt != NULL;
2990 parent_crt = parent_crt->next )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002991 {
Andrzej Kurek17c35312020-12-30 06:16:58 -05002992 volatile int parent_valid, parent_match, path_len_ok;
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002993
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002994#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2995check_signature:
2996#endif
Hanno Beckera788cab2019-02-24 17:47:46 +00002997
2998 parent_valid = parent_match = path_len_ok = 0;
Hanno Beckera788cab2019-02-24 17:47:46 +00002999 {
Hanno Becker5f268b32019-05-20 16:26:34 +01003000 mbedtls_x509_crt_frame const *parent;
Hanno Beckera788cab2019-02-24 17:47:46 +00003001
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003002 ret = mbedtls_x509_crt_frame_acquire( parent_crt, &parent );
Hanno Becker43bf9002019-02-25 14:46:49 +00003003 if( ret != 0 )
3004 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Hanno Beckera788cab2019-02-24 17:47:46 +00003005
Hanno Becker843b71a2019-06-25 09:39:21 +01003006#if !defined(MBEDTLS_X509_CRT_REMOVE_TIME)
Hanno Becker040c5642019-06-10 11:14:24 +01003007 if( !mbedtls_x509_time_is_past( &parent->valid_to ) &&
3008 !mbedtls_x509_time_is_future( &parent->valid_from ) )
Manuel Pégourié-Gonnardf1358ac2019-07-30 16:03:06 +02003009#endif /* !MBEDTLS_X509_CRT_REMOVE_TIME */
Hanno Becker43bf9002019-02-25 14:46:49 +00003010 {
3011 parent_valid = 1;
3012 }
3013
3014 /* basic parenting skills (name, CA bit, key usage) */
3015 if( x509_crt_check_parent( child_sig, parent, top ) == 0 )
3016 parent_match = 1;
3017
3018 /* +1 because the stored max_pathlen is 1 higher
3019 * than the actual value */
3020 if( !( parent->max_pathlen > 0 &&
3021 (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) )
3022 {
3023 path_len_ok = 1;
3024 }
3025
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00003026 mbedtls_x509_crt_frame_release( parent_crt );
Hanno Beckera788cab2019-02-24 17:47:46 +00003027 }
3028
3029 if( parent_match == 0 || path_len_ok == 0 )
3030 continue;
3031
3032 /* Signature */
Manuel Pégourié-Gonnardd1e55df2019-11-08 11:02:56 +01003033 ret_fi = x509_crt_check_signature( child_sig, parent_crt, rs_ctx );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003034
3035#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnardd1e55df2019-11-08 11:02:56 +01003036 if( rs_ctx != NULL && ret_fi == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003037 {
3038 /* save state */
Hanno Becker43bf9002019-02-25 14:46:49 +00003039 rs_ctx->parent = parent_crt;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01003040#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003041 rs_ctx->fallback_parent = fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02003042 rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01003043#endif /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003044
Manuel Pégourié-Gonnardd1e55df2019-11-08 11:02:56 +01003045 return( ret_fi );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003046 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003047#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003048
Manuel Pégourié-Gonnardd1e55df2019-11-08 11:02:56 +01003049 if( ret_fi == 0 )
3050 {
Arto Kinnunenac6d2262020-01-09 10:11:20 +02003051 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnardd1e55df2019-11-08 11:02:56 +01003052 if( ret_fi == 0 )
Manuel Pégourié-Gonnardf66657a2019-11-08 11:14:09 +01003053 signature_is_good = X509_SIGNATURE_IS_GOOD;
Piotr Nowickie048b912020-06-05 17:59:28 +02003054 else
3055 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnardd1e55df2019-11-08 11:02:56 +01003056 }
3057
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003058 if( top && ! signature_is_good )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02003059 continue;
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02003060
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02003061 /* optional time check */
Hanno Beckera788cab2019-02-24 17:47:46 +00003062 if( !parent_valid )
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02003063 {
Hanno Becker6f61b7b2019-06-10 11:12:33 +01003064#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02003065 if( fallback_parent == NULL )
3066 {
Hanno Becker43bf9002019-02-25 14:46:49 +00003067 fallback_parent = parent_crt;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02003068 fallback_signature_is_good = signature_is_good;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02003069 }
Hanno Becker6f61b7b2019-06-10 11:12:33 +01003070#endif /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02003071
3072 continue;
3073 }
3074
Manuel Pégourié-Gonnard8abd0a02019-09-10 11:24:29 +02003075 *r_parent = parent_crt;
Andy Gross3fc6f9d2019-01-30 10:25:53 -06003076 *r_signature_is_good = signature_is_good;
3077
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02003078 break;
3079 }
3080
Manuel Pégourié-Gonnard8abd0a02019-09-10 11:24:29 +02003081 if( parent_crt == NULL )
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003082 {
Hanno Becker6f61b7b2019-06-10 11:12:33 +01003083#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003084 *r_parent = fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02003085 *r_signature_is_good = fallback_signature_is_good;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01003086#else /* MBEDTLS_HAVE_TIME_DATE */
3087 *r_parent = NULL;
3088#endif /* !MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02003089 }
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02003090
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003091 return( 0 );
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02003092}
3093
3094/*
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02003095 * Find a parent in trusted CAs or the provided chain, or return NULL.
3096 *
3097 * Searches in trusted CAs first, and return the first suitable parent found
3098 * (see find_parent_in() for definition of suitable).
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02003099 *
3100 * Arguments:
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01003101 * - [in] child: certificate for which we're looking for a parent, followed
3102 * by a chain of possible intermediates
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02003103 * - [in] trust_ca: list of locally trusted certificates
3104 * - [out] parent: parent found (or NULL)
3105 * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
3106 * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
3107 * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
3108 * - [in] self_cnt: number of self-signed certs in the chain so far
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01003109 * (will always be no greater than path_cnt)
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02003110 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01003111 *
3112 * Return value:
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02003113 * - 0 on success
3114 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02003115 */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003116static int x509_crt_find_parent(
Hanno Becker5299cf82019-02-25 13:50:41 +00003117 mbedtls_x509_crt_sig_info const *child_sig,
Hanno Becker1e0677a2019-02-25 14:58:22 +00003118 mbedtls_x509_crt *rest,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003119 mbedtls_x509_crt *trust_ca,
3120 mbedtls_x509_crt **parent,
3121 int *parent_is_trusted,
3122 int *signature_is_good,
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02003123 unsigned path_cnt,
3124 unsigned self_cnt,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003125 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02003126{
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003127 int ret;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003128 mbedtls_x509_crt *search_list;
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02003129
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02003130 *parent_is_trusted = 1;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003131
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003132#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02003133 /* restore then clear saved state if we have some stored */
3134 if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
3135 {
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003136 *parent_is_trusted = rs_ctx->parent_is_trusted;
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02003137 rs_ctx->parent_is_trusted = -1;
3138 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003139#endif
3140
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003141 while( 1 ) {
Hanno Becker1e0677a2019-02-25 14:58:22 +00003142 search_list = *parent_is_trusted ? trust_ca : rest;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003143
Hanno Becker5299cf82019-02-25 13:50:41 +00003144 ret = x509_crt_find_parent_in( child_sig, search_list,
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003145 parent, signature_is_good,
3146 *parent_is_trusted,
3147 path_cnt, self_cnt, rs_ctx );
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02003148
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003149#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003150 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
3151 {
3152 /* save state */
3153 rs_ctx->parent_is_trusted = *parent_is_trusted;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003154 return( ret );
3155 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003156#else
3157 (void) ret;
3158#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003159
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003160 /* stop here if found or already in second iteration */
3161 if( *parent != NULL || *parent_is_trusted == 0 )
3162 break;
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02003163
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003164 /* prepare second iteration */
3165 *parent_is_trusted = 0;
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003166 }
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003167
3168 /* extra precaution against mistakes in the caller */
Krzysztof Stachowiakc388a8c2018-10-31 16:49:20 +01003169 if( *parent == NULL )
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003170 {
Manuel Pégourié-Gonnarda5a3e402018-10-16 11:27:23 +02003171 *parent_is_trusted = 0;
3172 *signature_is_good = 0;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02003173 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003174
3175 return( 0 );
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02003176}
3177
3178/*
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02003179 * Check if an end-entity certificate is locally trusted
3180 *
3181 * Currently we require such certificates to be self-signed (actually only
3182 * check for self-issued as self-signatures are not checked)
3183 */
3184static int x509_crt_check_ee_locally_trusted(
Hanno Becker1e0677a2019-02-25 14:58:22 +00003185 mbedtls_x509_crt_frame const *crt,
3186 mbedtls_x509_crt const *trust_ca )
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02003187{
Hanno Becker1e0677a2019-02-25 14:58:22 +00003188 mbedtls_x509_crt const *cur;
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02003189
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02003190 /* look for an exact match with trusted cert */
3191 for( cur = trust_ca; cur != NULL; cur = cur->next )
3192 {
3193 if( crt->raw.len == cur->raw.len &&
Piotr Nowickie3c4ee52020-06-23 12:59:56 +02003194 mbedtls_platform_memequal( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02003195 {
3196 return( 0 );
3197 }
3198 }
3199
3200 /* too bad */
3201 return( -1 );
3202}
3203
Hanno Becker8d6d3202019-08-16 17:18:15 +01003204#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
3205
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02003206/*
Hanno Beckeradc282a2019-08-16 17:14:25 +01003207 * Reset (init or clear) a verify_chain
3208 */
3209static void x509_crt_verify_chain_reset(
3210 mbedtls_x509_crt_verify_chain *ver_chain )
3211{
3212 size_t i;
3213
3214 for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
3215 {
3216 ver_chain->items[i].crt = NULL;
3217 ver_chain->items[i].flags = (uint32_t) -1;
3218 }
3219
3220 ver_chain->len = 0;
3221}
3222
3223/*
3224 * Merge the flags for all certs in the chain, after calling callback
3225 */
3226static int x509_crt_verify_chain_get_flags(
3227 const mbedtls_x509_crt_verify_chain *ver_chain,
3228 uint32_t *flags,
3229 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3230 void *p_vrfy )
3231{
3232 int ret;
3233 unsigned i;
3234 uint32_t cur_flags;
3235 const mbedtls_x509_crt_verify_chain_item *cur;
3236
3237 for( i = ver_chain->len; i != 0; --i )
3238 {
3239 cur = &ver_chain->items[i-1];
3240 cur_flags = cur->flags;
3241
3242 if( NULL != f_vrfy )
3243 if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
3244 return( ret );
3245
3246 *flags |= cur_flags;
3247 }
3248
3249 return( 0 );
3250}
3251
3252static void x509_crt_verify_chain_add_ee_flags(
3253 mbedtls_x509_crt_verify_chain *chain,
3254 uint32_t ee_flags )
3255{
3256 chain->items[0].flags |= ee_flags;
3257}
3258
3259static void x509_crt_verify_chain_add_crt(
3260 mbedtls_x509_crt_verify_chain *chain,
3261 mbedtls_x509_crt *crt )
3262{
3263 mbedtls_x509_crt_verify_chain_item *cur;
3264 cur = &chain->items[chain->len];
3265 cur->crt = crt;
3266 cur->flags = 0;
3267 chain->len++;
3268}
3269
3270static uint32_t* x509_crt_verify_chain_get_cur_flags(
3271 mbedtls_x509_crt_verify_chain *chain )
3272{
3273 return( &chain->items[chain->len - 1].flags );
3274}
3275
3276static unsigned x509_crt_verify_chain_len(
3277 mbedtls_x509_crt_verify_chain const *chain )
3278{
3279 return( chain->len );
3280}
3281
Hanno Becker14b0a682019-08-29 15:26:15 +01003282#else /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
Hanno Becker8d6d3202019-08-16 17:18:15 +01003283
3284/*
3285 * Reset (init or clear) a verify_chain
3286 */
3287static void x509_crt_verify_chain_reset(
3288 mbedtls_x509_crt_verify_chain *ver_chain )
3289{
3290 ver_chain->len = 0;
3291 ver_chain->flags = 0;
3292}
3293
3294/*
3295 * Merge the flags for all certs in the chain, after calling callback
3296 */
3297static int x509_crt_verify_chain_get_flags(
3298 const mbedtls_x509_crt_verify_chain *ver_chain,
3299 uint32_t *flags,
3300 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3301 void *p_vrfy )
3302{
3303 ((void) f_vrfy);
3304 ((void) p_vrfy);
3305 *flags = ver_chain->flags;
3306 return( 0 );
3307}
3308
3309static void x509_crt_verify_chain_add_ee_flags(
3310 mbedtls_x509_crt_verify_chain *chain,
3311 uint32_t ee_flags )
3312{
3313 chain->flags |= ee_flags;
3314}
3315
3316static void x509_crt_verify_chain_add_crt(
3317 mbedtls_x509_crt_verify_chain *chain,
3318 mbedtls_x509_crt *crt )
3319{
3320 ((void) crt);
3321 chain->len++;
3322}
3323
3324static uint32_t* x509_crt_verify_chain_get_cur_flags(
3325 mbedtls_x509_crt_verify_chain *chain )
3326{
3327 return( &chain->flags );
3328}
3329
3330static unsigned x509_crt_verify_chain_len(
3331 mbedtls_x509_crt_verify_chain const *chain )
3332{
3333 return( chain->len );
3334}
3335
3336#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
3337
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02003338/*
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003339 * This is used in addition to the flag for a specific issue, to ensure that
3340 * it is not possible for an active physical attacker to entirely clear the
3341 * flags just by flipping a single bit. Take advantage of the fact that all
3342 * values defined in include/mbedtls/x509.h so far are 24-bit or less, so the
3343 * top byte is free.
3344 *
3345 * Currently this protection is not compatible with the vrfy callback (as it
3346 * can observ and modify flags freely), so it's only enabled when the callback
3347 * is disabled.
3348 */
3349#if defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
3350#define X509_BADCERT_FI_EXTRA 0xff000000u
3351#else
3352#define X509_BADCERT_FI_EXTRA 0u
3353#endif
3354
3355/*
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003356 * Build and verify a certificate chain
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02003357 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003358 * Given a peer-provided list of certificates EE, C1, ..., Cn and
3359 * a list of trusted certs R1, ... Rp, try to build and verify a chain
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02003360 * EE, Ci1, ... Ciq [, Rj]
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003361 * such that every cert in the chain is a child of the next one,
3362 * jumping to a trusted root as early as possible.
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003363 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003364 * Verify that chain and return it with flags for all issues found.
3365 *
3366 * Special cases:
3367 * - EE == Rj -> return a one-element list containing it
3368 * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
3369 * -> return that chain with NOT_TRUSTED set on Ciq
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003370 *
Manuel Pégourié-Gonnardd19a41d2017-07-14 11:05:59 +02003371 * Tests for (aspects of) this function should include at least:
3372 * - trusted EE
3373 * - EE -> trusted root
Antonin Décimod5f47592019-01-23 15:24:37 +01003374 * - EE -> intermediate CA -> trusted root
Manuel Pégourié-Gonnardd19a41d2017-07-14 11:05:59 +02003375 * - if relevant: EE untrusted
3376 * - if relevant: EE -> intermediate, untrusted
3377 * with the aspect under test checked at each relevant level (EE, int, root).
3378 * For some aspects longer chains are required, but usually length 2 is
3379 * enough (but length 1 is not in general).
3380 *
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003381 * Arguments:
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003382 * - [in] crt: the cert list EE, C1, ..., Cn
3383 * - [in] trust_ca: the trusted list R1, ..., Rp
3384 * - [in] ca_crl, profile: as in verify_with_profile()
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003385 * - [out] ver_chain: the built and verified chain
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02003386 * Only valid when return value is 0, may contain garbage otherwise!
3387 * Restart note: need not be the same when calling again to resume.
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02003388 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003389 *
3390 * Return value:
3391 * - non-zero if the chain could not be fully built and examined
3392 * - 0 is the chain was successfully built and examined,
3393 * even if it was found to be invalid
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02003394 */
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003395static int x509_crt_verify_chain(
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003396 mbedtls_x509_crt *crt,
3397 mbedtls_x509_crt *trust_ca,
3398 mbedtls_x509_crl *ca_crl,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003399 const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003400 mbedtls_x509_crt_verify_chain *ver_chain,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003401 mbedtls_x509_crt_restart_ctx *rs_ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003402{
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02003403 /* Don't initialize any of those variables here, so that the compiler can
3404 * catch potential issues with jumping ahead when restarting */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003405 int ret;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003406 uint32_t *flags;
Hanno Becker1e0677a2019-02-25 14:58:22 +00003407 mbedtls_x509_crt *child_crt;
Hanno Becker58c35642019-02-25 18:13:46 +00003408 mbedtls_x509_crt *parent_crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003409 int parent_is_trusted;
3410 int child_is_trusted;
3411 int signature_is_good;
Manuel Pégourié-Gonnard81c1fc42019-11-08 11:25:16 +01003412 volatile int signature_is_good_fi;
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02003413 unsigned self_cnt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003414
3415#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3416 /* resume if we had an operation in progress */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003417 if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003418 {
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02003419 /* restore saved state */
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02003420 *ver_chain = rs_ctx->ver_chain; /* struct copy */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003421 self_cnt = rs_ctx->self_cnt;
Hanno Beckeradc282a2019-08-16 17:14:25 +01003422 child_crt = rs_ctx->cur_crt;
Hanno Becker1e0677a2019-02-25 14:58:22 +00003423
3424 child_is_trusted = 0;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003425 goto find_parent;
3426 }
3427#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02003428
Hanno Becker1e0677a2019-02-25 14:58:22 +00003429 child_crt = crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003430 self_cnt = 0;
3431 parent_is_trusted = 0;
3432 child_is_trusted = 0;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02003433
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003434 while( 1 ) {
Hanno Becker5299cf82019-02-25 13:50:41 +00003435#if defined(MBEDTLS_X509_CRL_PARSE_C)
3436 mbedtls_x509_buf_raw child_serial;
3437#endif /* MBEDTLS_X509_CRL_PARSE_C */
3438 int self_issued;
Hanno Becker1e0677a2019-02-25 14:58:22 +00003439
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003440 /* Add certificate to the verification chain */
Hanno Beckeradc282a2019-08-16 17:14:25 +01003441 x509_crt_verify_chain_add_crt( ver_chain, child_crt );
Hanno Becker10e6b9b2019-02-22 17:56:43 +00003442
3443#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3444find_parent:
3445#endif
3446
Hanno Beckeradc282a2019-08-16 17:14:25 +01003447 flags = x509_crt_verify_chain_get_cur_flags( ver_chain );
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02003448
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003449 {
Hanno Becker5299cf82019-02-25 13:50:41 +00003450 mbedtls_x509_crt_sig_info child_sig;
3451 {
Hanno Becker5f268b32019-05-20 16:26:34 +01003452 mbedtls_x509_crt_frame const *child;
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02003453
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003454 ret = mbedtls_x509_crt_frame_acquire( child_crt, &child );
Hanno Becker5299cf82019-02-25 13:50:41 +00003455 if( ret != 0 )
3456 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3457
Hanno Becker843b71a2019-06-25 09:39:21 +01003458#if !defined(MBEDTLS_X509_CRT_REMOVE_TIME)
Hanno Becker5299cf82019-02-25 13:50:41 +00003459 /* Check time-validity (all certificates) */
3460 if( mbedtls_x509_time_is_past( &child->valid_to ) )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003461 *flags |= MBEDTLS_X509_BADCERT_EXPIRED | X509_BADCERT_FI_EXTRA;
Hanno Becker5299cf82019-02-25 13:50:41 +00003462 if( mbedtls_x509_time_is_future( &child->valid_from ) )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003463 *flags |= MBEDTLS_X509_BADCERT_FUTURE | X509_BADCERT_FI_EXTRA;
Hanno Becker843b71a2019-06-25 09:39:21 +01003464#endif /* !MBEDTLS_X509_CRT_REMOVE_TIME */
Hanno Becker5299cf82019-02-25 13:50:41 +00003465
3466 /* Stop here for trusted roots (but not for trusted EE certs) */
3467 if( child_is_trusted )
3468 {
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00003469 mbedtls_x509_crt_frame_release( child_crt );
Hanno Becker5299cf82019-02-25 13:50:41 +00003470 return( 0 );
3471 }
3472
3473 self_issued = 0;
3474 if( mbedtls_x509_name_cmp_raw( &child->issuer_raw,
3475 &child->subject_raw,
3476 NULL, NULL ) == 0 )
3477 {
3478 self_issued = 1;
3479 }
3480
3481 /* Check signature algorithm: MD & PK algs */
3482 if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003483 *flags |= MBEDTLS_X509_BADCERT_BAD_MD | X509_BADCERT_FI_EXTRA;
Hanno Becker5299cf82019-02-25 13:50:41 +00003484
3485 if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003486 *flags |= MBEDTLS_X509_BADCERT_BAD_PK | X509_BADCERT_FI_EXTRA;
Hanno Becker5299cf82019-02-25 13:50:41 +00003487
3488 /* Special case: EE certs that are locally trusted */
Hanno Beckeradc282a2019-08-16 17:14:25 +01003489 if( x509_crt_verify_chain_len( ver_chain ) == 1 && self_issued &&
Hanno Becker5299cf82019-02-25 13:50:41 +00003490 x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
3491 {
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00003492 mbedtls_x509_crt_frame_release( child_crt );
Hanno Becker5299cf82019-02-25 13:50:41 +00003493 return( 0 );
3494 }
3495
3496#if defined(MBEDTLS_X509_CRL_PARSE_C)
3497 child_serial = child->serial;
3498#endif /* MBEDTLS_X509_CRL_PARSE_C */
3499
3500 ret = x509_crt_get_sig_info( child, &child_sig );
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00003501 mbedtls_x509_crt_frame_release( child_crt );
Hanno Becker5299cf82019-02-25 13:50:41 +00003502
Hanno Becker5299cf82019-02-25 13:50:41 +00003503 if( ret != 0 )
3504 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3505 }
3506
3507 /* Look for a parent in trusted CAs or up the chain */
3508 ret = x509_crt_find_parent( &child_sig, child_crt->next,
Hanno Becker58c35642019-02-25 18:13:46 +00003509 trust_ca, &parent_crt,
Hanno Becker5299cf82019-02-25 13:50:41 +00003510 &parent_is_trusted, &signature_is_good,
Hanno Beckeradc282a2019-08-16 17:14:25 +01003511 x509_crt_verify_chain_len( ver_chain ) - 1,
3512 self_cnt, rs_ctx );
Hanno Becker5299cf82019-02-25 13:50:41 +00003513
3514 x509_crt_free_sig_info( &child_sig );
3515 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003516
3517#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003518 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
3519 {
3520 /* save state */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003521 rs_ctx->in_progress = x509_crt_rs_find_parent;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003522 rs_ctx->self_cnt = self_cnt;
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02003523 rs_ctx->ver_chain = *ver_chain; /* struct copy */
Hanno Beckeradc282a2019-08-16 17:14:25 +01003524 rs_ctx->cur_crt = child_crt;
Hanno Becker5299cf82019-02-25 13:50:41 +00003525 return( ret );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003526 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003527#else
3528 (void) ret;
3529#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003530
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003531 /* No parent? We're done here */
Hanno Becker58c35642019-02-25 18:13:46 +00003532 if( parent_crt == NULL )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003533 {
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003534 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED | X509_BADCERT_FI_EXTRA;
Hanno Becker5299cf82019-02-25 13:50:41 +00003535 return( 0 );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003536 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003537
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003538 /* Count intermediate self-issued (not necessarily self-signed) certs.
3539 * These can occur with some strategies for key rollover, see [SIRO],
3540 * and should be excluded from max_pathlen checks. */
Hanno Beckeradc282a2019-08-16 17:14:25 +01003541 if( x509_crt_verify_chain_len( ver_chain ) != 1 && self_issued )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003542 self_cnt++;
Manuel Pégourié-Gonnardfd6c85c2014-11-20 16:34:20 +01003543
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003544 /* path_cnt is 0 for the first intermediate CA,
3545 * and if parent is trusted it's not an intermediate CA */
3546 if( ! parent_is_trusted &&
Hanno Beckeradc282a2019-08-16 17:14:25 +01003547 x509_crt_verify_chain_len( ver_chain ) >
3548 MBEDTLS_X509_MAX_INTERMEDIATE_CA )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003549 {
3550 /* return immediately to avoid overflow the chain array */
Hanno Becker5299cf82019-02-25 13:50:41 +00003551 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003552 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003553
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02003554 /* signature was checked while searching parent */
Manuel Pégourié-Gonnard81c1fc42019-11-08 11:25:16 +01003555 signature_is_good_fi = signature_is_good;
3556 if( signature_is_good_fi != X509_SIGNATURE_IS_GOOD )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003557 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED | X509_BADCERT_FI_EXTRA;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003558
Arto Kinnunenac6d2262020-01-09 10:11:20 +02003559 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard18761922019-11-14 09:19:08 +01003560 if( signature_is_good_fi != X509_SIGNATURE_IS_GOOD )
3561 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED | X509_BADCERT_FI_EXTRA;
Manuel Pégourié-Gonnard81c1fc42019-11-08 11:25:16 +01003562
Hanno Becker58c35642019-02-25 18:13:46 +00003563 {
3564 mbedtls_pk_context *parent_pk;
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003565 ret = mbedtls_x509_crt_pk_acquire( parent_crt, &parent_pk );
Hanno Becker58c35642019-02-25 18:13:46 +00003566 if( ret != 0 )
3567 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3568
3569 /* check size of signing key */
3570 if( x509_profile_check_key( profile, parent_pk ) != 0 )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003571 *flags |= MBEDTLS_X509_BADCERT_BAD_KEY | X509_BADCERT_FI_EXTRA;
Hanno Becker58c35642019-02-25 18:13:46 +00003572
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00003573 mbedtls_x509_crt_pk_release( parent_crt );
Hanno Becker58c35642019-02-25 18:13:46 +00003574 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003576#if defined(MBEDTLS_X509_CRL_PARSE_C)
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003577 /* Check trusted CA's CRL for the given crt */
Hanno Becker5299cf82019-02-25 13:50:41 +00003578 *flags |= x509_crt_verifycrl( child_serial.p,
3579 child_serial.len,
Hanno Becker58c35642019-02-25 18:13:46 +00003580 parent_crt, ca_crl, profile );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003581#else
3582 (void) ca_crl;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003583#endif
3584
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003585 /* prepare for next iteration */
Hanno Becker58c35642019-02-25 18:13:46 +00003586 child_crt = parent_crt;
3587 parent_crt = NULL;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003588 child_is_trusted = parent_is_trusted;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02003589 signature_is_good = 0;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02003590 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003591}
3592
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003593#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003594/*
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003595 * Check for CN match
3596 */
Hanno Becker24926222019-02-21 13:10:55 +00003597static int x509_crt_check_cn( unsigned char const *buf,
3598 size_t buflen,
3599 const char *cn,
3600 size_t cn_len )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003601{
Hanno Becker24926222019-02-21 13:10:55 +00003602 /* Try exact match */
Hanno Beckerb3def1d2019-02-22 11:46:06 +00003603 if( mbedtls_x509_memcasecmp( cn, buf, buflen, cn_len ) == 0 )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003604 return( 0 );
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003605
3606 /* try wildcard match */
Hanno Becker24926222019-02-21 13:10:55 +00003607 if( x509_check_wildcard( cn, cn_len, buf, buflen ) == 0 )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003608 {
3609 return( 0 );
3610 }
3611
3612 return( -1 );
3613}
3614
Hanno Becker8b543b32019-02-21 11:50:44 +00003615/* Returns 1 on a match and 0 on a mismatch.
3616 * This is because this function is used as a callback for
3617 * mbedtls_x509_name_cmp_raw(), which continues the name
3618 * traversal as long as the callback returns 0. */
3619static int x509_crt_check_name( void *ctx,
3620 mbedtls_x509_buf *oid,
Hanno Becker6b378122019-02-23 10:20:14 +00003621 mbedtls_x509_buf *val,
3622 int next_merged )
Hanno Becker8b543b32019-02-21 11:50:44 +00003623{
3624 char const *cn = (char const*) ctx;
3625 size_t cn_len = strlen( cn );
Hanno Becker6b378122019-02-23 10:20:14 +00003626 ((void) next_merged);
Hanno Becker8b543b32019-02-21 11:50:44 +00003627
3628 if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, oid ) == 0 &&
Hanno Becker24926222019-02-21 13:10:55 +00003629 x509_crt_check_cn( val->p, val->len, cn, cn_len ) == 0 )
Hanno Becker8b543b32019-02-21 11:50:44 +00003630 {
3631 return( 1 );
3632 }
3633
3634 return( 0 );
3635}
3636
Hanno Beckerda410822019-02-21 13:36:59 +00003637/* Returns 1 on a match and 0 on a mismatch.
3638 * This is because this function is used as a callback for
3639 * mbedtls_asn1_traverse_sequence_of(), which continues the
3640 * traversal as long as the callback returns 0. */
3641static int x509_crt_subject_alt_check_name( void *ctx,
3642 int tag,
3643 unsigned char *data,
3644 size_t data_len )
3645{
3646 char const *cn = (char const*) ctx;
3647 size_t cn_len = strlen( cn );
Hanno Becker90b94082019-02-21 21:13:21 +00003648 ((void) tag);
Hanno Beckerda410822019-02-21 13:36:59 +00003649
3650 if( x509_crt_check_cn( data, data_len, cn, cn_len ) == 0 )
3651 return( 1 );
3652
3653 return( 0 );
3654}
3655
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02003656/*
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003657 * Verify the requested CN - only call this if cn is not NULL!
3658 */
Hanno Becker082435c2019-02-25 18:14:40 +00003659static int x509_crt_verify_name( const mbedtls_x509_crt *crt,
3660 const char *cn,
3661 uint32_t *flags )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003662{
Hanno Beckerda410822019-02-21 13:36:59 +00003663 int ret;
Hanno Becker5f268b32019-05-20 16:26:34 +01003664 mbedtls_x509_crt_frame const *frame;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003665
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003666 ret = mbedtls_x509_crt_frame_acquire( crt, &frame );
Hanno Becker082435c2019-02-25 18:14:40 +00003667 if( ret != 0 )
3668 return( MBEDTLS_ERR_X509_FATAL_ERROR );
3669
3670 if( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003671 {
Hanno Becker90b94082019-02-21 21:13:21 +00003672 unsigned char *p =
Hanno Becker082435c2019-02-25 18:14:40 +00003673 frame->subject_alt_raw.p;
Hanno Beckerda410822019-02-21 13:36:59 +00003674 const unsigned char *end =
Hanno Becker082435c2019-02-25 18:14:40 +00003675 frame->subject_alt_raw.p + frame->subject_alt_raw.len;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003676
Hanno Becker90b94082019-02-21 21:13:21 +00003677 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
3678 MBEDTLS_ASN1_TAG_CLASS_MASK,
3679 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
3680 MBEDTLS_ASN1_TAG_VALUE_MASK,
3681 2 /* SubjectAlt DNS */,
3682 x509_crt_subject_alt_check_name,
Hanno Becker484caf02019-05-29 14:41:44 +01003683 (void *) cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003684 }
3685 else
3686 {
Hanno Becker082435c2019-02-25 18:14:40 +00003687 ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
3688 &frame->subject_raw,
Hanno Becker484caf02019-05-29 14:41:44 +01003689 x509_crt_check_name, (void *) cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003690 }
Hanno Beckerda410822019-02-21 13:36:59 +00003691
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00003692 mbedtls_x509_crt_frame_release( crt );
Hanno Becker082435c2019-02-25 18:14:40 +00003693
3694 /* x509_crt_check_name() and x509_crt_subject_alt_check_name()
3695 * return 1 when finding a name component matching `cn`. */
3696 if( ret == 1 )
3697 return( 0 );
3698
3699 if( ret != 0 )
3700 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
3701
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003702 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH | X509_BADCERT_FI_EXTRA;
Hanno Becker082435c2019-02-25 18:14:40 +00003703 return( ret );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003704}
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003705#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003706
3707/*
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003708 * Verify the certificate validity (default profile, not restartable)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003710int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
3711 mbedtls_x509_crt *trust_ca,
3712 mbedtls_x509_crl *ca_crl,
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003713#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
3714 const char *cn,
3715#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003716 uint32_t *flags
3717#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
3718 , int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *)
3719 , void *p_vrfy
3720#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
3721 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003722{
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003723 return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003724 &mbedtls_x509_crt_profile_default,
3725#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
3726 cn,
3727#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
3728 flags,
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003729#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
3730 f_vrfy, p_vrfy,
3731#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
3732 NULL ) );
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003733}
3734
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003735/*
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003736 * Verify the certificate validity (user-chosen profile, not restartable)
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003737 */
3738int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
3739 mbedtls_x509_crt *trust_ca,
3740 mbedtls_x509_crl *ca_crl,
3741 const mbedtls_x509_crt_profile *profile,
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003742#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
3743 const char *cn,
3744#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003745 uint32_t *flags
3746#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
3747 , int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *)
3748 , void *p_vrfy
3749#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
3750 )
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02003751{
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003752 return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003753 profile,
3754#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
3755 cn,
3756#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003757 flags,
3758#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
3759 f_vrfy, p_vrfy,
3760#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
3761 NULL ) );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003762}
3763
3764/*
3765 * Verify the certificate validity, with profile, restartable version
3766 *
3767 * This function:
3768 * - checks the requested CN (if any)
3769 * - checks the type and size of the EE cert's key,
3770 * as that isn't done as part of chain building/verification currently
3771 * - builds and verifies the chain
3772 * - then calls the callback and merges the flags
3773 */
3774int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
3775 mbedtls_x509_crt *trust_ca,
3776 mbedtls_x509_crl *ca_crl,
3777 const mbedtls_x509_crt_profile *profile,
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003778#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
3779 const char *cn,
3780#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
3781 uint32_t *flags,
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003782#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003783 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
3784 void *p_vrfy,
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003785#endif /* !MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003786 mbedtls_x509_crt_restart_ctx *rs_ctx )
3787{
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003788 int ret;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003789 mbedtls_x509_crt_verify_chain ver_chain;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003790 uint32_t ee_flags;
Manuel Pégourié-Gonnard9ca11fc2019-11-28 12:07:01 +01003791 volatile uint32_t flags_fi = (uint32_t) -1;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003792
3793 *flags = 0;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003794 ee_flags = 0;
3795 x509_crt_verify_chain_reset( &ver_chain );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003796
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003797 if( profile == NULL )
3798 {
3799 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
3800 goto exit;
3801 }
3802
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003803#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02003804 /* check name if requested */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003805 if( cn != NULL )
Hanno Becker87233362019-02-25 18:15:33 +00003806 {
3807 ret = x509_crt_verify_name( crt, cn, &ee_flags );
3808 if( ret != 0 )
3809 return( ret );
3810 }
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003811#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003812
Hanno Becker87233362019-02-25 18:15:33 +00003813 {
3814 mbedtls_pk_context *pk;
3815 mbedtls_pk_type_t pk_type;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003816
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003817 ret = mbedtls_x509_crt_pk_acquire( crt, &pk );
Hanno Becker87233362019-02-25 18:15:33 +00003818 if( ret != 0 )
3819 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003820
Hanno Becker87233362019-02-25 18:15:33 +00003821 /* Check the type and size of the key */
3822 pk_type = mbedtls_pk_get_type( pk );
3823
3824 if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003825 ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK | X509_BADCERT_FI_EXTRA;
Hanno Becker87233362019-02-25 18:15:33 +00003826
3827 if( x509_profile_check_key( profile, pk ) != 0 )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003828 ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY | X509_BADCERT_FI_EXTRA;
Hanno Becker87233362019-02-25 18:15:33 +00003829
Hanno Beckerc6d1c3e2019-03-05 13:50:56 +00003830 mbedtls_x509_crt_pk_release( crt );
Hanno Becker87233362019-02-25 18:15:33 +00003831 }
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02003832
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02003833 /* Check the chain */
Manuel Pégourié-Gonnard505c3952017-07-05 17:36:47 +02003834 ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02003835 &ver_chain, rs_ctx );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02003836
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02003837 if( ret != 0 )
3838 goto exit;
3839
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003840 /* Merge end-entity flags */
Hanno Beckeradc282a2019-08-16 17:14:25 +01003841 x509_crt_verify_chain_add_ee_flags( &ver_chain, ee_flags );
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003842
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02003843 /* Build final flags, calling callback on the way if any */
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003844#if !defined(MBEDTLS_X509_REMOVE_VERIFY_CALLBACK)
Hanno Beckeradc282a2019-08-16 17:14:25 +01003845 ret = x509_crt_verify_chain_get_flags( &ver_chain, flags, f_vrfy, p_vrfy );
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003846#else
Hanno Beckeradc282a2019-08-16 17:14:25 +01003847 ret = x509_crt_verify_chain_get_flags( &ver_chain, flags, NULL, NULL );
Hanno Becker9ec3fe02019-07-01 17:36:12 +01003848#endif /* MBEDTLS_X509_REMOVE_VERIFY_CALLBACK */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003849
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003850exit:
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003851#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3852 if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
3853 mbedtls_x509_crt_restart_free( rs_ctx );
3854#endif
3855
Manuel Pégourié-Gonnard9107b5f2017-07-06 12:16:25 +02003856 /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
3857 * the SSL module for authmode optional, but non-zero return from the
3858 * callback means a fatal error so it shouldn't be ignored */
Manuel Pégourié-Gonnard31458a12017-06-26 10:11:49 +02003859 if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
3860 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
3861
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02003862 if( ret != 0 )
3863 {
3864 *flags = (uint32_t) -1;
3865 return( ret );
3866 }
3867
Manuel Pégourié-Gonnard4c9b5562019-11-12 10:45:32 +01003868 flags_fi = *flags;
3869 if( flags_fi == 0 )
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003870 {
Arto Kinnunenac6d2262020-01-09 10:11:20 +02003871 mbedtls_platform_random_delay();
Manuel Pégourié-Gonnard4c9b5562019-11-12 10:45:32 +01003872 if( flags_fi == 0 )
3873 return( 0 );
Piotr Nowickie048b912020-06-05 17:59:28 +02003874 else
3875 return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
Manuel Pégourié-Gonnardea7eab12019-11-12 10:31:12 +01003876 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003877
Manuel Pégourié-Gonnard4c9b5562019-11-12 10:45:32 +01003878 /* Preserve the API by removing internal extra bits - from now on the
3879 * fact that flags is non-zero is also redundantly encoded by the
3880 * non-zero return value from this function. */
3881 *flags &= ~ X509_BADCERT_FI_EXTRA;
3882 return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003883}
3884
3885/*
Paul Bakker369d2eb2013-09-18 11:58:25 +02003886 * Initialize a certificate chain
3887 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003888void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
Paul Bakker369d2eb2013-09-18 11:58:25 +02003889{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003890 memset( crt, 0, sizeof(mbedtls_x509_crt) );
Paul Bakker369d2eb2013-09-18 11:58:25 +02003891}
3892
3893/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003894 * Unallocate all certificate data
3895 */
Hanno Beckercd03bb22019-02-15 17:15:53 +00003896
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003897void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003898{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003899 mbedtls_x509_crt *cert_cur = crt;
3900 mbedtls_x509_crt *cert_prv;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003901
3902 if( crt == NULL )
3903 return;
3904
3905 do
3906 {
Hanno Beckerb6c39fc2019-02-25 13:50:14 +00003907 x509_crt_cache_free( cert_cur->cache );
3908 mbedtls_free( cert_cur->cache );
Hanno Becker180f7bf2019-02-28 13:23:38 +00003909
3910#if !defined(MBEDTLS_X509_ON_DEMAND_PARSING)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003911 mbedtls_pk_free( &cert_cur->pk );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003912
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003913#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
3914 mbedtls_free( cert_cur->sig_opts );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +02003915#endif
3916
Hanno Becker2bcc7642019-02-26 19:01:00 +00003917 mbedtls_x509_name_free( cert_cur->issuer.next );
3918 mbedtls_x509_name_free( cert_cur->subject.next );
3919 mbedtls_x509_sequence_free( cert_cur->ext_key_usage.next );
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003920#if !defined(MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION)
Hanno Becker2bcc7642019-02-26 19:01:00 +00003921 mbedtls_x509_sequence_free( cert_cur->subject_alt_names.next );
Teppo Järvelin4009d8f2019-08-19 14:48:09 +03003922#endif /* !MBEDTLS_X509_REMOVE_HOSTNAME_VERIFICATION */
3923
Hanno Becker180f7bf2019-02-28 13:23:38 +00003924#endif /* !MBEDTLS_X509_ON_DEMAND_PARSING */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003925
Hanno Beckeraa8665a2019-01-31 08:57:44 +00003926 if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003927 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05003928 mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003929 mbedtls_free( cert_cur->raw.p );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003930 }
3931
3932 cert_cur = cert_cur->next;
3933 }
3934 while( cert_cur != NULL );
3935
3936 cert_cur = crt;
3937 do
3938 {
3939 cert_prv = cert_cur;
3940 cert_cur = cert_cur->next;
3941
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05003942 mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003943 if( cert_prv != crt )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003944 mbedtls_free( cert_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003945 }
3946 while( cert_cur != NULL );
3947}
3948
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003949#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3950/*
3951 * Initialize a restart context
3952 */
3953void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
3954{
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02003955 mbedtls_pk_restart_init( &ctx->pk );
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003956
3957 ctx->parent = NULL;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01003958#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003959 ctx->fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02003960 ctx->fallback_signature_is_good = 0;
Hanno Becker6f61b7b2019-06-10 11:12:33 +01003961#endif /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003962
3963 ctx->parent_is_trusted = -1;
3964
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02003965 ctx->in_progress = x509_crt_rs_none;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003966 ctx->self_cnt = 0;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02003967 x509_crt_verify_chain_reset( &ctx->ver_chain );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003968}
3969
3970/*
3971 * Free the components of a restart context
3972 */
3973void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
3974{
3975 if( ctx == NULL )
3976 return;
3977
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02003978 mbedtls_pk_restart_free( &ctx->pk );
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02003979 mbedtls_x509_crt_restart_init( ctx );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02003980}
3981#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
3982
Teppo Järvelinffaba552019-09-03 12:33:16 +03003983int mbedtls_x509_crt_frame_acquire( mbedtls_x509_crt const *crt,
3984 mbedtls_x509_crt_frame const **dst )
3985{
3986 int ret = 0;
3987#if defined(MBEDTLS_THREADING_C)
3988 if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
3989 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
3990#endif /* MBEDTLS_THREADING_C */
3991
3992#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
3993 defined(MBEDTLS_THREADING_C)
3994 if( crt->cache->frame_readers == 0 )
3995#endif
3996 ret = mbedtls_x509_crt_cache_provide_frame( crt );
3997
3998#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
3999 defined(MBEDTLS_THREADING_C)
4000 if( crt->cache->frame_readers == MBEDTLS_X509_CACHE_FRAME_READERS_MAX )
4001 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
4002
4003 crt->cache->frame_readers++;
4004#endif
4005
4006#if defined(MBEDTLS_THREADING_C)
4007 if( mbedtls_mutex_unlock( &crt->cache->frame_mutex ) != 0 )
4008 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
4009#endif /* MBEDTLS_THREADING_C */
4010
4011 *dst = crt->cache->frame;
4012 return( ret );
4013}
4014
4015int mbedtls_x509_crt_frame_release( mbedtls_x509_crt const *crt )
4016{
4017#if defined(MBEDTLS_THREADING_C)
4018 if( mbedtls_mutex_lock( &crt->cache->frame_mutex ) != 0 )
4019 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
4020#endif /* MBEDTLS_THREADING_C */
4021
4022#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
4023 defined(MBEDTLS_THREADING_C)
4024 if( crt->cache->frame_readers == 0 )
4025 return( MBEDTLS_ERR_X509_FATAL_ERROR );
4026
4027 crt->cache->frame_readers--;
4028#endif
4029
4030#if defined(MBEDTLS_THREADING_C)
4031 mbedtls_mutex_unlock( &crt->cache->frame_mutex );
4032#endif /* MBEDTLS_THREADING_C */
4033
4034#if defined(MBEDTLS_X509_ALWAYS_FLUSH)
4035 (void) mbedtls_x509_crt_flush_cache_frame( crt );
4036#endif /* MBEDTLS_X509_ALWAYS_FLUSH */
4037
4038#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) && \
4039 !defined(MBEDTLS_THREADING_C)
4040 ((void) crt);
4041#endif
4042
4043 return( 0 );
4044}
4045
4046int mbedtls_x509_crt_pk_acquire( mbedtls_x509_crt const *crt,
4047 mbedtls_pk_context **dst )
4048{
4049 int ret = 0;
4050#if defined(MBEDTLS_THREADING_C)
4051 if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
4052 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
4053#endif /* MBEDTLS_THREADING_C */
4054
4055#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
4056 defined(MBEDTLS_THREADING_C)
4057 if( crt->cache->pk_readers == 0 )
4058#endif
4059 ret = mbedtls_x509_crt_cache_provide_pk( crt );
4060
4061#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
4062 defined(MBEDTLS_THREADING_C)
4063 if( crt->cache->pk_readers == MBEDTLS_X509_CACHE_PK_READERS_MAX )
4064 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
4065
4066 crt->cache->pk_readers++;
4067#endif
4068
4069#if defined(MBEDTLS_THREADING_C)
4070 if( mbedtls_mutex_unlock( &crt->cache->pk_mutex ) != 0 )
4071 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
4072#endif /* MBEDTLS_THREADING_C */
4073
4074 *dst = crt->cache->pk;
4075 return( ret );
4076}
4077
4078int mbedtls_x509_crt_pk_release( mbedtls_x509_crt const *crt )
4079{
4080#if defined(MBEDTLS_THREADING_C)
4081 if( mbedtls_mutex_lock( &crt->cache->pk_mutex ) != 0 )
4082 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
4083#endif /* MBEDTLS_THREADING_C */
4084
4085#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) || \
4086 defined(MBEDTLS_THREADING_C)
4087 if( crt->cache->pk_readers == 0 )
4088 return( MBEDTLS_ERR_X509_FATAL_ERROR );
4089
4090 crt->cache->pk_readers--;
4091#endif
4092
4093#if defined(MBEDTLS_THREADING_C)
4094 mbedtls_mutex_unlock( &crt->cache->pk_mutex );
4095#endif /* MBEDTLS_THREADING_C */
4096
4097#if defined(MBEDTLS_X509_ALWAYS_FLUSH)
4098 (void) mbedtls_x509_crt_flush_cache_pk( crt );
4099#endif /* MBEDTLS_X509_ALWAYS_FLUSH */
4100
4101#if !defined(MBEDTLS_X509_ALWAYS_FLUSH) && \
4102 !defined(MBEDTLS_THREADING_C)
4103 ((void) crt);
4104#endif
4105
4106 return( 0 );
4107}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02004108#endif /* MBEDTLS_X509_CRT_PARSE_C */