blob: 3d50b20b8db3f5a59a8a857c8b090f4b22d807ec [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
Manuel Pégourié-Gonnard1c082f32014-06-12 22:34:55 +02002 * X.509 certificate parsing and verification
Paul Bakker7c6b2c32013-09-16 13:49:26 +02003 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker7c6b2c32013-09-16 13:49:26 +020018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020020 */
21/*
22 * The ITU-T X.509 standard defines a certificate format for PKI.
23 *
Manuel Pégourié-Gonnard1c082f32014-06-12 22:34:55 +020024 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
25 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
26 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020027 *
28 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +020030 *
31 * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020032 */
33
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020034#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000035#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020036#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020037#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020038#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_X509_CRT_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020041
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000042#include "mbedtls/x509_crt.h"
43#include "mbedtls/oid.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050044#include "mbedtls/platform_util.h"
Rich Evans00ab4702015-02-06 13:43:58 +000045
Rich Evans00ab4702015-02-06 13:43:58 +000046#include <string.h>
47
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/pem.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020050#endif
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020054#else
Simon Butcherd2642582018-10-03 15:11:19 +010055#include <stdio.h>
Rich Evans00ab4702015-02-06 13:43:58 +000056#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_free free
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_snprintf snprintf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020060#endif
61
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000063#include "mbedtls/threading.h"
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +010064#endif
65
Paul Bakkerfa6a6202013-10-28 18:48:30 +010066#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020067#include <windows.h>
68#else
69#include <time.h>
70#endif
71
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072#if defined(MBEDTLS_FS_IO)
Rich Evans00ab4702015-02-06 13:43:58 +000073#include <stdio.h>
Paul Bakker5ff3f912014-04-04 15:08:20 +020074#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020075#include <sys/types.h>
76#include <sys/stat.h>
77#include <dirent.h>
Rich Evans00ab4702015-02-06 13:43:58 +000078#endif /* !_WIN32 || EFIX64 || EFI32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +020079#endif
80
Hanno Becker21f55672019-02-15 15:27:59 +000081static int x509_crt_parse_frame( unsigned char *start,
82 unsigned char *end,
83 mbedtls_x509_crt_frame *frame );
84static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame *frame,
85 mbedtls_x509_name *subject );
86static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame *frame,
87 mbedtls_x509_name *issuer );
88static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame *frame,
89 mbedtls_x509_sequence *subject_alt );
90static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame *frame,
91 mbedtls_x509_sequence *ext_key_usage );
92
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +020093/*
94 * Item in a verification chain: cert and flags for it
95 */
96typedef struct {
97 mbedtls_x509_crt *crt;
98 uint32_t flags;
99} x509_crt_verify_chain_item;
100
101/*
102 * Max size of verification chain: end-entity + intermediates + trusted root
103 */
104#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
Paul Bakker34617722014-06-13 17:20:13 +0200105
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200106/*
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200107 * Default profile
108 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200109const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
110{
Gilles Peskine5d2511c2017-05-12 13:16:40 +0200111#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200112 /* Allow SHA-1 (weak, but still safe in controlled environments) */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200113 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200114#endif
115 /* Only SHA-2 hashes */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200116 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
117 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
118 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
119 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
120 0xFFFFFFF, /* Any PK alg */
121 0xFFFFFFF, /* Any curve */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200122 2048,
123};
124
125/*
126 * Next-default profile
127 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200128const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
129{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200130 /* Hashes from SHA-256 and above */
131 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
132 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
133 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
134 0xFFFFFFF, /* Any PK alg */
135#if defined(MBEDTLS_ECP_C)
136 /* Curves at or above 128-bit security level */
137 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
138 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
139 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
140 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
141 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
142 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
143 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
144#else
145 0,
146#endif
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200147 2048,
148};
149
150/*
151 * NSA Suite B Profile
152 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200153const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
154{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200155 /* Only SHA-256 and 384 */
156 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
157 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
158 /* Only ECDSA */
Ron Eldor85e1dcf2018-02-06 15:59:38 +0200159 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
160 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200161#if defined(MBEDTLS_ECP_C)
162 /* Only NIST P-256 and P-384 */
163 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
164 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
165#else
166 0,
167#endif
168 0,
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200169};
170
171/*
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200172 * Check md_alg against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200173 * Return 0 if md_alg is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200174 */
175static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
176 mbedtls_md_type_t md_alg )
177{
Philippe Antoineb5b25432018-05-11 11:06:29 +0200178 if( md_alg == MBEDTLS_MD_NONE )
179 return( -1 );
180
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200181 if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
182 return( 0 );
183
184 return( -1 );
185}
186
187/*
188 * Check pk_alg against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200189 * Return 0 if pk_alg is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200190 */
191static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
192 mbedtls_pk_type_t pk_alg )
193{
Philippe Antoineb5b25432018-05-11 11:06:29 +0200194 if( pk_alg == MBEDTLS_PK_NONE )
195 return( -1 );
196
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200197 if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
198 return( 0 );
199
200 return( -1 );
201}
202
203/*
204 * Check key against profile
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200205 * Return 0 if pk is acceptable for this profile, -1 otherwise
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200206 */
207static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200208 const mbedtls_pk_context *pk )
209{
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200210 const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk );
Manuel Pégourié-Gonnard19773ff2017-10-24 10:51:26 +0200211
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200212#if defined(MBEDTLS_RSA_C)
213 if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
214 {
Manuel Pégourié-Gonnard097c7bb2015-06-18 16:43:38 +0200215 if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200216 return( 0 );
217
218 return( -1 );
219 }
220#endif
221
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +0200222#if defined(MBEDTLS_ECP_C)
223 if( pk_alg == MBEDTLS_PK_ECDSA ||
224 pk_alg == MBEDTLS_PK_ECKEY ||
225 pk_alg == MBEDTLS_PK_ECKEY_DH )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200226 {
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +0200227 const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200228
Philippe Antoineb5b25432018-05-11 11:06:29 +0200229 if( gid == MBEDTLS_ECP_DP_NONE )
230 return( -1 );
231
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200232 if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
233 return( 0 );
234
235 return( -1 );
236 }
237#endif
238
239 return( -1 );
240}
241
242/*
Hanno Becker1f8527f2018-11-02 09:19:16 +0000243 * Return 0 if name matches wildcard, -1 otherwise
244 */
Hanno Becker24926222019-02-21 13:10:55 +0000245static int x509_check_wildcard( char const *cn,
246 size_t cn_len,
247 unsigned char const *buf,
248 size_t buf_len )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000249{
250 size_t i;
Hanno Becker24926222019-02-21 13:10:55 +0000251 size_t cn_idx = 0;
Hanno Becker1f8527f2018-11-02 09:19:16 +0000252
253 /* We can't have a match if there is no wildcard to match */
Hanno Becker24926222019-02-21 13:10:55 +0000254 if( buf_len < 3 || buf[0] != '*' || buf[1] != '.' )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000255 return( -1 );
256
257 for( i = 0; i < cn_len; ++i )
258 {
259 if( cn[i] == '.' )
260 {
261 cn_idx = i;
262 break;
263 }
264 }
265
266 if( cn_idx == 0 )
267 return( -1 );
268
Hanno Beckerb3def1d2019-02-22 11:46:06 +0000269 if( mbedtls_x509_memcasecmp( buf + 1, cn + cn_idx,
270 buf_len - 1, cn_len - cn_idx ) == 0 )
Hanno Becker1f8527f2018-11-02 09:19:16 +0000271 {
272 return( 0 );
273 }
274
275 return( -1 );
276}
277
278/*
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +0200279 * Reset (init or clear) a verify_chain
280 */
281static void x509_crt_verify_chain_reset(
282 mbedtls_x509_crt_verify_chain *ver_chain )
283{
284 size_t i;
285
286 for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
287 {
288 ver_chain->items[i].crt = NULL;
Hanno Beckerd6ddcd62019-01-10 09:19:26 +0000289 ver_chain->items[i].flags = (uint32_t) -1;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +0200290 }
291
292 ver_chain->len = 0;
293}
294
295/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200296 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
297 */
298static int x509_get_version( unsigned char **p,
299 const unsigned char *end,
300 int *ver )
301{
302 int ret;
303 size_t len;
304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
306 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200307 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200309 {
310 *ver = 0;
311 return( 0 );
312 }
313
Hanno Becker2f472142019-02-12 11:52:10 +0000314 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200315 }
316
317 end = *p + len;
318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
320 return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200321
322 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 return( MBEDTLS_ERR_X509_INVALID_VERSION +
324 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200325
326 return( 0 );
327}
328
329/*
330 * Validity ::= SEQUENCE {
331 * notBefore Time,
332 * notAfter Time }
333 */
334static int x509_get_dates( unsigned char **p,
335 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336 mbedtls_x509_time *from,
337 mbedtls_x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200338{
339 int ret;
340 size_t len;
341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
343 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
344 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200345
346 end = *p + len;
347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200349 return( ret );
350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200352 return( ret );
353
354 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 return( MBEDTLS_ERR_X509_INVALID_DATE +
356 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200357
358 return( 0 );
359}
360
361/*
362 * X.509 v2/v3 unique identifier (not parsed)
363 */
364static int x509_get_uid( unsigned char **p,
365 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 mbedtls_x509_buf *uid, int n )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200367{
368 int ret;
369
370 if( *p == end )
371 return( 0 );
372
373 uid->tag = **p;
374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
376 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200377 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200379 return( 0 );
380
Hanno Becker2f472142019-02-12 11:52:10 +0000381 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200382 }
383
384 uid->p = *p;
385 *p += uid->len;
386
387 return( 0 );
388}
389
390static int x509_get_basic_constraints( unsigned char **p,
391 const unsigned char *end,
392 int *ca_istrue,
393 int *max_pathlen )
394{
395 int ret;
396 size_t len;
397
398 /*
399 * BasicConstraints ::= SEQUENCE {
400 * cA BOOLEAN DEFAULT FALSE,
401 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
402 */
403 *ca_istrue = 0; /* DEFAULT FALSE */
404 *max_pathlen = 0; /* endless */
405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
407 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000408 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200409
410 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200411 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200414 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
416 ret = mbedtls_asn1_get_int( p, end, ca_istrue );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200417
418 if( ret != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000419 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200420
421 if( *ca_istrue != 0 )
422 *ca_istrue = 1;
423 }
424
425 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200426 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000429 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200430
431 if( *p != end )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000432 return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200433
434 (*max_pathlen)++;
435
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200436 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200437}
438
439static int x509_get_ns_cert_type( unsigned char **p,
440 const unsigned char *end,
441 unsigned char *ns_cert_type)
442{
443 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000447 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200448
449 if( bs.len != 1 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000450 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200451
452 /* Get actual bitstring */
453 *ns_cert_type = *bs.p;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200454 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200455}
456
457static int x509_get_key_usage( unsigned char **p,
458 const unsigned char *end,
Manuel Pégourié-Gonnard1d0ca1a2015-03-27 16:50:00 +0100459 unsigned int *key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200460{
461 int ret;
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200462 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000466 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200467
468 if( bs.len < 1 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000469 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200470
471 /* Get actual bitstring */
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200472 *key_usage = 0;
473 for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
474 {
475 *key_usage |= (unsigned int) bs.p[i] << (8*i);
476 }
477
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200478 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200479}
480
481/*
482 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
483 *
484 * KeyPurposeId ::= OBJECT IDENTIFIER
485 */
486static int x509_get_ext_key_usage( unsigned char **p,
487 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 mbedtls_x509_sequence *ext_key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200489{
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000490 return( mbedtls_asn1_get_sequence_of( p, end, ext_key_usage,
491 MBEDTLS_ASN1_OID ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200492}
493
494/*
495 * SubjectAltName ::= GeneralNames
496 *
497 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
498 *
499 * GeneralName ::= CHOICE {
500 * otherName [0] OtherName,
501 * rfc822Name [1] IA5String,
502 * dNSName [2] IA5String,
503 * x400Address [3] ORAddress,
504 * directoryName [4] Name,
505 * ediPartyName [5] EDIPartyName,
506 * uniformResourceIdentifier [6] IA5String,
507 * iPAddress [7] OCTET STRING,
508 * registeredID [8] OBJECT IDENTIFIER }
509 *
510 * OtherName ::= SEQUENCE {
511 * type-id OBJECT IDENTIFIER,
512 * value [0] EXPLICIT ANY DEFINED BY type-id }
513 *
514 * EDIPartyName ::= SEQUENCE {
515 * nameAssigner [0] DirectoryString OPTIONAL,
516 * partyName [1] DirectoryString }
517 *
Manuel Pégourié-Gonnardb4fe3cb2015-01-22 16:11:05 +0000518 * NOTE: we only parse and use dNSName at this point.
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200519 */
Hanno Beckerad462192019-02-21 13:32:31 +0000520static int x509_get_subject_alt_name_cb( void *ctx,
521 int tag,
522 unsigned char *data,
523 size_t data_len )
524{
525 mbedtls_asn1_sequence **cur_ptr = (mbedtls_asn1_sequence **) ctx;
526 mbedtls_asn1_sequence *cur = *cur_ptr;
527
Hanno Beckerad462192019-02-21 13:32:31 +0000528 /* Allocate and assign next pointer */
529 if( cur->buf.p != NULL )
530 {
531 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
532 if( cur->next == NULL )
Hanno Becker90b94082019-02-21 21:13:21 +0000533 return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
Hanno Beckerad462192019-02-21 13:32:31 +0000534 cur = cur->next;
535 }
536
537 cur->buf.tag = tag;
538 cur->buf.p = data;
539 cur->buf.len = data_len;
540
541 *cur_ptr = cur;
542 return( 0 );
543}
544
Hanno Becker5984d302019-02-21 14:46:54 +0000545static int x509_get_subject_alt_name( unsigned char *p,
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200546 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 mbedtls_x509_sequence *subject_alt_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200548{
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000549 return( mbedtls_asn1_traverse_sequence_of( &p, end,
550 MBEDTLS_ASN1_TAG_CLASS_MASK,
551 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
552 MBEDTLS_ASN1_TAG_VALUE_MASK,
553 2 /* SubjectAlt DNS */,
554 x509_get_subject_alt_name_cb,
555 (void*) &subject_alt_name ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200556}
557
558/*
559 * X.509 v3 extensions
560 *
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200561 */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000562static int x509_crt_get_ext_cb( void *ctx,
563 int tag,
564 unsigned char *p,
565 size_t ext_len )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200566{
567 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +0000568 mbedtls_x509_crt_frame *frame = (mbedtls_x509_crt_frame *) ctx;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200569 size_t len;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000570 unsigned char *end, *end_ext_octet;
571 mbedtls_x509_buf extn_oid = { 0, 0, NULL };
572 int is_critical = 0; /* DEFAULT FALSE */
573 int ext_type = 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200574
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000575 ((void) tag);
Hanno Becker4e1bfc12019-02-12 17:22:36 +0000576
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000577 /*
578 * Extension ::= SEQUENCE {
579 * extnID OBJECT IDENTIFIER,
580 * critical BOOLEAN DEFAULT FALSE,
581 * extnValue OCTET STRING }
582 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200583
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000584 end = p + ext_len;
585
586 /* Get extension ID */
587 if( ( ret = mbedtls_asn1_get_tag( &p, end, &extn_oid.len,
588 MBEDTLS_ASN1_OID ) ) != 0 )
589 goto err;
590
591 extn_oid.tag = MBEDTLS_ASN1_OID;
592 extn_oid.p = p;
593 p += extn_oid.len;
594
595 /* Get optional critical */
596 if( ( ret = mbedtls_asn1_get_bool( &p, end, &is_critical ) ) != 0 &&
597 ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
598 goto err;
599
600 /* Data should be octet string type */
601 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
602 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
603 goto err;
604
605 end_ext_octet = p + len;
606 if( end_ext_octet != end )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200607 {
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000608 ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
609 goto err;
610 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200611
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000612 /*
613 * Detect supported extensions
614 */
615 ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
616 if( ret != 0 )
617 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000619 if( is_critical )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200620 {
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000621 /* Data is marked as critical: fail */
622 ret = MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
623 goto err;
624 }
625#endif
626 return( 0 );
627 }
628
629 /* Forbid repeated extensions */
Hanno Becker21f55672019-02-15 15:27:59 +0000630 if( ( frame->ext_types & ext_type ) != 0 )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000631 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
632
Hanno Becker21f55672019-02-15 15:27:59 +0000633 frame->ext_types |= ext_type;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000634 switch( ext_type )
635 {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100636 case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000637 {
638 int ca_istrue;
639 int max_pathlen;
640
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200641 /* Parse basic constraints */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000642 ret = x509_get_basic_constraints( &p, end_ext_octet,
643 &ca_istrue,
644 &max_pathlen );
645 if( ret != 0 )
646 goto err;
647
Hanno Becker21f55672019-02-15 15:27:59 +0000648 frame->ca_istrue = ca_istrue;
649 frame->max_pathlen = max_pathlen;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200650 break;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000651 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 case MBEDTLS_X509_EXT_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200654 /* Parse key usage */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000655 ret = x509_get_key_usage( &p, end_ext_octet,
Hanno Becker21f55672019-02-15 15:27:59 +0000656 &frame->key_usage );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000657 if( ret != 0 )
658 goto err;
659 break;
660
661 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
662 /* Copy reference to raw subject alt name data. */
Hanno Becker21f55672019-02-15 15:27:59 +0000663 frame->subject_alt_raw.p = p;
664 frame->subject_alt_raw.len = end_ext_octet - p;
665
666 ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
667 MBEDTLS_ASN1_TAG_CLASS_MASK,
668 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
669 MBEDTLS_ASN1_TAG_VALUE_MASK,
670 2 /* SubjectAlt DNS */,
671 NULL, NULL );
672 if( ret != 0 )
673 goto err;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200674 break;
675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200677 /* Parse extended key usage */
Hanno Becker21f55672019-02-15 15:27:59 +0000678 frame->ext_key_usage_raw.p = p;
679 frame->ext_key_usage_raw.len = end_ext_octet - p;
680 if( frame->ext_key_usage_raw.len == 0 )
Hanno Becker5984d302019-02-21 14:46:54 +0000681 {
Hanno Becker21f55672019-02-15 15:27:59 +0000682 ret = MBEDTLS_ERR_ASN1_INVALID_LENGTH;
683 goto err;
Hanno Becker5984d302019-02-21 14:46:54 +0000684 }
Hanno Becker21f55672019-02-15 15:27:59 +0000685
686 /* Check structural sanity of extension. */
687 ret = mbedtls_asn1_traverse_sequence_of( &p, end_ext_octet,
688 0xFF, MBEDTLS_ASN1_OID,
689 0, 0, NULL, NULL );
690 if( ret != 0 )
691 goto err;
692
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200693 break;
694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200696 /* Parse netscape certificate type */
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000697 ret = x509_get_ns_cert_type( &p, end_ext_octet,
Hanno Becker21f55672019-02-15 15:27:59 +0000698 &frame->ns_cert_type );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000699 if( ret != 0 )
700 goto err;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200701 break;
702
703 default:
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000704 /*
705 * If this is a non-critical extension, which the oid layer
706 * supports, but there isn't an X.509 parser for it,
707 * skip the extension.
708 */
709#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
710 if( is_critical )
711 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
712#endif
713 p = end_ext_octet;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200714 }
715
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200716 return( 0 );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000717
718err:
719 return( ret );
720}
721
Hanno Becker21f55672019-02-15 15:27:59 +0000722static int x509_crt_frame_parse_ext( mbedtls_x509_crt_frame *frame )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000723{
724 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +0000725 unsigned char *p = frame->v3_ext.p;
726 unsigned char *end = p + frame->v3_ext.len;
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000727
Hanno Becker21f55672019-02-15 15:27:59 +0000728 if( p == end )
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000729 return( 0 );
730
Hanno Becker21f55672019-02-15 15:27:59 +0000731 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000732 0xFF, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED,
Hanno Becker21f55672019-02-15 15:27:59 +0000733 0, 0, x509_crt_get_ext_cb, frame );
Hanno Beckerf1b39bf2019-02-22 11:09:48 +0000734
735 if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
736 return( ret );
737 if( ret == MBEDTLS_ERR_X509_INVALID_EXTENSIONS )
738 return( ret );
739
740 if( ret != 0 )
741 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
742
743 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200744}
745
Hanno Becker21f55672019-02-15 15:27:59 +0000746static int x509_crt_parse_frame( unsigned char *start,
747 unsigned char *end,
748 mbedtls_x509_crt_frame *frame )
749{
750 int ret;
751 unsigned char *p;
752 size_t len;
753
754 mbedtls_x509_buf tmp;
755 unsigned char *tbs_start;
756
757 mbedtls_x509_buf outer_sig_alg;
758 size_t inner_sig_alg_len;
759 unsigned char *inner_sig_alg_start;
760
761 memset( frame, 0, sizeof( *frame ) );
762
763 /*
764 * Certificate ::= SEQUENCE {
765 * tbsCertificate TBSCertificate,
766 * signatureAlgorithm AlgorithmIdentifier,
767 * signatureValue BIT STRING
768 * }
769 *
770 */
771 p = start;
772
773 frame->raw.p = p;
774 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
775 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
776 {
777 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
778 }
779
780 /* NOTE: We are currently not checking that the `Certificate`
781 * structure spans the entire buffer. */
782 end = p + len;
783 frame->raw.len = end - frame->raw.p;
784
785 /*
786 * TBSCertificate ::= SEQUENCE { ...
787 */
788 frame->tbs.p = p;
789 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
790 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
791 {
792 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
793 }
794 tbs_start = p;
795
796 /* Breadth-first parsing: Jump over TBS for now. */
797 p += len;
798 frame->tbs.len = p - frame->tbs.p;
799
800 /*
801 * AlgorithmIdentifier ::= SEQUENCE { ...
802 */
803 outer_sig_alg.p = p;
804 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
805 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
806 {
807 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
808 }
809 p += len;
810 outer_sig_alg.len = p - outer_sig_alg.p;
811
812 /*
813 * signatureValue BIT STRING
814 */
815 ret = mbedtls_x509_get_sig( &p, end, &tmp );
816 if( ret != 0 )
817 return( ret );
818 frame->sig.p = tmp.p;
819 frame->sig.len = tmp.len;
820
821 /* Check that we consumed the entire `Certificate` structure. */
822 if( p != end )
823 {
824 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
825 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
826 }
827
828 /* Parse TBSCertificate structure
829 *
830 * TBSCertificate ::= SEQUENCE {
831 * version [0] EXPLICIT Version DEFAULT v1,
832 * serialNumber CertificateSerialNumber,
833 * signature AlgorithmIdentifier,
834 * issuer Name,
835 * validity Validity,
836 * subject Name,
837 * subjectPublicKeyInfo SubjectPublicKeyInfo,
838 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
839 * -- If present, version MUST be v2 or v3
840 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
841 * -- If present, version MUST be v2 or v3
842 * extensions [3] EXPLICIT Extensions OPTIONAL
843 * -- If present, version MUST be v3
844 * }
845 */
846 end = frame->tbs.p + frame->tbs.len;
847 p = tbs_start;
848
849 /*
850 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
851 */
852 {
853 int version;
854 ret = x509_get_version( &p, end, &version );
855 if( ret != 0 )
856 return( ret );
857
858 if( version < 0 || version > 2 )
859 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
860
861 frame->version = version + 1;
862 }
863
864 /*
865 * CertificateSerialNumber ::= INTEGER
866 */
867 ret = mbedtls_x509_get_serial( &p, end, &tmp );
868 if( ret != 0 )
869 return( ret );
870
871 frame->serial.p = tmp.p;
872 frame->serial.len = tmp.len;
873
874 /*
875 * signature AlgorithmIdentifier
876 */
877 inner_sig_alg_start = p;
878 ret = mbedtls_x509_get_sig_alg_raw( &p, end, &frame->sig_md,
879 &frame->sig_pk, NULL );
880 if( ret != 0 )
881 return( ret );
882 inner_sig_alg_len = p - inner_sig_alg_start;
883
884 frame->sig_alg.p = inner_sig_alg_start;
885 frame->sig_alg.len = inner_sig_alg_len;
886
887 /* Consistency check:
888 * Inner and outer AlgorithmIdentifier structures must coincide:
889 *
890 * Quoting RFC 5280, Section 4.1.1.2:
891 * This field MUST contain the same algorithm identifier as the
892 * signature field in the sequence tbsCertificate (Section 4.1.2.3).
893 */
894 if( outer_sig_alg.len != inner_sig_alg_len ||
895 memcmp( outer_sig_alg.p, inner_sig_alg_start, inner_sig_alg_len ) != 0 )
896 {
897 return( MBEDTLS_ERR_X509_SIG_MISMATCH );
898 }
899
900 /*
901 * issuer Name
902 *
903 * Name ::= CHOICE { -- only one possibility for now --
904 * rdnSequence RDNSequence }
905 *
906 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
907 */
908 frame->issuer_raw_with_hdr.p = p;
909
910 ret = mbedtls_asn1_get_tag( &p, end, &len,
911 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
912 if( ret != 0 )
913 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
914 frame->issuer_raw.p = p;
915 frame->issuer_raw.len = len;
916 p += len;
917
918 ret = mbedtls_x509_name_cmp_raw( &frame->issuer_raw,
919 &frame->issuer_raw,
920 NULL, NULL );
921 if( ret != 0 )
922 return( ret );
923
924 frame->issuer_raw_with_hdr.len = p - frame->issuer_raw_with_hdr.p;
925
926 /*
927 * Validity ::= SEQUENCE { ...
928 */
929 ret = x509_get_dates( &p, end, &frame->valid_from, &frame->valid_to );
930 if( ret != 0 )
931 return( ret );
932
933 /*
934 * subject Name
935 *
936 * Name ::= CHOICE { -- only one possibility for now --
937 * rdnSequence RDNSequence }
938 *
939 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
940 */
941 frame->subject_raw_with_hdr.p = p;
942
943 ret = mbedtls_asn1_get_tag( &p, end, &len,
944 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
945 if( ret != 0 )
946 return( ret + MBEDTLS_ERR_X509_INVALID_FORMAT );
947 frame->subject_raw.p = p;
948 frame->subject_raw.len = len;
949 p += len;
950
951 ret = mbedtls_x509_name_cmp_raw( &frame->subject_raw,
952 &frame->subject_raw,
953 NULL, NULL );
954 if( ret != 0 )
955 return( ret );
956
957 frame->subject_raw_with_hdr.len = p - frame->subject_raw_with_hdr.p;
958
959 /*
960 * SubjectPublicKeyInfo
961 */
962 frame->pubkey_raw.p = p;
963 ret = mbedtls_asn1_get_tag( &p, end, &len,
964 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
965 if( ret != 0 )
966 return( ret + MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
967 p += len;
968 frame->pubkey_raw.len = p - frame->pubkey_raw.p;
969
970 /*
971 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
972 * -- If present, version shall be v2 or v3
973 */
974 if( frame->version == 2 || frame->version == 3 )
975 {
976 ret = x509_get_uid( &p, end, &tmp, 1 /* implicit tag */ );
977 if( ret != 0 )
978 return( ret );
979
980 frame->issuer_id.p = tmp.p;
981 frame->issuer_id.len = tmp.len;
982 }
983
984 /*
985 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
986 * -- If present, version shall be v2 or v3
987 */
988 if( frame->version == 2 || frame->version == 3 )
989 {
990 ret = x509_get_uid( &p, end, &tmp, 2 /* implicit tag */ );
991 if( ret != 0 )
992 return( ret );
993
994 frame->subject_id.p = tmp.p;
995 frame->subject_id.len = tmp.len;
996 }
997
998 /*
999 * extensions [3] EXPLICIT Extensions OPTIONAL
1000 * -- If present, version shall be v3
1001 */
1002#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
1003 if( frame->version == 3 )
1004#endif
1005 {
1006 if( p != end )
1007 {
1008 ret = mbedtls_asn1_get_tag( &p, end, &len,
1009 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
1010 MBEDTLS_ASN1_CONSTRUCTED | 3 );
1011 if( len == 0 )
1012 ret = MBEDTLS_ERR_ASN1_OUT_OF_DATA;
1013 if( ret != 0 )
1014 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
1015
1016 frame->v3_ext.p = p;
1017 frame->v3_ext.len = len;
1018
1019 p += len;
1020 }
1021
1022 ret = x509_crt_frame_parse_ext( frame );
1023 if( ret != 0 )
1024 return( ret );
1025 }
1026
1027 /* Wrapup: Check that we consumed the entire `TBSCertificate` structure. */
1028 if( p != end )
1029 {
1030 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
1031 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
1032 }
1033
1034 return( 0 );
1035}
1036
1037static int x509_crt_subject_from_frame( mbedtls_x509_crt_frame *frame,
1038 mbedtls_x509_name *subject )
1039{
1040 unsigned char *p = frame->subject_raw.p;
1041 unsigned char *end = p + frame->subject_raw.len;
1042
1043 return( mbedtls_x509_get_name( &p, end, subject ) );
1044}
1045
1046static int x509_crt_issuer_from_frame( mbedtls_x509_crt_frame *frame,
1047 mbedtls_x509_name *issuer )
1048{
1049 unsigned char *p = frame->issuer_raw.p;
1050 unsigned char *end = p + frame->issuer_raw.len;
1051
1052 return( mbedtls_x509_get_name( &p, end, issuer ) );
1053}
1054
1055static int x509_crt_subject_alt_from_frame( mbedtls_x509_crt_frame *frame,
1056 mbedtls_x509_sequence *subject_alt )
1057{
1058 int ret;
1059 unsigned char *p = frame->subject_alt_raw.p;
1060 unsigned char *end = p + frame->subject_alt_raw.len;
1061
1062 memset( subject_alt, 0, sizeof( *subject_alt ) );
1063
1064 if( ( frame->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) == 0 )
1065 return( 0 );
1066
1067 ret = x509_get_subject_alt_name( p, end, subject_alt );
1068 if( ret != 0 )
1069 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1070 return( ret );
1071}
1072
1073static int x509_crt_ext_key_usage_from_frame( mbedtls_x509_crt_frame *frame,
1074 mbedtls_x509_sequence *ext_key_usage )
1075{
1076 int ret;
1077 unsigned char *p = frame->ext_key_usage_raw.p;
1078 unsigned char *end = p + frame->ext_key_usage_raw.len;
1079
1080 memset( ext_key_usage, 0, sizeof( *ext_key_usage ) );
1081
1082 if( ( frame->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
1083 return( 0 );
1084
1085 ret = x509_get_ext_key_usage( &p, end, ext_key_usage );
1086 if( ret != 0 )
1087 {
1088 ret += MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1089 return( ret );
1090 }
1091
1092 return( 0 );
1093}
1094
1095static int x509_crt_pk_from_frame( mbedtls_x509_crt_frame *frame,
1096 mbedtls_pk_context *pk )
1097{
1098 unsigned char *p = frame->pubkey_raw.p;
1099 unsigned char *end = p + frame->pubkey_raw.len;
1100 return( mbedtls_pk_parse_subpubkey( &p, end, pk ) );
1101}
1102
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001103/*
1104 * Parse and fill a single X.509 certificate in DER format
1105 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001106static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
1107 const unsigned char *buf,
1108 size_t buflen,
1109 int make_copy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001110{
1111 int ret;
Hanno Becker21f55672019-02-15 15:27:59 +00001112 mbedtls_x509_crt_frame frame;
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +01001113
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001114 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001116
Hanno Becker21f55672019-02-15 15:27:59 +00001117 if( make_copy == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001118 {
Hanno Becker21f55672019-02-15 15:27:59 +00001119 crt->raw.p = (unsigned char*) buf;
1120 crt->raw.len = buflen;
1121 crt->own_buffer = 0;
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001122 }
1123 else
1124 {
Hanno Becker21f55672019-02-15 15:27:59 +00001125 crt->raw.p = mbedtls_calloc( 1, buflen );
1126 if( crt->raw.p == NULL )
1127 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
1128 crt->raw.len = buflen;
1129 memcpy( crt->raw.p, buf, buflen );
1130
1131 crt->own_buffer = 1;
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001132 }
Janos Follathcc0e49d2016-02-17 14:34:12 +00001133
Hanno Becker21f55672019-02-15 15:27:59 +00001134 /* Parse CRT frame.
1135 * This omits:
1136 * - Issuer, Subject
1137 * - ExtKeyUsage, SubjectAltNames,
1138 * - Time
1139 * - PK
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001140 */
Hanno Becker21f55672019-02-15 15:27:59 +00001141 ret = x509_crt_parse_frame( crt->raw.p,
1142 crt->raw.p + crt->raw.len,
1143 &frame );
1144 if( ret != 0 )
1145 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001146
Hanno Becker21f55672019-02-15 15:27:59 +00001147 /* Currently, we accept DER encoded CRTs with trailing garbage
1148 * and promise to not account for the garbage in the `raw` field.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001149 *
Hanno Becker21f55672019-02-15 15:27:59 +00001150 * Note that this means that `crt->raw.len` is not necessarily the
1151 * full size of the heap buffer allocated at `crt->raw.p` in case
1152 * of copy-mode, but this is not a problem: freeing the buffer doesn't
1153 * need the size, and the garbage data doesn't need zeroization. */
1154 crt->raw.len = frame->raw.len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001155
Hanno Becker21f55672019-02-15 15:27:59 +00001156 /* Copy frame to legacy CRT structure -- that's inefficient, but if
1157 * memory matters, the new CRT structure should be used anyway. */
1158 crt->tbs.p = frame.tbs.p;
1159 crt->tbs.len = frame.tbs.len;
1160 crt->serial.p = frame.serial.p;
1161 crt->serial.len = frame.serial.len;
1162 crt->issuer_raw.p = frame.issuer_raw_with_hdr.p;
1163 crt->issuer_raw.len = frame.issuer_raw_with_hdr.len;
1164 crt->subject_raw.p = frame.subject_raw_with_hdr.p;
1165 crt->subject_raw.len = frame.subject_raw_with_hdr.len;
1166 crt->issuer_raw_no_hdr = frame.issuer_raw;
1167 crt->subject_raw_no_hdr = frame.subject_raw;
1168 crt->issuer_id.p = frame.issuer_id.p;
1169 crt->issuer_id.len = frame.issuer_id.len;
1170 crt->subject_id.p = frame.subject_id.p;
1171 crt->subject_id.len = frame.subject_id.len;
1172 crt->pk_raw.p = frame.pubkey_raw.p;
1173 crt->pk_raw.len = frame.pubkey_raw.len;
1174 crt->ext_key_usage_raw = frame.ext_key_usage_raw;
1175 crt->subject_alt_raw = frame.subject_alt_raw;
1176 crt->sig.p = frame.sig.p;
1177 crt->sig.len = frame.sig.len;
1178 crt->valid_from = frame.valid_from;
1179 crt->valid_to = frame.valid_to;
1180 crt->v3_ext.p = frame.v3_ext.p;
1181 crt->v3_ext.len = frame.v3_ext.len;
1182 crt->version = frame.version;
1183 crt->ca_istrue = frame.ca_istrue;
1184 crt->max_pathlen = frame.max_pathlen;
1185 crt->ext_types = frame.ext_types;
1186 crt->key_usage = frame.key_usage;
1187 crt->ns_cert_type = frame.ns_cert_type;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001188
1189 /*
Hanno Becker21f55672019-02-15 15:27:59 +00001190 * Obtain the remaining fields from the frame.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001191 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001192
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001193 {
Hanno Becker21f55672019-02-15 15:27:59 +00001194 /* sig_oid: Previously, needed for convenience in
1195 * mbedtls_x509_crt_info(), now pure legacy burden. */
1196 unsigned char *tmp = frame.sig_alg.p;
1197 unsigned char *end = tmp + frame.sig_alg.len;
1198 mbedtls_x509_buf sig_oid, sig_params;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001199
Hanno Becker21f55672019-02-15 15:27:59 +00001200 ret = mbedtls_x509_get_alg( &tmp, end,
1201 &sig_oid, &sig_params );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001202 if( ret != 0 )
1203 {
Hanno Becker21f55672019-02-15 15:27:59 +00001204 /* This should never happen, because we check
1205 * the sanity of the AlgorithmIdentifier structure
1206 * during frame parsing. */
1207 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1208 goto exit;
1209 }
1210 crt->sig_oid = sig_oid;
1211
1212 /* Signature parameters */
1213 tmp = frame.sig_alg.p;
1214 ret = mbedtls_x509_get_sig_alg_raw( &tmp, end,
1215 &crt->sig_md, &crt->sig_pk,
1216 &crt->sig_opts );
1217 if( ret != 0 )
1218 {
1219 /* Again, this should never happen. */
1220 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
1221 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001222 }
1223 }
1224
Hanno Becker21f55672019-02-15 15:27:59 +00001225 ret = x509_crt_pk_from_frame( &frame, &crt->pk );
1226 if( ret != 0 )
1227 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001228
Hanno Becker21f55672019-02-15 15:27:59 +00001229 ret = x509_crt_subject_from_frame( &frame, &crt->subject );
1230 if( ret != 0 )
1231 goto exit;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001232
Hanno Becker21f55672019-02-15 15:27:59 +00001233 ret = x509_crt_issuer_from_frame( &frame, &crt->issuer );
1234 if( ret != 0 )
1235 goto exit;
1236
1237 ret = x509_crt_subject_alt_from_frame( &frame, &crt->subject_alt_names );
1238 if( ret != 0 )
1239 goto exit;
1240
1241 ret = x509_crt_ext_key_usage_from_frame( &frame, &crt->ext_key_usage );
1242 if( ret != 0 )
1243 goto exit;
1244
1245exit:
1246 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001248
Hanno Becker21f55672019-02-15 15:27:59 +00001249 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001250}
1251
1252/*
1253 * Parse one X.509 certificate in DER format from a buffer and add them to a
1254 * chained list
1255 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001256static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
1257 const unsigned char *buf,
1258 size_t buflen,
1259 int make_copy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001260{
1261 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 mbedtls_x509_crt *crt = chain, *prev = NULL;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001263
1264 /*
1265 * Check for valid input
1266 */
1267 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001268 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001269
1270 while( crt->version != 0 && crt->next != NULL )
1271 {
1272 prev = crt;
1273 crt = crt->next;
1274 }
1275
1276 /*
1277 * Add new certificate on the end of the chain if needed.
1278 */
Paul Bakker66d5d072014-06-17 16:39:18 +02001279 if( crt->version != 0 && crt->next == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001280 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001281 crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001282
1283 if( crt->next == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001284 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001285
1286 prev = crt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287 mbedtls_x509_crt_init( crt->next );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001288 crt = crt->next;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001289 }
1290
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001291 if( ( ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001292 {
1293 if( prev )
1294 prev->next = NULL;
1295
1296 if( crt != chain )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001297 mbedtls_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001298
1299 return( ret );
1300 }
1301
1302 return( 0 );
1303}
1304
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001305int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain,
1306 const unsigned char *buf,
1307 size_t buflen )
1308{
1309 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0 ) );
1310}
1311
1312int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain,
1313 const unsigned char *buf,
1314 size_t buflen )
1315{
1316 return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1 ) );
1317}
1318
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001319/*
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001320 * Parse one or more PEM certificates from a buffer and add them to the chained
1321 * list
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001322 */
Hanno Beckeraa8665a2019-01-31 08:57:44 +00001323int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
1324 const unsigned char *buf,
1325 size_t buflen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001326{
Janos Follath98e28a72016-05-31 14:03:54 +01001327#if defined(MBEDTLS_PEM_PARSE_C)
Andres AGc0db5112016-12-07 15:05:53 +00001328 int success = 0, first_error = 0, total_failed = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001329 int buf_format = MBEDTLS_X509_FORMAT_DER;
Janos Follath98e28a72016-05-31 14:03:54 +01001330#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001331
1332 /*
1333 * Check for valid input
1334 */
1335 if( chain == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001337
1338 /*
1339 * Determine buffer content. Buffer contains either one DER certificate or
1340 * one or more PEM certificates.
1341 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001342#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001343 if( buflen != 0 && buf[buflen - 1] == '\0' &&
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001344 strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
1345 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 buf_format = MBEDTLS_X509_FORMAT_PEM;
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001347 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 if( buf_format == MBEDTLS_X509_FORMAT_DER )
1350 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
Janos Follath98e28a72016-05-31 14:03:54 +01001351#else
1352 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
1353#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001354
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355#if defined(MBEDTLS_PEM_PARSE_C)
1356 if( buf_format == MBEDTLS_X509_FORMAT_PEM )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001357 {
1358 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359 mbedtls_pem_context pem;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001360
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001361 /* 1 rather than 0 since the terminating NULL byte is counted in */
1362 while( buflen > 1 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001363 {
1364 size_t use_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 mbedtls_pem_init( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001366
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001367 /* If we get there, we know the string is null-terminated */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 ret = mbedtls_pem_read_buffer( &pem,
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001369 "-----BEGIN CERTIFICATE-----",
1370 "-----END CERTIFICATE-----",
1371 buf, NULL, 0, &use_len );
1372
1373 if( ret == 0 )
1374 {
1375 /*
1376 * Was PEM encoded
1377 */
1378 buflen -= use_len;
1379 buf += use_len;
1380 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001382 {
1383 return( ret );
1384 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001386 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001388
1389 /*
1390 * PEM header and footer were found
1391 */
1392 buflen -= use_len;
1393 buf += use_len;
1394
1395 if( first_error == 0 )
1396 first_error = ret;
1397
Paul Bakker5a5fa922014-09-26 14:53:04 +02001398 total_failed++;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001399 continue;
1400 }
1401 else
1402 break;
1403
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001404 ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001407
1408 if( ret != 0 )
1409 {
1410 /*
1411 * Quit parsing on a memory error
1412 */
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001413 if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001414 return( ret );
1415
1416 if( first_error == 0 )
1417 first_error = ret;
1418
1419 total_failed++;
1420 continue;
1421 }
1422
1423 success = 1;
1424 }
1425 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001426
1427 if( success )
1428 return( total_failed );
1429 else if( first_error )
1430 return( first_error );
1431 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
Janos Follath98e28a72016-05-31 14:03:54 +01001433#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001434}
1435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436#if defined(MBEDTLS_FS_IO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001437/*
1438 * Load one or more certificates and add them to the chained list
1439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001441{
1442 int ret;
1443 size_t n;
1444 unsigned char *buf;
1445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001447 return( ret );
1448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001449 ret = mbedtls_x509_crt_parse( chain, buf, n );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001450
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05001451 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001452 mbedtls_free( buf );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001453
1454 return( ret );
1455}
1456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001457int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001458{
1459 int ret = 0;
Paul Bakkerfa6a6202013-10-28 18:48:30 +01001460#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001461 int w_ret;
1462 WCHAR szDir[MAX_PATH];
1463 char filename[MAX_PATH];
Paul Bakker9af723c2014-05-01 13:03:14 +02001464 char *p;
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001465 size_t len = strlen( path );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001466
Paul Bakker9af723c2014-05-01 13:03:14 +02001467 WIN32_FIND_DATAW file_data;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001468 HANDLE hFind;
1469
1470 if( len > MAX_PATH - 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001472
Paul Bakker9af723c2014-05-01 13:03:14 +02001473 memset( szDir, 0, sizeof(szDir) );
1474 memset( filename, 0, MAX_PATH );
1475 memcpy( filename, path, len );
1476 filename[len++] = '\\';
1477 p = filename + len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001478 filename[len++] = '*';
1479
Simon B3c6b18d2016-11-03 01:11:37 +00001480 w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001481 MAX_PATH - 3 );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001482 if( w_ret == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001484
1485 hFind = FindFirstFileW( szDir, &file_data );
Paul Bakker66d5d072014-06-17 16:39:18 +02001486 if( hFind == INVALID_HANDLE_VALUE )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001488
1489 len = MAX_PATH - len;
1490 do
1491 {
Paul Bakker9af723c2014-05-01 13:03:14 +02001492 memset( p, 0, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001493
1494 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
1495 continue;
1496
Paul Bakker9af723c2014-05-01 13:03:14 +02001497 w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
Paul Bakker66d5d072014-06-17 16:39:18 +02001498 lstrlenW( file_data.cFileName ),
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001499 p, (int) len - 1,
Paul Bakker9af723c2014-05-01 13:03:14 +02001500 NULL, NULL );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001501 if( w_ret == 0 )
Ron Eldor36d90422017-01-09 15:09:16 +02001502 {
1503 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
1504 goto cleanup;
1505 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 w_ret = mbedtls_x509_crt_parse_file( chain, filename );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001508 if( w_ret < 0 )
1509 ret++;
1510 else
1511 ret += w_ret;
1512 }
1513 while( FindNextFileW( hFind, &file_data ) != 0 );
1514
Paul Bakker66d5d072014-06-17 16:39:18 +02001515 if( GetLastError() != ERROR_NO_MORE_FILES )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001517
Ron Eldor36d90422017-01-09 15:09:16 +02001518cleanup:
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001519 FindClose( hFind );
Paul Bakkerbe089b02013-10-14 15:51:50 +02001520#else /* _WIN32 */
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001521 int t_ret;
Andres AGf9113192016-09-02 14:06:04 +01001522 int snp_ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001523 struct stat sb;
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001524 struct dirent *entry;
Andres AGf9113192016-09-02 14:06:04 +01001525 char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001526 DIR *dir = opendir( path );
1527
Paul Bakker66d5d072014-06-17 16:39:18 +02001528 if( dir == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001529 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001530
Ron Eldor63140682017-01-09 19:27:59 +02001531#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02001532 if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02001533 {
1534 closedir( dir );
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001535 return( ret );
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02001536 }
Ron Eldor63140682017-01-09 19:27:59 +02001537#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001538
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001539 while( ( entry = readdir( dir ) ) != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001540 {
Andres AGf9113192016-09-02 14:06:04 +01001541 snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
1542 "%s/%s", path, entry->d_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001543
Andres AGf9113192016-09-02 14:06:04 +01001544 if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001545 {
Andres AGf9113192016-09-02 14:06:04 +01001546 ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1547 goto cleanup;
1548 }
1549 else if( stat( entry_name, &sb ) == -1 )
1550 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001552 goto cleanup;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001553 }
1554
1555 if( !S_ISREG( sb.st_mode ) )
1556 continue;
1557
1558 // Ignore parse errors
1559 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001561 if( t_ret < 0 )
1562 ret++;
1563 else
1564 ret += t_ret;
1565 }
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001566
1567cleanup:
Andres AGf9113192016-09-02 14:06:04 +01001568 closedir( dir );
1569
Ron Eldor63140682017-01-09 19:27:59 +02001570#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02001571 if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
Ron Eldor63140682017-01-09 19:27:59 +02001573#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001574
Paul Bakkerbe089b02013-10-14 15:51:50 +02001575#endif /* _WIN32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001576
1577 return( ret );
1578}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579#endif /* MBEDTLS_FS_IO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001580
Hanno Becker02a21932019-06-10 15:08:43 +01001581#if !defined(MBEDTLS_X509_REMOVE_INFO)
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001582static int x509_info_subject_alt_name( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583 const mbedtls_x509_sequence *subject_alt_name )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001584{
1585 size_t i;
1586 size_t n = *size;
1587 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 const mbedtls_x509_sequence *cur = subject_alt_name;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001589 const char *sep = "";
1590 size_t sep_len = 0;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001591
1592 while( cur != NULL )
1593 {
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001594 if( cur->buf.len + sep_len >= n )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001595 {
1596 *p = '\0';
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001597 return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001598 }
1599
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001600 n -= cur->buf.len + sep_len;
1601 for( i = 0; i < sep_len; i++ )
1602 *p++ = sep[i];
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001603 for( i = 0; i < cur->buf.len; i++ )
1604 *p++ = cur->buf.p[i];
1605
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001606 sep = ", ";
1607 sep_len = 2;
1608
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001609 cur = cur->next;
1610 }
1611
1612 *p = '\0';
1613
1614 *size = n;
1615 *buf = p;
1616
1617 return( 0 );
1618}
1619
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001620#define PRINT_ITEM(i) \
1621 { \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001623 MBEDTLS_X509_SAFE_SNPRINTF; \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001624 sep = ", "; \
1625 }
1626
1627#define CERT_TYPE(type,name) \
Hanno Beckerd6028a12018-10-15 12:01:35 +01001628 if( ns_cert_type & (type) ) \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001629 PRINT_ITEM( name );
1630
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001631static int x509_info_cert_type( char **buf, size_t *size,
1632 unsigned char ns_cert_type )
1633{
1634 int ret;
1635 size_t n = *size;
1636 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001637 const char *sep = "";
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001640 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" );
1642 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" );
1643 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001644 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" );
1645 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" );
1646 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" );
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001647
1648 *size = n;
1649 *buf = p;
1650
1651 return( 0 );
1652}
1653
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001654#define KEY_USAGE(code,name) \
Hanno Beckerd6028a12018-10-15 12:01:35 +01001655 if( key_usage & (code) ) \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001656 PRINT_ITEM( name );
1657
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001658static int x509_info_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02001659 unsigned int key_usage )
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001660{
1661 int ret;
1662 size_t n = *size;
1663 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001664 const char *sep = "";
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" );
1667 KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001668 KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" );
1669 KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" );
1670 KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" );
1672 KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" );
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02001673 KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" );
1674 KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" );
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001675
1676 *size = n;
1677 *buf = p;
1678
1679 return( 0 );
1680}
1681
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001682static int x509_info_ext_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 const mbedtls_x509_sequence *extended_key_usage )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001684{
1685 int ret;
1686 const char *desc;
1687 size_t n = *size;
1688 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001689 const mbedtls_x509_sequence *cur = extended_key_usage;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001690 const char *sep = "";
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001691
1692 while( cur != NULL )
1693 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001694 if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001695 desc = "???";
1696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001698 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001699
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001700 sep = ", ";
1701
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001702 cur = cur->next;
1703 }
1704
1705 *size = n;
1706 *buf = p;
1707
1708 return( 0 );
1709}
1710
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001711/*
1712 * Return an informational string about the certificate.
1713 */
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001714#define BEFORE_COLON 18
1715#define BC "18"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
1717 const mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001718{
1719 int ret;
1720 size_t n;
1721 char *p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001722 char key_size_str[BEFORE_COLON];
1723
1724 p = buf;
1725 n = size;
1726
Janos Follath98e28a72016-05-31 14:03:54 +01001727 if( NULL == crt )
1728 {
1729 ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
1730 MBEDTLS_X509_SAFE_SNPRINTF;
1731
1732 return( (int) ( size - n ) );
1733 }
1734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001735 ret = mbedtls_snprintf( p, n, "%scert. version : %d\n",
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001736 prefix, crt->version );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001737 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 ret = mbedtls_snprintf( p, n, "%sserial number : ",
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001739 prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001740 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001741
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001742 ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001743 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001746 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747 ret = mbedtls_x509_dn_gets( p, n, &crt->issuer );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001748 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001751 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001752 ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001753 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001754
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 ret = mbedtls_snprintf( p, n, "\n%sissued on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001756 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1757 crt->valid_from.year, crt->valid_from.mon,
1758 crt->valid_from.day, crt->valid_from.hour,
1759 crt->valid_from.min, crt->valid_from.sec );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001760 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001761
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001763 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1764 crt->valid_to.year, crt->valid_to.mon,
1765 crt->valid_to.day, crt->valid_to.hour,
1766 crt->valid_to.min, crt->valid_to.sec );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001767 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001769 ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001770 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001771
Hanno Becker83cd8672019-02-21 17:13:46 +00001772 ret = mbedtls_x509_sig_alg_gets( p, n, sig_info.sig_pk,
1773 sig_info.sig_md, sig_info.sig_opts );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001774 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001775
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001776 /* Key size */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001777 if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
1778 mbedtls_pk_get_name( &crt->pk ) ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001779 {
1780 return( ret );
1781 }
1782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001783 ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
Manuel Pégourié-Gonnard097c7bb2015-06-18 16:43:38 +02001784 (int) mbedtls_pk_get_bitlen( &crt->pk ) );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001785 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001786
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001787 /*
1788 * Optional extensions
1789 */
1790
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001791 if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001792 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001794 crt->ca_istrue ? "true" : "false" );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001795 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001796
1797 if( crt->max_pathlen > 0 )
1798 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001800 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001801 }
1802 }
1803
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001804 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001805 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001807 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001808
1809 if( ( ret = x509_info_subject_alt_name( &p, &n,
1810 &crt->subject_alt_names ) ) != 0 )
1811 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001812 }
1813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001815 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001816 ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001817 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001818
1819 if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
1820 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001821 }
1822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001824 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001825 ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001826 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001827
1828 if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
1829 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001830 }
1831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001833 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834 ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001835 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001836
1837 if( ( ret = x509_info_ext_key_usage( &p, &n,
1838 &crt->ext_key_usage ) ) != 0 )
1839 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001840 }
1841
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 ret = mbedtls_snprintf( p, n, "\n" );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001843 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001844
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001845 return( (int) ( size - n ) );
1846}
1847
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001848struct x509_crt_verify_string {
1849 int code;
1850 const char *string;
1851};
1852
1853static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001854 { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001855 { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
1856 { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" },
1857 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" },
1858 { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" },
1859 { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001860 { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" },
1861 { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" },
1862 { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001863 { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001864 { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" },
1865 { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" },
1866 { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
1867 { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" },
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02001868 { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." },
1869 { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
1870 { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
1871 { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." },
1872 { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
1873 { 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 +01001874 { 0, NULL }
1875};
1876
1877int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02001878 uint32_t flags )
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001879{
1880 int ret;
1881 const struct x509_crt_verify_string *cur;
1882 char *p = buf;
1883 size_t n = size;
1884
1885 for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
1886 {
1887 if( ( flags & cur->code ) == 0 )
1888 continue;
1889
1890 ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001891 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001892 flags ^= cur->code;
1893 }
1894
1895 if( flags != 0 )
1896 {
1897 ret = mbedtls_snprintf( p, n, "%sUnknown reason "
1898 "(this should not happen)\n", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001899 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001900 }
1901
1902 return( (int) ( size - n ) );
1903}
Hanno Becker02a21932019-06-10 15:08:43 +01001904#endif /* !MBEDTLS_X509_REMOVE_INFO */
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Manuel Pégourié-Gonnard655a9642015-06-23 10:48:44 +02001907int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
1908 unsigned int usage )
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02001909{
Manuel Pégourié-Gonnard655a9642015-06-23 10:48:44 +02001910 unsigned int usage_must, usage_may;
1911 unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
1912 | MBEDTLS_X509_KU_DECIPHER_ONLY;
1913
1914 if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
1915 return( 0 );
1916
1917 usage_must = usage & ~may_mask;
1918
1919 if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
1920 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
1921
1922 usage_may = usage & may_mask;
1923
1924 if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02001926
1927 return( 0 );
1928}
1929#endif
1930
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001931#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
Hanno Beckerc7c638e2019-02-21 21:10:51 +00001932typedef struct
1933{
1934 const char *oid;
1935 size_t oid_len;
1936} x509_crt_check_ext_key_usage_cb_ctx_t;
1937
1938static int x509_crt_check_ext_key_usage_cb( void *ctx,
1939 int tag,
1940 unsigned char *data,
1941 size_t data_len )
1942{
1943 x509_crt_check_ext_key_usage_cb_ctx_t *cb_ctx =
1944 (x509_crt_check_ext_key_usage_cb_ctx_t *) ctx;
1945 ((void) tag);
1946
1947 if( MBEDTLS_OID_CMP_RAW( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE,
1948 data, data_len ) == 0 )
1949 {
1950 return( 1 );
1951 }
1952
1953 if( data_len == cb_ctx->oid_len && memcmp( data, cb_ctx->oid,
1954 data_len ) == 0 )
1955 {
1956 return( 1 );
1957 }
1958
1959 return( 0 );
1960}
1961
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
Hanno Beckere1956af2019-02-21 14:28:12 +00001963 const char *usage_oid,
1964 size_t usage_len )
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001965{
Hanno Beckere1956af2019-02-21 14:28:12 +00001966 int ret;
Hanno Beckere1956af2019-02-21 14:28:12 +00001967 unsigned ext_types;
1968 unsigned char *p, *end;
Hanno Beckerc7c638e2019-02-21 21:10:51 +00001969 x509_crt_check_ext_key_usage_cb_ctx_t cb_ctx = { usage_oid, usage_len };
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001970
1971 /* Extension is not mandatory, absent means no restriction */
Hanno Beckere1956af2019-02-21 14:28:12 +00001972 ext_types = crt->ext_types;
1973 if( ( ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001974 return( 0 );
1975
Hanno Beckere1956af2019-02-21 14:28:12 +00001976 p = crt->ext_key_usage_raw.p;
1977 end = p + crt->ext_key_usage_raw.len;
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001978
Hanno Beckerc7c638e2019-02-21 21:10:51 +00001979 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
1980 0xFF, MBEDTLS_ASN1_OID, 0, 0,
1981 x509_crt_check_ext_key_usage_cb,
1982 &cb_ctx );
1983 if( ret == 1 )
1984 return( 0 );
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001985
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001987}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990#if defined(MBEDTLS_X509_CRL_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001991/*
1992 * Return 1 if the certificate is revoked, or 0 otherwise.
1993 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00001994static int x509_serial_is_revoked( unsigned char const *serial,
1995 size_t serial_len,
1996 const mbedtls_x509_crl *crl )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001997{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001998 const mbedtls_x509_crl_entry *cur = &crl->entry;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001999
2000 while( cur != NULL && cur->serial.len != 0 )
2001 {
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002002 if( serial_len == cur->serial.len &&
2003 memcmp( serial, cur->serial.p, serial_len ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002004 {
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002005 if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002006 return( 1 );
2007 }
2008
2009 cur = cur->next;
2010 }
2011
2012 return( 0 );
2013}
2014
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002015int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt,
2016 const mbedtls_x509_crl *crl )
2017{
2018 return( x509_serial_is_revoked( crt->serial.p,
2019 crt->serial.len,
2020 crl ) );
2021}
2022
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002023/*
Manuel Pégourié-Gonnardeeef9472016-02-22 11:36:55 +01002024 * Check that the given certificate is not revoked according to the CRL.
Manuel Pégourié-Gonnard08eacec2017-10-18 14:20:24 +02002025 * Skip validation if no CRL for the given CA is present.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002026 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002027static int x509_crt_verifycrl( unsigned char *crt_serial,
2028 size_t crt_serial_len,
2029 mbedtls_x509_crt *ca,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002030 mbedtls_x509_crl *crl_list,
2031 const mbedtls_x509_crt_profile *profile )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002032{
2033 int flags = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
2035 const mbedtls_md_info_t *md_info;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002036
2037 if( ca == NULL )
2038 return( flags );
2039
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002040 while( crl_list != NULL )
2041 {
2042 if( crl_list->version == 0 ||
Hanno Becker7dee12a2019-02-21 13:58:38 +00002043 mbedtls_x509_name_cmp_raw( &crl_list->issuer_raw_no_hdr,
Hanno Becker67284cc2019-02-21 14:31:51 +00002044 &ca->subject_raw_no_hdr,
2045 NULL, NULL ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002046 {
2047 crl_list = crl_list->next;
2048 continue;
2049 }
2050
2051 /*
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002052 * Check if the CA is configured to sign CRLs
2053 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Hanno Beckerb75ffb52018-11-02 09:19:54 +00002055 if( mbedtls_x509_crt_check_key_usage( ca,
2056 MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002057 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02002059 break;
2060 }
2061#endif
2062
2063 /*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002064 * Check if CRL is correctly signed by the trusted CA
2065 */
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002066 if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
2067 flags |= MBEDTLS_X509_BADCRL_BAD_MD;
2068
2069 if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
2070 flags |= MBEDTLS_X509_BADCRL_BAD_PK;
2071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 md_info = mbedtls_md_info_from_type( crl_list->sig_md );
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02002073 if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002074 {
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02002075 /* Note: this can't happen except after an internal error */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002077 break;
2078 }
2079
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +02002080 if( x509_profile_check_key( profile, &ca->pk ) != 0 )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002081 flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002083 if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
2084 crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
Manuel Pégourié-Gonnard53882022014-06-05 17:53:52 +02002085 crl_list->sig.p, crl_list->sig.len ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002086 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002087 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002088 break;
2089 }
2090
2091 /*
2092 * Check for validity of CRL (Do not drop out)
2093 */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002094 if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 flags |= MBEDTLS_X509_BADCRL_EXPIRED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002096
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01002097 if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01002098 flags |= MBEDTLS_X509_BADCRL_FUTURE;
Manuel Pégourié-Gonnard95337652014-03-10 13:15:18 +01002099
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002100 /*
2101 * Check if certificate is revoked
2102 */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002103 if( x509_serial_is_revoked( crt_serial, crt_serial_len,
2104 crl_list ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002105 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002106 flags |= MBEDTLS_X509_BADCERT_REVOKED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002107 break;
2108 }
2109
2110 crl_list = crl_list->next;
2111 }
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02002112
Paul Bakkerd8bb8262014-06-17 14:06:49 +02002113 return( flags );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002114}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115#endif /* MBEDTLS_X509_CRL_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002116
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02002117/*
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002118 * Check the signature of a certificate by its parent
2119 */
2120static int x509_crt_check_signature( const mbedtls_x509_crt *child,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002121 mbedtls_x509_crt *parent,
2122 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002123{
2124 const mbedtls_md_info_t *md_info;
2125 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
2126
2127 md_info = mbedtls_md_info_from_type( child->sig_md );
2128 if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
2129 {
2130 /* Note: this can't happen except after an internal error */
2131 return( -1 );
2132 }
2133
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002134 /* Skip expensive computation on obvious mismatch */
2135 if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002136 return( -1 );
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002137
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002138#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002139 if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
2140 {
2141 return( mbedtls_pk_verify_restartable( &parent->pk,
2142 child->sig_md, hash, mbedtls_md_get_size( md_info ),
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02002143 child->sig.p, child->sig.len, &rs_ctx->pk ) );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002144 }
2145#else
2146 (void) rs_ctx;
2147#endif
2148
2149 return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
2150 child->sig_md, hash, mbedtls_md_get_size( md_info ),
2151 child->sig.p, child->sig.len ) );
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002152}
2153
2154/*
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002155 * Check if 'parent' is a suitable parent (signing CA) for 'child'.
2156 * Return 0 if yes, -1 if not.
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002157 *
2158 * top means parent is a locally-trusted certificate
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160static int x509_crt_check_parent( const mbedtls_x509_crt *child,
2161 const mbedtls_x509_crt *parent,
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002162 int top )
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002163{
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002164 int need_ca_bit;
2165
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02002166 /* Parent must be the issuer */
Hanno Becker7dee12a2019-02-21 13:58:38 +00002167 if( mbedtls_x509_name_cmp_raw( &child->issuer_raw_no_hdr,
Hanno Becker67284cc2019-02-21 14:31:51 +00002168 &parent->subject_raw_no_hdr,
2169 NULL, NULL ) != 0 )
Hanno Becker7dee12a2019-02-21 13:58:38 +00002170 {
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002171 return( -1 );
Hanno Becker7dee12a2019-02-21 13:58:38 +00002172 }
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002173
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002174 /* Parent must have the basicConstraints CA bit set as a general rule */
2175 need_ca_bit = 1;
2176
2177 /* Exception: v1/v2 certificates that are locally trusted. */
2178 if( top && parent->version < 3 )
2179 need_ca_bit = 0;
2180
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002181 if( need_ca_bit && ! parent->ca_istrue )
2182 return( -1 );
2183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02002185 if( need_ca_bit &&
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02002187 {
2188 return( -1 );
2189 }
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02002190#endif
2191
2192 return( 0 );
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02002193}
2194
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002195/*
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002196 * Find a suitable parent for child in candidates, or return NULL.
2197 *
2198 * Here suitable is defined as:
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002199 * 1. subject name matches child's issuer
2200 * 2. if necessary, the CA bit is set and key usage allows signing certs
2201 * 3. for trusted roots, the signature is correct
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002202 * (for intermediates, the signature is checked and the result reported)
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002203 * 4. pathlen constraints are satisfied
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002204 *
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002205 * If there's a suitable candidate which is also time-valid, return the first
2206 * such. Otherwise, return the first suitable candidate (or NULL if there is
2207 * none).
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002208 *
2209 * The rationale for this rule is that someone could have a list of trusted
2210 * roots with two versions on the same root with different validity periods.
2211 * (At least one user reported having such a list and wanted it to just work.)
2212 * The reason we don't just require time-validity is that generally there is
2213 * only one version, and if it's expired we want the flags to state that
2214 * rather than NOT_TRUSTED, as would be the case if we required it here.
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002215 *
2216 * The rationale for rule 3 (signature for trusted roots) is that users might
2217 * have two versions of the same CA with different keys in their list, and the
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002218 * way we select the correct one is by checking the signature (as we don't
2219 * rely on key identifier extensions). (This is one way users might choose to
2220 * handle key rollover, another relies on self-issued certs, see [SIRO].)
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002221 *
2222 * Arguments:
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002223 * - [in] child: certificate for which we're looking for a parent
2224 * - [in] candidates: chained list of potential parents
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002225 * - [out] r_parent: parent found (or NULL)
2226 * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002227 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
2228 * of the chain, 0 otherwise
2229 * - [in] path_cnt: number of intermediates seen so far
2230 * - [in] self_cnt: number of self-signed intermediates seen so far
2231 * (will never be greater than path_cnt)
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002232 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002233 *
2234 * Return value:
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002235 * - 0 on success
2236 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002237 */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002238static int x509_crt_find_parent_in(
2239 mbedtls_x509_crt *child,
2240 mbedtls_x509_crt *candidates,
2241 mbedtls_x509_crt **r_parent,
2242 int *r_signature_is_good,
2243 int top,
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002244 unsigned path_cnt,
2245 unsigned self_cnt,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002246 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002247{
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002248 int ret;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002249 mbedtls_x509_crt *parent, *fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002250 int signature_is_good, fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002251
2252#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002253 /* did we have something in progress? */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002254 if( rs_ctx != NULL && rs_ctx->parent != NULL )
2255 {
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002256 /* restore saved state */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002257 parent = rs_ctx->parent;
2258 fallback_parent = rs_ctx->fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002259 fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002260
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002261 /* clear saved state */
2262 rs_ctx->parent = NULL;
2263 rs_ctx->fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002264 rs_ctx->fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002265
2266 /* resume where we left */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002267 goto check_signature;
2268 }
2269#endif
2270
2271 fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002272 fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002273
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002274 for( parent = candidates; parent != NULL; parent = parent->next )
2275 {
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002276 /* basic parenting skills (name, CA bit, key usage) */
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002277 if( x509_crt_check_parent( child, parent, top ) != 0 )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002278 continue;
2279
Manuel Pégourié-Gonnard9c6118c2017-06-29 12:38:42 +02002280 /* +1 because stored max_pathlen is 1 higher that the actual value */
2281 if( parent->max_pathlen > 0 &&
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002282 (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt )
Manuel Pégourié-Gonnard9c6118c2017-06-29 12:38:42 +02002283 {
2284 continue;
2285 }
2286
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002287 /* Signature */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002288#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2289check_signature:
2290#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002291 ret = x509_crt_check_signature( child, parent, rs_ctx );
2292
2293#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002294 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
2295 {
2296 /* save state */
2297 rs_ctx->parent = parent;
2298 rs_ctx->fallback_parent = fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002299 rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002300
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002301 return( ret );
2302 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002303#else
2304 (void) ret;
2305#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002306
2307 signature_is_good = ret == 0;
2308 if( top && ! signature_is_good )
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002309 continue;
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02002310
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002311 /* optional time check */
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002312 if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
2313 mbedtls_x509_time_is_future( &parent->valid_from ) )
2314 {
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002315 if( fallback_parent == NULL )
2316 {
2317 fallback_parent = parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002318 fallback_signature_is_good = signature_is_good;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002319 }
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002320
2321 continue;
2322 }
2323
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002324 break;
2325 }
2326
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002327 if( parent != NULL )
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002328 {
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002329 *r_parent = parent;
2330 *r_signature_is_good = signature_is_good;
2331 }
2332 else
2333 {
2334 *r_parent = fallback_parent;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002335 *r_signature_is_good = fallback_signature_is_good;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002336 }
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02002337
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002338 return( 0 );
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02002339}
2340
2341/*
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002342 * Find a parent in trusted CAs or the provided chain, or return NULL.
2343 *
2344 * Searches in trusted CAs first, and return the first suitable parent found
2345 * (see find_parent_in() for definition of suitable).
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002346 *
2347 * Arguments:
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002348 * - [in] child: certificate for which we're looking for a parent, followed
2349 * by a chain of possible intermediates
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002350 * - [in] trust_ca: list of locally trusted certificates
2351 * - [out] parent: parent found (or NULL)
2352 * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
2353 * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
2354 * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
2355 * - [in] self_cnt: number of self-signed certs in the chain so far
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002356 * (will always be no greater than path_cnt)
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002357 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnarde57d7432018-03-07 10:00:57 +01002358 *
2359 * Return value:
Manuel Pégourié-Gonnardda19f4c2018-06-12 12:40:54 +02002360 * - 0 on success
2361 * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002362 */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002363static int x509_crt_find_parent(
2364 mbedtls_x509_crt *child,
2365 mbedtls_x509_crt *trust_ca,
2366 mbedtls_x509_crt **parent,
2367 int *parent_is_trusted,
2368 int *signature_is_good,
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002369 unsigned path_cnt,
2370 unsigned self_cnt,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002371 mbedtls_x509_crt_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002372{
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002373 int ret;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002374 mbedtls_x509_crt *search_list;
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002375
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002376 *parent_is_trusted = 1;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002377
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002378#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002379 /* restore then clear saved state if we have some stored */
2380 if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
2381 {
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002382 *parent_is_trusted = rs_ctx->parent_is_trusted;
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002383 rs_ctx->parent_is_trusted = -1;
2384 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002385#endif
2386
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002387 while( 1 ) {
2388 search_list = *parent_is_trusted ? trust_ca : child->next;
2389
2390 ret = x509_crt_find_parent_in( child, search_list,
2391 parent, signature_is_good,
2392 *parent_is_trusted,
2393 path_cnt, self_cnt, rs_ctx );
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002394
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002395#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002396 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
2397 {
2398 /* save state */
2399 rs_ctx->parent_is_trusted = *parent_is_trusted;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002400 return( ret );
2401 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002402#else
2403 (void) ret;
2404#endif
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002405
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002406 /* stop here if found or already in second iteration */
2407 if( *parent != NULL || *parent_is_trusted == 0 )
2408 break;
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002409
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002410 /* prepare second iteration */
2411 *parent_is_trusted = 0;
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002412 }
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002413
2414 /* extra precaution against mistakes in the caller */
Krzysztof Stachowiakc388a8c2018-10-31 16:49:20 +01002415 if( *parent == NULL )
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002416 {
Manuel Pégourié-Gonnarda5a3e402018-10-16 11:27:23 +02002417 *parent_is_trusted = 0;
2418 *signature_is_good = 0;
Manuel Pégourié-Gonnard18547b52017-08-14 16:11:43 +02002419 }
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002420
2421 return( 0 );
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002422}
2423
2424/*
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002425 * Check if an end-entity certificate is locally trusted
2426 *
2427 * Currently we require such certificates to be self-signed (actually only
2428 * check for self-issued as self-signatures are not checked)
2429 */
2430static int x509_crt_check_ee_locally_trusted(
2431 mbedtls_x509_crt *crt,
2432 mbedtls_x509_crt *trust_ca )
2433{
2434 mbedtls_x509_crt *cur;
2435
2436 /* must be self-issued */
Hanno Becker7dee12a2019-02-21 13:58:38 +00002437 if( mbedtls_x509_name_cmp_raw( &crt->issuer_raw_no_hdr,
Hanno Becker67284cc2019-02-21 14:31:51 +00002438 &crt->subject_raw_no_hdr,
2439 NULL, NULL ) != 0 )
Hanno Becker7dee12a2019-02-21 13:58:38 +00002440 {
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002441 return( -1 );
Hanno Becker7dee12a2019-02-21 13:58:38 +00002442 }
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002443
2444 /* look for an exact match with trusted cert */
2445 for( cur = trust_ca; cur != NULL; cur = cur->next )
2446 {
2447 if( crt->raw.len == cur->raw.len &&
2448 memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
2449 {
2450 return( 0 );
2451 }
2452 }
2453
2454 /* too bad */
2455 return( -1 );
2456}
2457
2458/*
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002459 * Build and verify a certificate chain
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002460 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002461 * Given a peer-provided list of certificates EE, C1, ..., Cn and
2462 * a list of trusted certs R1, ... Rp, try to build and verify a chain
Manuel Pégourié-Gonnard562df402017-08-08 18:09:14 +02002463 * EE, Ci1, ... Ciq [, Rj]
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002464 * such that every cert in the chain is a child of the next one,
2465 * jumping to a trusted root as early as possible.
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002466 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002467 * Verify that chain and return it with flags for all issues found.
2468 *
2469 * Special cases:
2470 * - EE == Rj -> return a one-element list containing it
2471 * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
2472 * -> return that chain with NOT_TRUSTED set on Ciq
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002473 *
Manuel Pégourié-Gonnardd19a41d2017-07-14 11:05:59 +02002474 * Tests for (aspects of) this function should include at least:
2475 * - trusted EE
2476 * - EE -> trusted root
2477 * - EE -> intermedate CA -> trusted root
2478 * - if relevant: EE untrusted
2479 * - if relevant: EE -> intermediate, untrusted
2480 * with the aspect under test checked at each relevant level (EE, int, root).
2481 * For some aspects longer chains are required, but usually length 2 is
2482 * enough (but length 1 is not in general).
2483 *
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002484 * Arguments:
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002485 * - [in] crt: the cert list EE, C1, ..., Cn
2486 * - [in] trust_ca: the trusted list R1, ..., Rp
2487 * - [in] ca_crl, profile: as in verify_with_profile()
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002488 * - [out] ver_chain: the built and verified chain
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02002489 * Only valid when return value is 0, may contain garbage otherwise!
2490 * Restart note: need not be the same when calling again to resume.
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002491 * - [in-out] rs_ctx: context for restarting operations
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002492 *
2493 * Return value:
2494 * - non-zero if the chain could not be fully built and examined
2495 * - 0 is the chain was successfully built and examined,
2496 * even if it was found to be invalid
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002497 */
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002498static int x509_crt_verify_chain(
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002499 mbedtls_x509_crt *crt,
2500 mbedtls_x509_crt *trust_ca,
2501 mbedtls_x509_crl *ca_crl,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002502 const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002503 mbedtls_x509_crt_verify_chain *ver_chain,
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002504 mbedtls_x509_crt_restart_ctx *rs_ctx )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002505{
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02002506 /* Don't initialize any of those variables here, so that the compiler can
2507 * catch potential issues with jumping ahead when restarting */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002508 int ret;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002509 uint32_t *flags;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002510 mbedtls_x509_crt_verify_chain_item *cur;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002511 mbedtls_x509_crt *child;
Manuel Pégourié-Gonnard58dcd2d2017-07-03 21:35:04 +02002512 mbedtls_x509_crt *parent;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002513 int parent_is_trusted;
2514 int child_is_trusted;
2515 int signature_is_good;
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002516 unsigned self_cnt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002517
2518#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2519 /* resume if we had an operation in progress */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002520 if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002521 {
Manuel Pégourié-Gonnard3627a8b2017-08-23 11:20:48 +02002522 /* restore saved state */
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02002523 *ver_chain = rs_ctx->ver_chain; /* struct copy */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002524 self_cnt = rs_ctx->self_cnt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002525
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002526 /* restore derived state */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002527 cur = &ver_chain->items[ver_chain->len - 1];
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002528 child = cur->crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002529 goto find_parent;
2530 }
2531#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02002532
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002533 child = crt;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002534 self_cnt = 0;
2535 parent_is_trusted = 0;
2536 child_is_trusted = 0;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002537
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002538 while( 1 ) {
2539 /* Add certificate to the verification chain */
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002540 cur = &ver_chain->items[ver_chain->len];
2541 cur->crt = child;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002542 cur->flags = 0;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002543 ver_chain->len++;
Hanno Becker10e6b9b2019-02-22 17:56:43 +00002544
2545#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2546find_parent:
2547#endif
2548
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002549 flags = &cur->flags;
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02002550
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002551 /* Check time-validity (all certificates) */
2552 if( mbedtls_x509_time_is_past( &child->valid_to ) )
2553 *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02002554
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002555 if( mbedtls_x509_time_is_future( &child->valid_from ) )
2556 *flags |= MBEDTLS_X509_BADCERT_FUTURE;
Manuel Pégourié-Gonnardcb396102017-07-04 00:00:24 +02002557
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002558 /* Stop here for trusted roots (but not for trusted EE certs) */
2559 if( child_is_trusted )
2560 return( 0 );
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02002561
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002562 /* Check signature algorithm: MD & PK algs */
2563 if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
2564 *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02002565
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002566 if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
2567 *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002568
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002569 /* Special case: EE certs that are locally trusted */
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002570 if( ver_chain->len == 1 &&
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002571 x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
2572 {
2573 return( 0 );
2574 }
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02002575
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002576 /* Look for a parent in trusted CAs or up the chain */
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002577 ret = x509_crt_find_parent( child, trust_ca, &parent,
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002578 &parent_is_trusted, &signature_is_good,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002579 ver_chain->len - 1, self_cnt, rs_ctx );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002580
2581#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002582 if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
2583 {
2584 /* save state */
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002585 rs_ctx->in_progress = x509_crt_rs_find_parent;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002586 rs_ctx->self_cnt = self_cnt;
Manuel Pégourié-Gonnarda9688432017-08-23 11:23:59 +02002587 rs_ctx->ver_chain = *ver_chain; /* struct copy */
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002588
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002589 return( ret );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002590 }
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002591#else
2592 (void) ret;
2593#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002594
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002595 /* No parent? We're done here */
2596 if( parent == NULL )
2597 {
2598 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
2599 return( 0 );
2600 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002601
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002602 /* Count intermediate self-issued (not necessarily self-signed) certs.
2603 * These can occur with some strategies for key rollover, see [SIRO],
2604 * and should be excluded from max_pathlen checks. */
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002605 if( ver_chain->len != 1 &&
Hanno Becker7dee12a2019-02-21 13:58:38 +00002606 mbedtls_x509_name_cmp_raw( &child->issuer_raw_no_hdr,
Hanno Becker67284cc2019-02-21 14:31:51 +00002607 &child->subject_raw_no_hdr,
2608 NULL, NULL ) == 0 )
Manuel Pégourié-Gonnard24611f92017-08-09 10:28:07 +02002609 {
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002610 self_cnt++;
Manuel Pégourié-Gonnard24611f92017-08-09 10:28:07 +02002611 }
Manuel Pégourié-Gonnardfd6c85c2014-11-20 16:34:20 +01002612
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002613 /* path_cnt is 0 for the first intermediate CA,
2614 * and if parent is trusted it's not an intermediate CA */
2615 if( ! parent_is_trusted &&
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002616 ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002617 {
2618 /* return immediately to avoid overflow the chain array */
2619 return( MBEDTLS_ERR_X509_FATAL_ERROR );
2620 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002621
Manuel Pégourié-Gonnard98a67782017-08-17 10:52:20 +02002622 /* signature was checked while searching parent */
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002623 if( ! signature_is_good )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002624 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
2625
2626 /* check size of signing key */
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +02002627 if( x509_profile_check_key( profile, &parent->pk ) != 0 )
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002628 *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630#if defined(MBEDTLS_X509_CRL_PARSE_C)
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002631 /* Check trusted CA's CRL for the given crt */
Hanno Beckerc84fd1c2019-02-22 15:01:03 +00002632 *flags |= x509_crt_verifycrl( child->serial.p,
2633 child->serial.len,
2634 parent, ca_crl, profile );
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002635#else
2636 (void) ca_crl;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002637#endif
2638
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002639 /* prepare for next iteration */
2640 child = parent;
2641 parent = NULL;
2642 child_is_trusted = parent_is_trusted;
Manuel Pégourié-Gonnardbe4ff422017-07-14 12:04:14 +02002643 signature_is_good = 0;
Manuel Pégourié-Gonnardce6e52f2017-07-05 17:05:03 +02002644 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002645}
2646
2647/*
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002648 * Check for CN match
2649 */
Hanno Becker24926222019-02-21 13:10:55 +00002650static int x509_crt_check_cn( unsigned char const *buf,
2651 size_t buflen,
2652 const char *cn,
2653 size_t cn_len )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002654{
Hanno Becker24926222019-02-21 13:10:55 +00002655 /* Try exact match */
Hanno Beckerb3def1d2019-02-22 11:46:06 +00002656 if( mbedtls_x509_memcasecmp( cn, buf, buflen, cn_len ) == 0 )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002657 return( 0 );
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002658
2659 /* try wildcard match */
Hanno Becker24926222019-02-21 13:10:55 +00002660 if( x509_check_wildcard( cn, cn_len, buf, buflen ) == 0 )
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002661 {
2662 return( 0 );
2663 }
2664
2665 return( -1 );
2666}
2667
Hanno Becker8b543b32019-02-21 11:50:44 +00002668/* Returns 1 on a match and 0 on a mismatch.
2669 * This is because this function is used as a callback for
2670 * mbedtls_x509_name_cmp_raw(), which continues the name
2671 * traversal as long as the callback returns 0. */
2672static int x509_crt_check_name( void *ctx,
2673 mbedtls_x509_buf *oid,
Hanno Becker6b378122019-02-23 10:20:14 +00002674 mbedtls_x509_buf *val,
2675 int next_merged )
Hanno Becker8b543b32019-02-21 11:50:44 +00002676{
2677 char const *cn = (char const*) ctx;
2678 size_t cn_len = strlen( cn );
Hanno Becker6b378122019-02-23 10:20:14 +00002679 ((void) next_merged);
Hanno Becker8b543b32019-02-21 11:50:44 +00002680
2681 if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, oid ) == 0 &&
Hanno Becker24926222019-02-21 13:10:55 +00002682 x509_crt_check_cn( val->p, val->len, cn, cn_len ) == 0 )
Hanno Becker8b543b32019-02-21 11:50:44 +00002683 {
2684 return( 1 );
2685 }
2686
2687 return( 0 );
2688}
2689
Hanno Beckerda410822019-02-21 13:36:59 +00002690/* Returns 1 on a match and 0 on a mismatch.
2691 * This is because this function is used as a callback for
2692 * mbedtls_asn1_traverse_sequence_of(), which continues the
2693 * traversal as long as the callback returns 0. */
2694static int x509_crt_subject_alt_check_name( void *ctx,
2695 int tag,
2696 unsigned char *data,
2697 size_t data_len )
2698{
2699 char const *cn = (char const*) ctx;
2700 size_t cn_len = strlen( cn );
Hanno Becker90b94082019-02-21 21:13:21 +00002701 ((void) tag);
Hanno Beckerda410822019-02-21 13:36:59 +00002702
2703 if( x509_crt_check_cn( data, data_len, cn, cn_len ) == 0 )
2704 return( 1 );
2705
2706 return( 0 );
2707}
2708
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002709/*
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002710 * Verify the requested CN - only call this if cn is not NULL!
2711 */
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002712static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002713 const char *cn,
2714 uint32_t *flags )
2715{
Hanno Beckerda410822019-02-21 13:36:59 +00002716 int ret;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002717
2718 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
2719 {
Hanno Becker90b94082019-02-21 21:13:21 +00002720 unsigned char *p =
2721 crt->subject_alt_raw.p;
Hanno Beckerda410822019-02-21 13:36:59 +00002722 const unsigned char *end =
2723 crt->subject_alt_raw.p + crt->subject_alt_raw.len;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002724
Hanno Becker90b94082019-02-21 21:13:21 +00002725 ret = mbedtls_asn1_traverse_sequence_of( &p, end,
2726 MBEDTLS_ASN1_TAG_CLASS_MASK,
2727 MBEDTLS_ASN1_CONTEXT_SPECIFIC,
2728 MBEDTLS_ASN1_TAG_VALUE_MASK,
2729 2 /* SubjectAlt DNS */,
2730 x509_crt_subject_alt_check_name,
2731 (void*) cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002732 }
2733 else
2734 {
Hanno Becker8b543b32019-02-21 11:50:44 +00002735 ret = mbedtls_x509_name_cmp_raw( &crt->subject_raw_no_hdr,
2736 &crt->subject_raw_no_hdr,
2737 x509_crt_check_name, (void*) cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002738 }
Hanno Beckerda410822019-02-21 13:36:59 +00002739
2740 if( ret != 1 )
2741 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002742}
2743
2744/*
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02002745 * Merge the flags for all certs in the chain, after calling callback
2746 */
2747static int x509_crt_merge_flags_with_cb(
2748 uint32_t *flags,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002749 const mbedtls_x509_crt_verify_chain *ver_chain,
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02002750 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
2751 void *p_vrfy )
2752{
2753 int ret;
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002754 unsigned i;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02002755 uint32_t cur_flags;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002756 const mbedtls_x509_crt_verify_chain_item *cur;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02002757
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002758 for( i = ver_chain->len; i != 0; --i )
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02002759 {
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002760 cur = &ver_chain->items[i-1];
2761 cur_flags = cur->flags;
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02002762
2763 if( NULL != f_vrfy )
Manuel Pégourié-Gonnardbb216bd2017-08-28 13:25:55 +02002764 if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02002765 return( ret );
2766
2767 *flags |= cur_flags;
2768 }
2769
2770 return( 0 );
2771}
2772
2773/*
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02002774 * Verify the certificate validity (default profile, not restartable)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002775 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002776int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
2777 mbedtls_x509_crt *trust_ca,
2778 mbedtls_x509_crl *ca_crl,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02002779 const char *cn, uint32_t *flags,
2780 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
Paul Bakkerddf26b42013-09-18 13:46:23 +02002781 void *p_vrfy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002782{
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02002783 return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
2784 &mbedtls_x509_crt_profile_default, cn, flags,
2785 f_vrfy, p_vrfy, NULL ) );
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002786}
2787
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002788/*
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02002789 * Verify the certificate validity (user-chosen profile, not restartable)
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002790 */
2791int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
2792 mbedtls_x509_crt *trust_ca,
2793 mbedtls_x509_crl *ca_crl,
2794 const mbedtls_x509_crt_profile *profile,
2795 const char *cn, uint32_t *flags,
2796 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
2797 void *p_vrfy )
2798{
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02002799 return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
2800 profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
2801}
2802
2803/*
2804 * Verify the certificate validity, with profile, restartable version
2805 *
2806 * This function:
2807 * - checks the requested CN (if any)
2808 * - checks the type and size of the EE cert's key,
2809 * as that isn't done as part of chain building/verification currently
2810 * - builds and verifies the chain
2811 * - then calls the callback and merges the flags
2812 */
2813int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
2814 mbedtls_x509_crt *trust_ca,
2815 mbedtls_x509_crl *ca_crl,
2816 const mbedtls_x509_crt_profile *profile,
2817 const char *cn, uint32_t *flags,
2818 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
2819 void *p_vrfy,
2820 mbedtls_x509_crt_restart_ctx *rs_ctx )
2821{
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002822 int ret;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02002823 mbedtls_pk_type_t pk_type;
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002824 mbedtls_x509_crt_verify_chain ver_chain;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002825 uint32_t ee_flags;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002826
2827 *flags = 0;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002828 ee_flags = 0;
2829 x509_crt_verify_chain_reset( &ver_chain );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002830
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02002831 if( profile == NULL )
2832 {
2833 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
2834 goto exit;
2835 }
2836
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002837 /* check name if requested */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002838 if( cn != NULL )
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002839 x509_crt_verify_name( crt, cn, &ee_flags );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002840
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02002841 /* Check the type and size of the key */
2842 pk_type = mbedtls_pk_get_type( &crt->pk );
2843
2844 if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002845 ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02002846
Manuel Pégourié-Gonnard3f816912017-10-26 10:24:16 +02002847 if( x509_profile_check_key( profile, &crt->pk ) != 0 )
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002848 ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02002849
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002850 /* Check the chain */
Manuel Pégourié-Gonnard505c3952017-07-05 17:36:47 +02002851 ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002852 &ver_chain, rs_ctx );
Manuel Pégourié-Gonnarda4a5d1d2017-07-17 10:26:19 +02002853
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02002854 if( ret != 0 )
2855 goto exit;
2856
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002857 /* Merge end-entity flags */
2858 ver_chain.items[0].flags |= ee_flags;
2859
Manuel Pégourié-Gonnarda707e1d2017-07-05 17:18:42 +02002860 /* Build final flags, calling callback on the way if any */
Manuel Pégourié-Gonnardc11e4ba2017-08-14 17:17:14 +02002861 ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002862
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02002863exit:
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002864#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2865 if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2866 mbedtls_x509_crt_restart_free( rs_ctx );
2867#endif
2868
Manuel Pégourié-Gonnard9107b5f2017-07-06 12:16:25 +02002869 /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
2870 * the SSL module for authmode optional, but non-zero return from the
2871 * callback means a fatal error so it shouldn't be ignored */
Manuel Pégourié-Gonnard31458a12017-06-26 10:11:49 +02002872 if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
2873 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2874
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02002875 if( ret != 0 )
2876 {
2877 *flags = (uint32_t) -1;
2878 return( ret );
2879 }
2880
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002881 if( *flags != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002882 return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002883
2884 return( 0 );
2885}
2886
2887/*
Paul Bakker369d2eb2013-09-18 11:58:25 +02002888 * Initialize a certificate chain
2889 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002890void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
Paul Bakker369d2eb2013-09-18 11:58:25 +02002891{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002892 memset( crt, 0, sizeof(mbedtls_x509_crt) );
Paul Bakker369d2eb2013-09-18 11:58:25 +02002893}
2894
2895/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002896 * Unallocate all certificate data
2897 */
Hanno Beckercd03bb22019-02-15 17:15:53 +00002898
2899static void x509_free_sequence( mbedtls_x509_sequence *seq )
2900{
2901 while( seq != NULL )
2902 {
2903 mbedtls_x509_sequence *next = seq->next;
2904 mbedtls_platform_zeroize( seq, sizeof( *seq ) );
2905 mbedtls_free( seq );
2906 seq = next;
2907 }
2908}
2909
2910static void x509_free_name( mbedtls_x509_name *name )
2911{
2912 while( name != NULL )
2913 {
2914 mbedtls_x509_name *next = name->next;
2915 mbedtls_platform_zeroize( name, sizeof( *name ) );
2916 mbedtls_free( name );
2917 name = next;
2918 }
2919}
2920
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002921void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002922{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002923 mbedtls_x509_crt *cert_cur = crt;
2924 mbedtls_x509_crt *cert_prv;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002925
2926 if( crt == NULL )
2927 return;
2928
2929 do
2930 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002931 mbedtls_pk_free( &cert_cur->pk );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002932
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002933#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
2934 mbedtls_free( cert_cur->sig_opts );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +02002935#endif
2936
Hanno Beckercd03bb22019-02-15 17:15:53 +00002937 x509_free_name( cert_cur->issuer.next );
2938 x509_free_name( cert_cur->subject.next );
2939 x509_free_sequence( cert_cur->ext_key_usage.next );
2940 x509_free_sequence( cert_cur->subject_alt_names.next );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002941
Hanno Beckeraa8665a2019-01-31 08:57:44 +00002942 if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002943 {
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05002944 mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002945 mbedtls_free( cert_cur->raw.p );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002946 }
2947
2948 cert_cur = cert_cur->next;
2949 }
2950 while( cert_cur != NULL );
2951
2952 cert_cur = crt;
2953 do
2954 {
2955 cert_prv = cert_cur;
2956 cert_cur = cert_cur->next;
2957
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -05002958 mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002959 if( cert_prv != crt )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002960 mbedtls_free( cert_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002961 }
2962 while( cert_cur != NULL );
2963}
2964
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02002965#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
2966/*
2967 * Initialize a restart context
2968 */
2969void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
2970{
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02002971 mbedtls_pk_restart_init( &ctx->pk );
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002972
2973 ctx->parent = NULL;
2974 ctx->fallback_parent = NULL;
Manuel Pégourié-Gonnard78d7e8c2018-07-02 12:33:14 +02002975 ctx->fallback_signature_is_good = 0;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002976
2977 ctx->parent_is_trusted = -1;
2978
Manuel Pégourié-Gonnarddaf04912017-08-23 12:32:19 +02002979 ctx->in_progress = x509_crt_rs_none;
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002980 ctx->self_cnt = 0;
Manuel Pégourié-Gonnard83e923b2017-08-23 10:55:41 +02002981 x509_crt_verify_chain_reset( &ctx->ver_chain );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02002982}
2983
2984/*
2985 * Free the components of a restart context
2986 */
2987void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
2988{
2989 if( ctx == NULL )
2990 return;
2991
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +02002992 mbedtls_pk_restart_free( &ctx->pk );
Manuel Pégourié-Gonnard8b590492017-08-14 18:04:19 +02002993 mbedtls_x509_crt_restart_init( ctx );
Manuel Pégourié-Gonnardbc3f44a2017-07-11 11:02:20 +02002994}
2995#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
2996
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002997#endif /* MBEDTLS_X509_CRT_PARSE_C */