blob: d4e5112ed898058344b11a27bc47d6dc4b5fd672 [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"
Rich Evans00ab4702015-02-06 13:43:58 +000044
45#include <stdio.h>
46#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
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_free free
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_snprintf snprintf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020059#endif
60
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020061#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000062#include "mbedtls/threading.h"
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +010063#endif
64
Paul Bakkerfa6a6202013-10-28 18:48:30 +010065#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020066#include <windows.h>
67#else
68#include <time.h>
69#endif
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#if defined(MBEDTLS_FS_IO)
Rich Evans00ab4702015-02-06 13:43:58 +000072#include <stdio.h>
Paul Bakker5ff3f912014-04-04 15:08:20 +020073#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020074#include <sys/types.h>
75#include <sys/stat.h>
76#include <dirent.h>
Rich Evans00ab4702015-02-06 13:43:58 +000077#endif /* !_WIN32 || EFIX64 || EFI32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +020078#endif
79
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +020080/*
81 * Item in a verification chain: cert and flags for it
82 */
83typedef struct {
84 mbedtls_x509_crt *crt;
85 uint32_t flags;
86} x509_crt_verify_chain_item;
87
88/*
89 * Max size of verification chain: end-entity + intermediates + trusted root
90 */
91#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
92
Paul Bakker34617722014-06-13 17:20:13 +020093/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020095 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
96}
97
Paul Bakker7c6b2c32013-09-16 13:49:26 +020098/*
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +020099 * Default profile
100 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200101const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
102{
Gilles Peskine5d2511c2017-05-12 13:16:40 +0200103#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES)
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200104 /* Allow SHA-1 (weak, but still safe in controlled environments) */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200105 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
Gilles Peskine5e79cb32017-05-04 16:17:21 +0200106#endif
107 /* Only SHA-2 hashes */
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200108 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
109 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
110 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
111 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
112 0xFFFFFFF, /* Any PK alg */
113 0xFFFFFFF, /* Any curve */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200114 2048,
115};
116
117/*
118 * Next-default profile
119 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200120const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next =
121{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200122 /* Hashes from SHA-256 and above */
123 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
124 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
125 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ),
126 0xFFFFFFF, /* Any PK alg */
127#if defined(MBEDTLS_ECP_C)
128 /* Curves at or above 128-bit security level */
129 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
130 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) |
131 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) |
132 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) |
133 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) |
134 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) |
135 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ),
136#else
137 0,
138#endif
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200139 2048,
140};
141
142/*
143 * NSA Suite B Profile
144 */
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200145const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
146{
Manuel Pégourié-Gonnardf8ea8562015-06-15 15:33:19 +0200147 /* Only SHA-256 and 384 */
148 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
149 MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
150 /* Only ECDSA */
151 MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ),
152#if defined(MBEDTLS_ECP_C)
153 /* Only NIST P-256 and P-384 */
154 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
155 MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
156#else
157 0,
158#endif
159 0,
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200160};
161
162/*
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200163 * Check md_alg against profile
164 * Return 0 if md_alg acceptable for this profile, -1 otherwise
165 */
166static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile,
167 mbedtls_md_type_t md_alg )
168{
169 if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 )
170 return( 0 );
171
172 return( -1 );
173}
174
175/*
176 * Check pk_alg against profile
177 * Return 0 if pk_alg acceptable for this profile, -1 otherwise
178 */
179static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile,
180 mbedtls_pk_type_t pk_alg )
181{
182 if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 )
183 return( 0 );
184
185 return( -1 );
186}
187
188/*
189 * Check key against profile
190 * Return 0 if pk_alg acceptable for this profile, -1 otherwise
191 */
192static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
193 mbedtls_pk_type_t pk_alg,
194 const mbedtls_pk_context *pk )
195{
196#if defined(MBEDTLS_RSA_C)
197 if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS )
198 {
Manuel Pégourié-Gonnard097c7bb2015-06-18 16:43:38 +0200199 if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200200 return( 0 );
201
202 return( -1 );
203 }
204#endif
205
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +0200206#if defined(MBEDTLS_ECP_C)
207 if( pk_alg == MBEDTLS_PK_ECDSA ||
208 pk_alg == MBEDTLS_PK_ECKEY ||
209 pk_alg == MBEDTLS_PK_ECKEY_DH )
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +0200210 {
211 mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id;
212
213 if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 )
214 return( 0 );
215
216 return( -1 );
217 }
218#endif
219
220 return( -1 );
221}
222
223/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200224 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
225 */
226static int x509_get_version( unsigned char **p,
227 const unsigned char *end,
228 int *ver )
229{
230 int ret;
231 size_t len;
232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
234 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200235 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200237 {
238 *ver = 0;
239 return( 0 );
240 }
241
242 return( ret );
243 }
244
245 end = *p + len;
246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
248 return( MBEDTLS_ERR_X509_INVALID_VERSION + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200249
250 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251 return( MBEDTLS_ERR_X509_INVALID_VERSION +
252 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200253
254 return( 0 );
255}
256
257/*
258 * Validity ::= SEQUENCE {
259 * notBefore Time,
260 * notAfter Time }
261 */
262static int x509_get_dates( unsigned char **p,
263 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 mbedtls_x509_time *from,
265 mbedtls_x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200266{
267 int ret;
268 size_t len;
269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
271 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
272 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200273
274 end = *p + len;
275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200277 return( ret );
278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279 if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200280 return( ret );
281
282 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 return( MBEDTLS_ERR_X509_INVALID_DATE +
284 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200285
286 return( 0 );
287}
288
289/*
290 * X.509 v2/v3 unique identifier (not parsed)
291 */
292static int x509_get_uid( unsigned char **p,
293 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 mbedtls_x509_buf *uid, int n )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200295{
296 int ret;
297
298 if( *p == end )
299 return( 0 );
300
301 uid->tag = **p;
302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len,
304 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200305 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200307 return( 0 );
308
309 return( ret );
310 }
311
312 uid->p = *p;
313 *p += uid->len;
314
315 return( 0 );
316}
317
318static int x509_get_basic_constraints( unsigned char **p,
319 const unsigned char *end,
320 int *ca_istrue,
321 int *max_pathlen )
322{
323 int ret;
324 size_t len;
325
326 /*
327 * BasicConstraints ::= SEQUENCE {
328 * cA BOOLEAN DEFAULT FALSE,
329 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
330 */
331 *ca_istrue = 0; /* DEFAULT FALSE */
332 *max_pathlen = 0; /* endless */
333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200334 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
335 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
336 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200337
338 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200339 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200342 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
344 ret = mbedtls_asn1_get_int( p, end, ca_istrue );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200345
346 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200348
349 if( *ca_istrue != 0 )
350 *ca_istrue = 1;
351 }
352
353 if( *p == end )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200354 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 )
357 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200358
359 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
361 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200362
363 (*max_pathlen)++;
364
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200365 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200366}
367
368static int x509_get_ns_cert_type( unsigned char **p,
369 const unsigned char *end,
370 unsigned char *ns_cert_type)
371{
372 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
376 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200377
378 if( bs.len != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
380 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200381
382 /* Get actual bitstring */
383 *ns_cert_type = *bs.p;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200384 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200385}
386
387static int x509_get_key_usage( unsigned char **p,
388 const unsigned char *end,
Manuel Pégourié-Gonnard1d0ca1a2015-03-27 16:50:00 +0100389 unsigned int *key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200390{
391 int ret;
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200392 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 mbedtls_x509_bitstring bs = { 0, 0, NULL };
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200394
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
396 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200397
398 if( bs.len < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
400 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200401
402 /* Get actual bitstring */
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +0200403 *key_usage = 0;
404 for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ )
405 {
406 *key_usage |= (unsigned int) bs.p[i] << (8*i);
407 }
408
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200409 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200410}
411
412/*
413 * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
414 *
415 * KeyPurposeId ::= OBJECT IDENTIFIER
416 */
417static int x509_get_ext_key_usage( unsigned char **p,
418 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 mbedtls_x509_sequence *ext_key_usage)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200420{
421 int ret;
422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
424 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200425
426 /* Sequence length must be >= 1 */
427 if( ext_key_usage->buf.p == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
429 MBEDTLS_ERR_ASN1_INVALID_LENGTH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200430
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200431 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200432}
433
434/*
435 * SubjectAltName ::= GeneralNames
436 *
437 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
438 *
439 * GeneralName ::= CHOICE {
440 * otherName [0] OtherName,
441 * rfc822Name [1] IA5String,
442 * dNSName [2] IA5String,
443 * x400Address [3] ORAddress,
444 * directoryName [4] Name,
445 * ediPartyName [5] EDIPartyName,
446 * uniformResourceIdentifier [6] IA5String,
447 * iPAddress [7] OCTET STRING,
448 * registeredID [8] OBJECT IDENTIFIER }
449 *
450 * OtherName ::= SEQUENCE {
451 * type-id OBJECT IDENTIFIER,
452 * value [0] EXPLICIT ANY DEFINED BY type-id }
453 *
454 * EDIPartyName ::= SEQUENCE {
455 * nameAssigner [0] DirectoryString OPTIONAL,
456 * partyName [1] DirectoryString }
457 *
Manuel Pégourié-Gonnardb4fe3cb2015-01-22 16:11:05 +0000458 * NOTE: we only parse and use dNSName at this point.
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200459 */
460static int x509_get_subject_alt_name( unsigned char **p,
461 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_x509_sequence *subject_alt_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200463{
464 int ret;
465 size_t len, tag_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 mbedtls_asn1_buf *buf;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200467 unsigned char tag;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 mbedtls_asn1_sequence *cur = subject_alt_name;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200469
470 /* Get main sequence tag */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
472 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
473 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200474
475 if( *p + len != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
477 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200478
479 while( *p < end )
480 {
481 if( ( end - *p ) < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
483 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200484
485 tag = **p;
486 (*p)++;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 )
488 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 if( ( tag & MBEDTLS_ASN1_CONTEXT_SPECIFIC ) != MBEDTLS_ASN1_CONTEXT_SPECIFIC )
491 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
492 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200493
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +0200494 /* Skip everything but DNS name */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200496 {
497 *p += tag_len;
498 continue;
499 }
500
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200501 /* Allocate and assign next pointer */
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +0200502 if( cur->buf.p != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200503 {
Manuel Pégourié-Gonnardb1340602014-11-11 23:11:16 +0100504 if( cur->next != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
Manuel Pégourié-Gonnardb1340602014-11-11 23:11:16 +0100506
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200507 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200508
509 if( cur->next == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200511 MBEDTLS_ERR_ASN1_ALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200512
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200513 cur = cur->next;
514 }
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +0200515
516 buf = &(cur->buf);
517 buf->tag = tag;
518 buf->p = *p;
519 buf->len = tag_len;
520 *p += buf->len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200521 }
522
523 /* Set final sequence entry's next pointer to NULL */
524 cur->next = NULL;
525
526 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
528 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200529
530 return( 0 );
531}
532
533/*
534 * X.509 v3 extensions
535 *
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200536 */
537static int x509_get_crt_ext( unsigned char **p,
538 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200540{
541 int ret;
542 size_t len;
543 unsigned char *end_ext_data, *end_ext_octet;
544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545 if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200546 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200548 return( 0 );
549
550 return( ret );
551 }
552
553 while( *p < end )
554 {
555 /*
556 * Extension ::= SEQUENCE {
557 * extnID OBJECT IDENTIFIER,
558 * critical BOOLEAN DEFAULT FALSE,
559 * extnValue OCTET STRING }
560 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 mbedtls_x509_buf extn_oid = {0, 0, NULL};
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200562 int is_critical = 0; /* DEFAULT FALSE */
563 int ext_type = 0;
564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
566 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
567 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200568
569 end_ext_data = *p + len;
570
571 /* Get extension ID */
572 extn_oid.tag = **p;
573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
575 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200576
577 extn_oid.p = *p;
578 *p += extn_oid.len;
579
580 if( ( end - *p ) < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
582 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200583
584 /* Get optional critical */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 &&
586 ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) )
587 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200588
589 /* Data should be octet string type */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len,
591 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
592 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200593
594 end_ext_octet = *p + len;
595
596 if( end_ext_octet != end_ext_data )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
598 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200599
600 /*
601 * Detect supported extensions
602 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200604
605 if( ret != 0 )
606 {
607 /* No parser found, skip extension */
608 *p = end_ext_octet;
609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200611 if( is_critical )
612 {
613 /* Data is marked as critical: fail */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
615 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200616 }
617#endif
618 continue;
619 }
620
Manuel Pégourié-Gonnard8a5e3d42014-11-12 17:47:28 +0100621 /* Forbid repeated extensions */
622 if( ( crt->ext_types & ext_type ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
Manuel Pégourié-Gonnard8a5e3d42014-11-12 17:47:28 +0100624
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200625 crt->ext_types |= ext_type;
626
627 switch( ext_type )
628 {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100629 case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200630 /* Parse basic constraints */
631 if( ( ret = x509_get_basic_constraints( p, end_ext_octet,
632 &crt->ca_istrue, &crt->max_pathlen ) ) != 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200633 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200634 break;
635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 case MBEDTLS_X509_EXT_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200637 /* Parse key usage */
638 if( ( ret = x509_get_key_usage( p, end_ext_octet,
639 &crt->key_usage ) ) != 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200640 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200641 break;
642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643 case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200644 /* Parse extended key usage */
645 if( ( ret = x509_get_ext_key_usage( p, end_ext_octet,
646 &crt->ext_key_usage ) ) != 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200647 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200648 break;
649
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +0100650 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200651 /* Parse subject alt name */
652 if( ( ret = x509_get_subject_alt_name( p, end_ext_octet,
653 &crt->subject_alt_names ) ) != 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200654 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200655 break;
656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200658 /* Parse netscape certificate type */
659 if( ( ret = x509_get_ns_cert_type( p, end_ext_octet,
660 &crt->ns_cert_type ) ) != 0 )
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200661 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200662 break;
663
664 default:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200666 }
667 }
668
669 if( *p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
671 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200672
673 return( 0 );
674}
675
676/*
677 * Parse and fill a single X.509 certificate in DER format
678 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf,
Paul Bakkerddf26b42013-09-18 13:46:23 +0200680 size_t buflen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200681{
682 int ret;
683 size_t len;
684 unsigned char *p, *end, *crt_end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) );
688 memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) );
689 memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200690
691 /*
692 * Check for valid input
693 */
694 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200696
Janos Follathcc0e49d2016-02-17 14:34:12 +0000697 // Use the original buffer until we figure out actual length
698 p = (unsigned char*) buf;
699 len = buflen;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200700 end = p + len;
701
702 /*
703 * Certificate ::= SEQUENCE {
704 * tbsCertificate TBSCertificate,
705 * signatureAlgorithm AlgorithmIdentifier,
706 * signatureValue BIT STRING }
707 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
709 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200710 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 mbedtls_x509_crt_free( crt );
712 return( MBEDTLS_ERR_X509_INVALID_FORMAT );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200713 }
714
715 if( len > (size_t) ( end - p ) )
716 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717 mbedtls_x509_crt_free( crt );
718 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
719 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200720 }
721 crt_end = p + len;
722
Janos Follathcc0e49d2016-02-17 14:34:12 +0000723 // Create and populate a new buffer for the raw field
724 crt->raw.len = crt_end - buf;
725 crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
726 if( p == NULL )
727 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
728
729 memcpy( p, buf, crt->raw.len );
730
731 // Direct pointers to the new buffer
732 p += crt->raw.len - len;
733 end = crt_end = p + len;
734
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200735 /*
736 * TBSCertificate ::= SEQUENCE {
737 */
738 crt->tbs.p = p;
739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
741 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200742 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_x509_crt_free( crt );
744 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200745 }
746
747 end = p + len;
748 crt->tbs.len = end - crt->tbs.p;
749
750 /*
751 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
752 *
753 * CertificateSerialNumber ::= INTEGER
754 *
755 * signature AlgorithmIdentifier
756 */
757 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200758 ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
759 ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid,
Manuel Pégourié-Gonnarddddbb1d2014-06-05 17:02:24 +0200760 &sig_params1 ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200761 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200762 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200763 return( ret );
764 }
765
Andres AG7ca4a032017-03-09 16:16:11 +0000766 if( crt->version < 0 || crt->version > 2 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200767 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 mbedtls_x509_crt_free( crt );
769 return( MBEDTLS_ERR_X509_UNKNOWN_VERSION );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200770 }
771
Andres AG7ca4a032017-03-09 16:16:11 +0000772 crt->version++;
773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200774 if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1,
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200775 &crt->sig_md, &crt->sig_pk,
776 &crt->sig_opts ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200777 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200779 return( ret );
780 }
781
782 /*
783 * issuer Name
784 */
785 crt->issuer_raw.p = p;
786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
788 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200789 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790 mbedtls_x509_crt_free( crt );
791 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200792 }
793
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200794 if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200795 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200797 return( ret );
798 }
799
800 crt->issuer_raw.len = p - crt->issuer_raw.p;
801
802 /*
803 * Validity ::= SEQUENCE {
804 * notBefore Time,
805 * notAfter Time }
806 *
807 */
808 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
809 &crt->valid_to ) ) != 0 )
810 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200812 return( ret );
813 }
814
815 /*
816 * subject Name
817 */
818 crt->subject_raw.p = p;
819
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
821 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200822 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 mbedtls_x509_crt_free( crt );
824 return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200825 }
826
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200827 if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200828 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200830 return( ret );
831 }
832
833 crt->subject_raw.len = p - crt->subject_raw.p;
834
835 /*
836 * SubjectPublicKeyInfo
837 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200839 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200841 return( ret );
842 }
843
844 /*
845 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
846 * -- If present, version shall be v2 or v3
847 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
848 * -- If present, version shall be v2 or v3
849 * extensions [3] EXPLICIT Extensions OPTIONAL
850 * -- If present, version shall be v3
851 */
852 if( crt->version == 2 || crt->version == 3 )
853 {
854 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
855 if( ret != 0 )
856 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200858 return( ret );
859 }
860 }
861
862 if( crt->version == 2 || crt->version == 3 )
863 {
864 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
865 if( ret != 0 )
866 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200868 return( ret );
869 }
870 }
871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200873 if( crt->version == 3 )
Paul Bakkerc27c4e22013-09-23 15:01:36 +0200874#endif
Manuel Pégourié-Gonnarda252af72015-03-27 16:15:55 +0100875 {
Paul Bakker66d5d072014-06-17 16:39:18 +0200876 ret = x509_get_crt_ext( &p, end, crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200877 if( ret != 0 )
878 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200880 return( ret );
881 }
882 }
883
884 if( p != end )
885 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 mbedtls_x509_crt_free( crt );
887 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
888 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200889 }
890
891 end = crt_end;
892
893 /*
894 * }
895 * -- end of TBSCertificate
896 *
897 * signatureAlgorithm AlgorithmIdentifier,
898 * signatureValue BIT STRING
899 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200900 if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200901 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200903 return( ret );
904 }
905
Manuel Pégourié-Gonnard1022fed2015-03-27 16:30:47 +0100906 if( crt->sig_oid.len != sig_oid2.len ||
907 memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 ||
Manuel Pégourié-Gonnarddddbb1d2014-06-05 17:02:24 +0200908 sig_params1.len != sig_params2.len ||
Manuel Pégourié-Gonnard159c5242015-04-30 11:15:22 +0200909 ( sig_params1.len != 0 &&
910 memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200911 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200912 mbedtls_x509_crt_free( crt );
913 return( MBEDTLS_ERR_X509_SIG_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200914 }
915
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916 if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200917 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200918 mbedtls_x509_crt_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200919 return( ret );
920 }
921
922 if( p != end )
923 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 mbedtls_x509_crt_free( crt );
925 return( MBEDTLS_ERR_X509_INVALID_FORMAT +
926 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200927 }
928
929 return( 0 );
930}
931
932/*
933 * Parse one X.509 certificate in DER format from a buffer and add them to a
934 * chained list
935 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf,
Paul Bakkerddf26b42013-09-18 13:46:23 +0200937 size_t buflen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200938{
939 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 mbedtls_x509_crt *crt = chain, *prev = NULL;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200941
942 /*
943 * Check for valid input
944 */
945 if( crt == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200947
948 while( crt->version != 0 && crt->next != NULL )
949 {
950 prev = crt;
951 crt = crt->next;
952 }
953
954 /*
955 * Add new certificate on the end of the chain if needed.
956 */
Paul Bakker66d5d072014-06-17 16:39:18 +0200957 if( crt->version != 0 && crt->next == NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200958 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200959 crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200960
961 if( crt->next == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200962 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200963
964 prev = crt;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965 mbedtls_x509_crt_init( crt->next );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200966 crt = crt->next;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200967 }
968
Paul Bakkerddf26b42013-09-18 13:46:23 +0200969 if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200970 {
971 if( prev )
972 prev->next = NULL;
973
974 if( crt != chain )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975 mbedtls_free( crt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200976
977 return( ret );
978 }
979
980 return( 0 );
981}
982
983/*
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200984 * Parse one or more PEM certificates from a buffer and add them to the chained
985 * list
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200986 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200988{
Janos Follath98e28a72016-05-31 14:03:54 +0100989#if defined(MBEDTLS_PEM_PARSE_C)
Andres AGc0db5112016-12-07 15:05:53 +0000990 int success = 0, first_error = 0, total_failed = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 int buf_format = MBEDTLS_X509_FORMAT_DER;
Janos Follath98e28a72016-05-31 14:03:54 +0100992#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200993
994 /*
995 * Check for valid input
996 */
997 if( chain == NULL || buf == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200999
1000 /*
1001 * Determine buffer content. Buffer contains either one DER certificate or
1002 * one or more PEM certificates.
1003 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001004#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +02001005 if( buflen != 0 && buf[buflen - 1] == '\0' &&
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001006 strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL )
1007 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001008 buf_format = MBEDTLS_X509_FORMAT_PEM;
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001009 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001010
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 if( buf_format == MBEDTLS_X509_FORMAT_DER )
1012 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
Janos Follath98e28a72016-05-31 14:03:54 +01001013#else
1014 return mbedtls_x509_crt_parse_der( chain, buf, buflen );
1015#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001016
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017#if defined(MBEDTLS_PEM_PARSE_C)
1018 if( buf_format == MBEDTLS_X509_FORMAT_PEM )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001019 {
1020 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 mbedtls_pem_context pem;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001022
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001023 /* 1 rather than 0 since the terminating NULL byte is counted in */
1024 while( buflen > 1 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001025 {
1026 size_t use_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001027 mbedtls_pem_init( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001028
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001029 /* If we get there, we know the string is null-terminated */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030 ret = mbedtls_pem_read_buffer( &pem,
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001031 "-----BEGIN CERTIFICATE-----",
1032 "-----END CERTIFICATE-----",
1033 buf, NULL, 0, &use_len );
1034
1035 if( ret == 0 )
1036 {
1037 /*
1038 * Was PEM encoded
1039 */
1040 buflen -= use_len;
1041 buf += use_len;
1042 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043 else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001044 {
1045 return( ret );
1046 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001047 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001048 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001050
1051 /*
1052 * PEM header and footer were found
1053 */
1054 buflen -= use_len;
1055 buf += use_len;
1056
1057 if( first_error == 0 )
1058 first_error = ret;
1059
Paul Bakker5a5fa922014-09-26 14:53:04 +02001060 total_failed++;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001061 continue;
1062 }
1063 else
1064 break;
1065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 mbedtls_pem_free( &pem );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001069
1070 if( ret != 0 )
1071 {
1072 /*
1073 * Quit parsing on a memory error
1074 */
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001075 if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001076 return( ret );
1077
1078 if( first_error == 0 )
1079 first_error = ret;
1080
1081 total_failed++;
1082 continue;
1083 }
1084
1085 success = 1;
1086 }
1087 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001088
1089 if( success )
1090 return( total_failed );
1091 else if( first_error )
1092 return( first_error );
1093 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT );
Janos Follath98e28a72016-05-31 14:03:54 +01001095#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001096}
1097
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098#if defined(MBEDTLS_FS_IO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001099/*
1100 * Load one or more certificates and add them to the chained list
1101 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001103{
1104 int ret;
1105 size_t n;
1106 unsigned char *buf;
1107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001108 if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001109 return( ret );
1110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001111 ret = mbedtls_x509_crt_parse( chain, buf, n );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001112
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001113 mbedtls_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114 mbedtls_free( buf );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001115
1116 return( ret );
1117}
1118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001120{
1121 int ret = 0;
Paul Bakkerfa6a6202013-10-28 18:48:30 +01001122#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001123 int w_ret;
1124 WCHAR szDir[MAX_PATH];
1125 char filename[MAX_PATH];
Paul Bakker9af723c2014-05-01 13:03:14 +02001126 char *p;
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001127 size_t len = strlen( path );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001128
Paul Bakker9af723c2014-05-01 13:03:14 +02001129 WIN32_FIND_DATAW file_data;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001130 HANDLE hFind;
1131
1132 if( len > MAX_PATH - 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001134
Paul Bakker9af723c2014-05-01 13:03:14 +02001135 memset( szDir, 0, sizeof(szDir) );
1136 memset( filename, 0, MAX_PATH );
1137 memcpy( filename, path, len );
1138 filename[len++] = '\\';
1139 p = filename + len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001140 filename[len++] = '*';
1141
Simon B3c6b18d2016-11-03 01:11:37 +00001142 w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +02001143 MAX_PATH - 3 );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001144 if( w_ret == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001146
1147 hFind = FindFirstFileW( szDir, &file_data );
Paul Bakker66d5d072014-06-17 16:39:18 +02001148 if( hFind == INVALID_HANDLE_VALUE )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001150
1151 len = MAX_PATH - len;
1152 do
1153 {
Paul Bakker9af723c2014-05-01 13:03:14 +02001154 memset( p, 0, len );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001155
1156 if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
1157 continue;
1158
Paul Bakker9af723c2014-05-01 13:03:14 +02001159 w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName,
Paul Bakker66d5d072014-06-17 16:39:18 +02001160 lstrlenW( file_data.cFileName ),
Manuel Pégourié-Gonnard261faed2015-10-21 10:16:29 +02001161 p, (int) len - 1,
Paul Bakker9af723c2014-05-01 13:03:14 +02001162 NULL, NULL );
Manuel Pégourié-Gonnardacdb9b92015-01-23 17:50:34 +00001163 if( w_ret == 0 )
Ron Eldor36d90422017-01-09 15:09:16 +02001164 {
1165 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
1166 goto cleanup;
1167 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 w_ret = mbedtls_x509_crt_parse_file( chain, filename );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001170 if( w_ret < 0 )
1171 ret++;
1172 else
1173 ret += w_ret;
1174 }
1175 while( FindNextFileW( hFind, &file_data ) != 0 );
1176
Paul Bakker66d5d072014-06-17 16:39:18 +02001177 if( GetLastError() != ERROR_NO_MORE_FILES )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001178 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001179
Ron Eldor36d90422017-01-09 15:09:16 +02001180cleanup:
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001181 FindClose( hFind );
Paul Bakkerbe089b02013-10-14 15:51:50 +02001182#else /* _WIN32 */
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001183 int t_ret;
Andres AGf9113192016-09-02 14:06:04 +01001184 int snp_ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001185 struct stat sb;
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001186 struct dirent *entry;
Andres AGf9113192016-09-02 14:06:04 +01001187 char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN];
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001188 DIR *dir = opendir( path );
1189
Paul Bakker66d5d072014-06-17 16:39:18 +02001190 if( dir == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191 return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001192
Ron Eldor63140682017-01-09 19:27:59 +02001193#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02001194 if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02001195 {
1196 closedir( dir );
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001197 return( ret );
Manuel Pégourié-Gonnardf9b85d92015-06-22 18:39:57 +02001198 }
Ron Eldor63140682017-01-09 19:27:59 +02001199#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001200
Manuel Pégourié-Gonnard964bf9b2013-11-26 16:47:11 +01001201 while( ( entry = readdir( dir ) ) != NULL )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001202 {
Andres AGf9113192016-09-02 14:06:04 +01001203 snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name,
1204 "%s/%s", path, entry->d_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001205
Andres AGf9113192016-09-02 14:06:04 +01001206 if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001207 {
Andres AGf9113192016-09-02 14:06:04 +01001208 ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1209 goto cleanup;
1210 }
1211 else if( stat( entry_name, &sb ) == -1 )
1212 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001213 ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001214 goto cleanup;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001215 }
1216
1217 if( !S_ISREG( sb.st_mode ) )
1218 continue;
1219
1220 // Ignore parse errors
1221 //
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222 t_ret = mbedtls_x509_crt_parse_file( chain, entry_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001223 if( t_ret < 0 )
1224 ret++;
1225 else
1226 ret += t_ret;
1227 }
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001228
1229cleanup:
Andres AGf9113192016-09-02 14:06:04 +01001230 closedir( dir );
1231
Ron Eldor63140682017-01-09 19:27:59 +02001232#if defined(MBEDTLS_THREADING_C)
Manuel Pégourié-Gonnard944cfe82015-05-27 20:07:18 +02001233 if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234 ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
Ron Eldor63140682017-01-09 19:27:59 +02001235#endif /* MBEDTLS_THREADING_C */
Manuel Pégourié-Gonnard5ad68e42013-11-28 17:11:54 +01001236
Paul Bakkerbe089b02013-10-14 15:51:50 +02001237#endif /* _WIN32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001238
1239 return( ret );
1240}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241#endif /* MBEDTLS_FS_IO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001242
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001243static int x509_info_subject_alt_name( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001244 const mbedtls_x509_sequence *subject_alt_name )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001245{
1246 size_t i;
1247 size_t n = *size;
1248 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001249 const mbedtls_x509_sequence *cur = subject_alt_name;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001250 const char *sep = "";
1251 size_t sep_len = 0;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001252
1253 while( cur != NULL )
1254 {
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001255 if( cur->buf.len + sep_len >= n )
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001256 {
1257 *p = '\0';
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001258 return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001259 }
1260
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001261 n -= cur->buf.len + sep_len;
1262 for( i = 0; i < sep_len; i++ )
1263 *p++ = sep[i];
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001264 for( i = 0; i < cur->buf.len; i++ )
1265 *p++ = cur->buf.p[i];
1266
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001267 sep = ", ";
1268 sep_len = 2;
1269
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001270 cur = cur->next;
1271 }
1272
1273 *p = '\0';
1274
1275 *size = n;
1276 *buf = p;
1277
1278 return( 0 );
1279}
1280
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001281#define PRINT_ITEM(i) \
1282 { \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283 ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001284 MBEDTLS_X509_SAFE_SNPRINTF; \
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001285 sep = ", "; \
1286 }
1287
1288#define CERT_TYPE(type,name) \
1289 if( ns_cert_type & type ) \
1290 PRINT_ITEM( name );
1291
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001292static int x509_info_cert_type( char **buf, size_t *size,
1293 unsigned char ns_cert_type )
1294{
1295 int ret;
1296 size_t n = *size;
1297 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001298 const char *sep = "";
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001301 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" );
1303 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" );
1304 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001305 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" );
1306 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" );
1307 CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" );
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001308
1309 *size = n;
1310 *buf = p;
1311
1312 return( 0 );
1313}
1314
Manuel Pégourié-Gonnard0db29b02014-04-01 18:12:24 +02001315#define KEY_USAGE(code,name) \
1316 if( key_usage & code ) \
1317 PRINT_ITEM( name );
1318
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001319static int x509_info_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02001320 unsigned int key_usage )
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001321{
1322 int ret;
1323 size_t n = *size;
1324 char *p = *buf;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001325 const char *sep = "";
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" );
1328 KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" );
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001329 KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" );
1330 KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" );
1331 KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" );
1333 KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" );
Manuel Pégourié-Gonnard9a702252015-06-23 10:14:36 +02001334 KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" );
1335 KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" );
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001336
1337 *size = n;
1338 *buf = p;
1339
1340 return( 0 );
1341}
1342
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001343static int x509_info_ext_key_usage( char **buf, size_t *size,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 const mbedtls_x509_sequence *extended_key_usage )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001345{
1346 int ret;
1347 const char *desc;
1348 size_t n = *size;
1349 char *p = *buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001350 const mbedtls_x509_sequence *cur = extended_key_usage;
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001351 const char *sep = "";
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001352
1353 while( cur != NULL )
1354 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355 if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 )
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001356 desc = "???";
1357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001358 ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001359 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001360
Manuel Pégourié-Gonnard7b30cfc2014-04-01 18:00:07 +02001361 sep = ", ";
1362
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001363 cur = cur->next;
1364 }
1365
1366 *size = n;
1367 *buf = p;
1368
1369 return( 0 );
1370}
1371
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001372/*
1373 * Return an informational string about the certificate.
1374 */
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001375#define BEFORE_COLON 18
1376#define BC "18"
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001377int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
1378 const mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001379{
1380 int ret;
1381 size_t n;
1382 char *p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001383 char key_size_str[BEFORE_COLON];
1384
1385 p = buf;
1386 n = size;
1387
Janos Follath98e28a72016-05-31 14:03:54 +01001388 if( NULL == crt )
1389 {
1390 ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" );
1391 MBEDTLS_X509_SAFE_SNPRINTF;
1392
1393 return( (int) ( size - n ) );
1394 }
1395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 ret = mbedtls_snprintf( p, n, "%scert. version : %d\n",
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001397 prefix, crt->version );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001398 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 ret = mbedtls_snprintf( p, n, "%sserial number : ",
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001400 prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001401 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403 ret = mbedtls_x509_serial_gets( p, n, &crt->serial );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001404 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001407 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 ret = mbedtls_x509_dn_gets( p, n, &crt->issuer );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001409 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001411 ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001412 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 ret = mbedtls_x509_dn_gets( p, n, &crt->subject );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001414 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 ret = mbedtls_snprintf( p, n, "\n%sissued on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001417 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1418 crt->valid_from.year, crt->valid_from.mon,
1419 crt->valid_from.day, crt->valid_from.hour,
1420 crt->valid_from.min, crt->valid_from.sec );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001421 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001423 ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001424 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1425 crt->valid_to.year, crt->valid_to.mon,
1426 crt->valid_to.day, crt->valid_to.hour,
1427 crt->valid_to.min, crt->valid_to.sec );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001428 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430 ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001431 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001433 ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk,
Manuel Pégourié-Gonnardbf696d02014-06-05 17:07:30 +02001434 crt->sig_md, crt->sig_opts );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001435 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001436
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001437 /* Key size */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438 if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON,
1439 mbedtls_pk_get_name( &crt->pk ) ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001440 {
1441 return( ret );
1442 }
1443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str,
Manuel Pégourié-Gonnard097c7bb2015-06-18 16:43:38 +02001445 (int) mbedtls_pk_get_bitlen( &crt->pk ) );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001446 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001447
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001448 /*
1449 * Optional extensions
1450 */
1451
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001452 if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001453 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454 ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix,
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001455 crt->ca_istrue ? "true" : "false" );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001456 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001457
1458 if( crt->max_pathlen > 0 )
1459 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001460 ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001461 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001462 }
1463 }
1464
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001465 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001466 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001467 ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001468 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardbce2b302014-04-01 13:43:28 +02001469
1470 if( ( ret = x509_info_subject_alt_name( &p, &n,
1471 &crt->subject_alt_names ) ) != 0 )
1472 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001473 }
1474
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001477 ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001478 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard919f8f52014-04-01 13:01:11 +02001479
1480 if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 )
1481 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001482 }
1483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001485 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001487 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard65c2ddc2014-04-01 14:12:11 +02001488
1489 if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 )
1490 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001491 }
1492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE )
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001494 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001495 ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001496 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardf6f4ab42014-04-01 17:32:44 +02001497
1498 if( ( ret = x509_info_ext_key_usage( &p, &n,
1499 &crt->ext_key_usage ) ) != 0 )
1500 return( ret );
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001501 }
1502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 ret = mbedtls_snprintf( p, n, "\n" );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001504 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb28487d2014-04-01 12:19:09 +02001505
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001506 return( (int) ( size - n ) );
1507}
1508
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001509struct x509_crt_verify_string {
1510 int code;
1511 const char *string;
1512};
1513
1514static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001515 { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001516 { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" },
1517 { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" },
1518 { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" },
1519 { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" },
1520 { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001521 { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" },
1522 { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" },
1523 { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" },
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001524 { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" },
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001525 { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" },
1526 { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" },
1527 { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" },
1528 { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" },
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02001529 { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." },
1530 { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
1531 { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." },
1532 { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." },
1533 { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." },
1534 { 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 +01001535 { 0, NULL }
1536};
1537
1538int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02001539 uint32_t flags )
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001540{
1541 int ret;
1542 const struct x509_crt_verify_string *cur;
1543 char *p = buf;
1544 size_t n = size;
1545
1546 for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ )
1547 {
1548 if( ( flags & cur->code ) == 0 )
1549 continue;
1550
1551 ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001552 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001553 flags ^= cur->code;
1554 }
1555
1556 if( flags != 0 )
1557 {
1558 ret = mbedtls_snprintf( p, n, "%sUnknown reason "
1559 "(this should not happen)\n", prefix );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +02001560 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardb5f48ad2015-04-20 10:38:13 +01001561 }
1562
1563 return( (int) ( size - n ) );
1564}
1565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Manuel Pégourié-Gonnard655a9642015-06-23 10:48:44 +02001567int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
1568 unsigned int usage )
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02001569{
Manuel Pégourié-Gonnard655a9642015-06-23 10:48:44 +02001570 unsigned int usage_must, usage_may;
1571 unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY
1572 | MBEDTLS_X509_KU_DECIPHER_ONLY;
1573
1574 if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 )
1575 return( 0 );
1576
1577 usage_must = usage & ~may_mask;
1578
1579 if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must )
1580 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
1581
1582 usage_may = usage & may_mask;
1583
1584 if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard603116c2014-04-09 09:50:03 +02001586
1587 return( 0 );
1588}
1589#endif
1590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001591#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE)
1592int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt,
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001593 const char *usage_oid,
1594 size_t usage_len )
1595{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001596 const mbedtls_x509_sequence *cur;
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001597
1598 /* Extension is not mandatory, absent means no restriction */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 )
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001600 return( 0 );
1601
1602 /*
1603 * Look for the requested usage (or wildcard ANY) in our list
1604 */
1605 for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next )
1606 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 const mbedtls_x509_buf *cur_oid = &cur->buf;
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001608
1609 if( cur_oid->len == usage_len &&
1610 memcmp( cur_oid->p, usage_oid, usage_len ) == 0 )
1611 {
1612 return( 0 );
1613 }
1614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 )
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001616 return( 0 );
1617 }
1618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001620}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001621#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */
Manuel Pégourié-Gonnard7afb8a02014-04-10 17:53:56 +02001622
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623#if defined(MBEDTLS_X509_CRL_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001624/*
1625 * Return 1 if the certificate is revoked, or 0 otherwise.
1626 */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01001627int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001628{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001629 const mbedtls_x509_crl_entry *cur = &crl->entry;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001630
1631 while( cur != NULL && cur->serial.len != 0 )
1632 {
1633 if( crt->serial.len == cur->serial.len &&
1634 memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 )
1635 {
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01001636 if( mbedtls_x509_time_is_past( &cur->revocation_date ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001637 return( 1 );
1638 }
1639
1640 cur = cur->next;
1641 }
1642
1643 return( 0 );
1644}
1645
1646/*
Manuel Pégourié-Gonnardeeef9472016-02-22 11:36:55 +01001647 * Check that the given certificate is not revoked according to the CRL.
1648 * Skip validation is no CRL for the given CA is present.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001649 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02001651 mbedtls_x509_crl *crl_list,
1652 const mbedtls_x509_crt_profile *profile )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001653{
1654 int flags = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
1656 const mbedtls_md_info_t *md_info;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001657
1658 if( ca == NULL )
1659 return( flags );
1660
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001661 while( crl_list != NULL )
1662 {
1663 if( crl_list->version == 0 ||
1664 crl_list->issuer_raw.len != ca->subject_raw.len ||
1665 memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
1666 crl_list->issuer_raw.len ) != 0 )
1667 {
1668 crl_list = crl_list->next;
1669 continue;
1670 }
1671
1672 /*
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02001673 * Check if the CA is configured to sign CRLs
1674 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001675#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
1676 if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02001677 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Manuel Pégourié-Gonnard99d4f192014-04-08 15:10:07 +02001679 break;
1680 }
1681#endif
1682
1683 /*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001684 * Check if CRL is correctly signed by the trusted CA
1685 */
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02001686 if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 )
1687 flags |= MBEDTLS_X509_BADCRL_BAD_MD;
1688
1689 if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 )
1690 flags |= MBEDTLS_X509_BADCRL_BAD_PK;
1691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 md_info = mbedtls_md_info_from_type( crl_list->sig_md );
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02001693 if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001694 {
Manuel Pégourié-Gonnard329e78c2017-06-26 12:22:17 +02001695 /* Note: this can't happen except after an internal error */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001697 break;
1698 }
1699
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02001700 if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 )
1701 flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02001702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703 if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk,
1704 crl_list->sig_md, hash, mbedtls_md_get_size( md_info ),
Manuel Pégourié-Gonnard53882022014-06-05 17:53:52 +02001705 crl_list->sig.p, crl_list->sig.len ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001706 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001707 flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001708 break;
1709 }
1710
1711 /*
1712 * Check for validity of CRL (Do not drop out)
1713 */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01001714 if( mbedtls_x509_time_is_past( &crl_list->next_update ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001715 flags |= MBEDTLS_X509_BADCRL_EXPIRED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001716
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01001717 if( mbedtls_x509_time_is_future( &crl_list->this_update ) )
Manuel Pégourié-Gonnarde6028c92015-04-20 12:19:02 +01001718 flags |= MBEDTLS_X509_BADCRL_FUTURE;
Manuel Pégourié-Gonnard95337652014-03-10 13:15:18 +01001719
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001720 /*
1721 * Check if certificate is revoked
1722 */
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01001723 if( mbedtls_x509_crt_is_revoked( crt, crl_list ) )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001724 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 flags |= MBEDTLS_X509_BADCERT_REVOKED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001726 break;
1727 }
1728
1729 crl_list = crl_list->next;
1730 }
Manuel Pégourié-Gonnardcbb1f6e2015-06-15 16:17:55 +02001731
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001732 return( flags );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001733}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734#endif /* MBEDTLS_X509_CRL_PARSE_C */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001735
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02001736/*
1737 * Like memcmp, but case-insensitive and always returns -1 if different
1738 */
1739static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001740{
1741 size_t i;
1742 unsigned char diff;
1743 const unsigned char *n1 = s1, *n2 = s2;
1744
1745 for( i = 0; i < len; i++ )
1746 {
1747 diff = n1[i] ^ n2[i];
1748
Paul Bakkerf2b4d862013-11-20 17:23:53 +01001749 if( diff == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001750 continue;
1751
Paul Bakkerf2b4d862013-11-20 17:23:53 +01001752 if( diff == 32 &&
1753 ( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
1754 ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
1755 {
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001756 continue;
Paul Bakkerf2b4d862013-11-20 17:23:53 +01001757 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001758
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02001759 return( -1 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001760 }
1761
1762 return( 0 );
1763}
1764
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02001765/*
Manuel Pégourié-Gonnardb80d16d2015-06-23 09:24:29 +02001766 * Return 0 if name matches wildcard, -1 otherwise
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02001767 */
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02001768static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001769{
1770 size_t i;
Paul Bakker14b16c62014-05-28 11:33:54 +02001771 size_t cn_idx = 0, cn_len = strlen( cn );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001772
1773 if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
1774 return( 0 );
1775
Paul Bakker14b16c62014-05-28 11:33:54 +02001776 for( i = 0; i < cn_len; ++i )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001777 {
1778 if( cn[i] == '.' )
1779 {
1780 cn_idx = i;
1781 break;
1782 }
1783 }
1784
1785 if( cn_idx == 0 )
Manuel Pégourié-Gonnardb80d16d2015-06-23 09:24:29 +02001786 return( -1 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001787
Paul Bakker14b16c62014-05-28 11:33:54 +02001788 if( cn_len - cn_idx == name->len - 1 &&
Manuel Pégourié-Gonnard88421242014-10-17 11:36:18 +02001789 x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001790 {
Manuel Pégourié-Gonnardb80d16d2015-06-23 09:24:29 +02001791 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001792 }
1793
Manuel Pégourié-Gonnardb80d16d2015-06-23 09:24:29 +02001794 return( -1 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001795}
1796
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02001797/*
Manuel Pégourié-Gonnardef9a6ae2014-10-17 12:25:12 +02001798 * Compare two X.509 strings, case-insensitive, and allowing for some encoding
1799 * variations (but not all).
1800 *
1801 * Return 0 if equal, -1 otherwise.
1802 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
Manuel Pégourié-Gonnardef9a6ae2014-10-17 12:25:12 +02001804{
1805 if( a->tag == b->tag &&
1806 a->len == b->len &&
1807 memcmp( a->p, b->p, b->len ) == 0 )
1808 {
1809 return( 0 );
1810 }
1811
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
1813 ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
Manuel Pégourié-Gonnardef9a6ae2014-10-17 12:25:12 +02001814 a->len == b->len &&
1815 x509_memcasecmp( a->p, b->p, b->len ) == 0 )
1816 {
1817 return( 0 );
1818 }
1819
1820 return( -1 );
1821}
1822
1823/*
1824 * Compare two X.509 Names (aka rdnSequence).
1825 *
1826 * See RFC 5280 section 7.1, though we don't implement the whole algorithm:
1827 * we sometimes return unequal when the full algorithm would return equal,
1828 * but never the other way. (In particular, we don't do Unicode normalisation
1829 * or space folding.)
1830 *
1831 * Return 0 if equal, -1 otherwise.
1832 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
Manuel Pégourié-Gonnardef9a6ae2014-10-17 12:25:12 +02001834{
Manuel Pégourié-Gonnardf631bbc2014-11-12 18:35:31 +01001835 /* Avoid recursion, it might not be optimised by the compiler */
1836 while( a != NULL || b != NULL )
Manuel Pégourié-Gonnardef9a6ae2014-10-17 12:25:12 +02001837 {
Manuel Pégourié-Gonnardf631bbc2014-11-12 18:35:31 +01001838 if( a == NULL || b == NULL )
1839 return( -1 );
1840
1841 /* type */
1842 if( a->oid.tag != b->oid.tag ||
1843 a->oid.len != b->oid.len ||
1844 memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
1845 {
1846 return( -1 );
1847 }
1848
1849 /* value */
1850 if( x509_string_cmp( &a->val, &b->val ) != 0 )
1851 return( -1 );
1852
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +00001853 /* structure of the list of sets */
1854 if( a->next_merged != b->next_merged )
1855 return( -1 );
1856
Manuel Pégourié-Gonnardf631bbc2014-11-12 18:35:31 +01001857 a = a->next;
1858 b = b->next;
Manuel Pégourié-Gonnardef9a6ae2014-10-17 12:25:12 +02001859 }
1860
Manuel Pégourié-Gonnardf631bbc2014-11-12 18:35:31 +01001861 /* a == NULL == b */
1862 return( 0 );
Manuel Pégourié-Gonnardef9a6ae2014-10-17 12:25:12 +02001863}
1864
1865/*
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02001866 * Check the signature of a certificate by its parent
1867 */
1868static int x509_crt_check_signature( const mbedtls_x509_crt *child,
1869 mbedtls_x509_crt *parent )
1870{
1871 const mbedtls_md_info_t *md_info;
1872 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
1873
1874 md_info = mbedtls_md_info_from_type( child->sig_md );
1875 if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
1876 {
1877 /* Note: this can't happen except after an internal error */
1878 return( -1 );
1879 }
1880
1881 if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
1882 child->sig_md, hash, mbedtls_md_get_size( md_info ),
1883 child->sig.p, child->sig.len ) != 0 )
1884 {
1885 return( -1 );
1886 }
1887
1888 return( 0 );
1889}
1890
1891/*
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02001892 * Check if 'parent' is a suitable parent (signing CA) for 'child'.
1893 * Return 0 if yes, -1 if not.
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02001894 *
1895 * top means parent is a locally-trusted certificate
1896 * bottom means child is the end entity cert
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02001897 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898static int x509_crt_check_parent( const mbedtls_x509_crt *child,
1899 const mbedtls_x509_crt *parent,
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02001900 int top )
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02001901{
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02001902 int need_ca_bit;
1903
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02001904 /* Parent must be the issuer */
Manuel Pégourié-Gonnardef9a6ae2014-10-17 12:25:12 +02001905 if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 )
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02001906 return( -1 );
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02001907
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02001908 /* Parent must have the basicConstraints CA bit set as a general rule */
1909 need_ca_bit = 1;
1910
1911 /* Exception: v1/v2 certificates that are locally trusted. */
1912 if( top && parent->version < 3 )
1913 need_ca_bit = 0;
1914
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02001915 if( need_ca_bit && ! parent->ca_istrue )
1916 return( -1 );
1917
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001918#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
Manuel Pégourié-Gonnardd249b7a2014-06-24 11:49:16 +02001919 if( need_ca_bit &&
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 )
Manuel Pégourié-Gonnardc4eff162014-06-19 12:18:08 +02001921 {
1922 return( -1 );
1923 }
Manuel Pégourié-Gonnard312010e2014-04-09 14:30:11 +02001924#endif
1925
1926 return( 0 );
Manuel Pégourié-Gonnard3fed0b32014-04-08 13:18:01 +02001927}
1928
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02001929/*
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02001930 * Find a suitable parent for child in candidates, or return NULL.
1931 *
1932 * Here suitable is defined as:
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02001933 * 1. subject name matches child's issuer
1934 * 2. if necessary, the CA bit is set and key usage allows signing certs
1935 * 3. for trusted roots, the signature is correct
1936 * 4. pathlen constraints are satisfied
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02001937 *
1938 * Stop at the first suitable candidate, except if it's not time-valid (not
1939 * expired nor future) *and* there is a later suitable candidate that is
1940 * time-valid.
1941 *
1942 * The rationale for this rule is that someone could have a list of trusted
1943 * roots with two versions on the same root with different validity periods.
1944 * (At least one user reported having such a list and wanted it to just work.)
1945 * The reason we don't just require time-validity is that generally there is
1946 * only one version, and if it's expired we want the flags to state that
1947 * rather than NOT_TRUSTED, as would be the case if we required it here.
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02001948 *
1949 * The rationale for rule 3 (signature for trusted roots) is that users might
1950 * have two versions of the same CA with different keys in their list, and the
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02001951 * way we select the correct one is by checking the signature (as we don't
1952 * rely on key identifier extensions). (This is one way users might choose to
1953 * handle key rollover, another relies on self-issued certs, see [SIRO].)
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02001954 */
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02001955static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
1956 mbedtls_x509_crt *candidates,
1957 int top,
1958 int path_cnt,
1959 int self_cnt )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02001960{
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02001961 mbedtls_x509_crt *parent, *badtime_parent = NULL;
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02001962
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02001963 for( parent = candidates; parent != NULL; parent = parent->next )
1964 {
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02001965 /* basic parenting skills (name, CA bit, key usage) */
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02001966 if( x509_crt_check_parent( child, parent, top ) != 0 )
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02001967 continue;
1968
Manuel Pégourié-Gonnard9c6118c2017-06-29 12:38:42 +02001969 /* +1 because stored max_pathlen is 1 higher that the actual value */
1970 if( parent->max_pathlen > 0 &&
1971 parent->max_pathlen < 1 + path_cnt - self_cnt )
1972 {
1973 continue;
1974 }
1975
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02001976 /* Signature */
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02001977 if( top && x509_crt_check_signature( child, parent ) != 0 )
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02001978 {
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02001979 continue;
Manuel Pégourié-Gonnard2f09d592017-07-03 18:30:43 +02001980 }
1981
1982 /* optionnal time check */
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02001983 if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
1984 mbedtls_x509_time_is_future( &parent->valid_from ) )
1985 {
1986 if( badtime_parent == NULL )
1987 badtime_parent = parent;
1988
1989 continue;
1990 }
1991
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02001992 break;
1993 }
1994
Manuel Pégourié-Gonnard3e329b82017-06-29 12:55:27 +02001995 if( parent == NULL )
1996 parent = badtime_parent;
1997
Manuel Pégourié-Gonnard2f1c33d2017-06-29 12:27:23 +02001998 return parent;
1999}
2000
2001/*
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002002 * Find a parent in trusted CAs or the provided chain, or return NULL.
2003 *
2004 * Searches in trusted CAs first, and return the first suitable parent found
2005 * (see find_parent_in() for definition of suitable).
2006 */
2007static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child,
2008 mbedtls_x509_crt *trust_ca,
2009 int *parent_is_trusted,
2010 int path_cnt,
2011 int self_cnt )
2012{
2013 mbedtls_x509_crt *parent;
2014
2015 /* Look for a parent in trusted CAs */
2016 *parent_is_trusted = 1;
2017 parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt );
2018
2019 if( parent != NULL )
2020 return parent;
2021
2022 /* Look for a parent upwards the chain */
2023 *parent_is_trusted = 0;
2024 return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) );
2025}
2026
2027/*
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002028 * Check if an end-entity certificate is locally trusted
2029 *
2030 * Currently we require such certificates to be self-signed (actually only
2031 * check for self-issued as self-signatures are not checked)
2032 */
2033static int x509_crt_check_ee_locally_trusted(
2034 mbedtls_x509_crt *crt,
2035 mbedtls_x509_crt *trust_ca )
2036{
2037 mbedtls_x509_crt *cur;
2038
2039 /* must be self-issued */
2040 if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 )
2041 return( -1 );
2042
2043 /* look for an exact match with trusted cert */
2044 for( cur = trust_ca; cur != NULL; cur = cur->next )
2045 {
2046 if( crt->raw.len == cur->raw.len &&
2047 memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 )
2048 {
2049 return( 0 );
2050 }
2051 }
2052
2053 /* too bad */
2054 return( -1 );
2055}
2056
2057/*
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002058 * Build and verify a certificate chain
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002059 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002060 * Given a peer-provided list of certificates EE, C1, ..., Cn and
2061 * a list of trusted certs R1, ... Rp, try to build and verify a chain
2062 * EE, Ci1, ... Ciq, Rj
2063 * such that every cert in the chain is a child of the next one,
2064 * jumping to a trusted root as early as possible.
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002065 *
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002066 * Verify that chain and return it with flags for all issues found.
2067 *
2068 * Special cases:
2069 * - EE == Rj -> return a one-element list containing it
2070 * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
2071 * -> return that chain with NOT_TRUSTED set on Ciq
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002072 *
2073 * Arguments:
2074 * - child: the current bottom of the chain to verify
2075 * - trust_ca, ca_crl, profile: as in verify_with_profile()
2076 * - top: 1 if child is known to be locally trusted
2077 * - path_cnt: current depth as passed to f_vrfy() (EE = 0, etc)
2078 * - self_cnt: number of self-issued certs seen so far in the chain
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002079 * - [out] ver_chain: the built and verified chain
2080 *
2081 * Return value:
2082 * - non-zero if the chain could not be fully built and examined
2083 * - 0 is the chain was successfully built and examined,
2084 * even if it was found to be invalid
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002085 */
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002086static int x509_crt_verify_chain(
Manuel Pégourié-Gonnard58dcd2d2017-07-03 21:35:04 +02002087 mbedtls_x509_crt *child,
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002088 mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl,
2089 const mbedtls_x509_crt_profile *profile,
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002090 int top, int path_cnt, int self_cnt,
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02002091 x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE] )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002092{
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002093 uint32_t *flags;
Manuel Pégourié-Gonnard58dcd2d2017-07-03 21:35:04 +02002094 mbedtls_x509_crt *parent;
Manuel Pégourié-Gonnard6e786742017-07-03 23:47:44 +02002095 int parent_is_trusted = 0;
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02002096
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002097 /* Add certificate to the verification chain */
2098 ver_chain[path_cnt].crt = child;
2099 flags = &ver_chain[path_cnt].flags;
2100
2101 /* Check time-validity (all certificates) */
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02002102 if( mbedtls_x509_time_is_past( &child->valid_to ) )
2103 *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
2104
2105 if( mbedtls_x509_time_is_future( &child->valid_from ) )
2106 *flags |= MBEDTLS_X509_BADCERT_FUTURE;
2107
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002108 /* Stop here for trusted roots (but not for trusted EE certs) */
Manuel Pégourié-Gonnardcb396102017-07-04 00:00:24 +02002109 if( top )
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002110 return( 0 );
Manuel Pégourié-Gonnardcb396102017-07-04 00:00:24 +02002111
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002112 /* Check signature algorithm: MD & PK algs */
Manuel Pégourié-Gonnard66fac752017-07-03 21:39:21 +02002113 if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 )
2114 *flags |= MBEDTLS_X509_BADCERT_BAD_MD;
2115
2116 if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 )
2117 *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
2118
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002119 /* Special case: EE certs that are locally trusted */
2120 if( path_cnt == 0 &&
2121 x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
2122 {
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002123 return( 0 );
Manuel Pégourié-Gonnard27e94792017-07-04 00:49:31 +02002124 }
2125
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002126 /* Look for a parent in trusted CAs or up the chain */
2127 parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted,
2128 path_cnt, self_cnt );
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02002129
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002130 /* No parent? We're done here */
2131 if( parent == NULL )
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02002132 {
Manuel Pégourié-Gonnard63686122017-07-04 01:01:39 +02002133 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002134 return( 0 );
Manuel Pégourié-Gonnard8f8c2822017-07-03 21:25:10 +02002135 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002136
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002137 /* Count intermediate self-issued (not necessarily self-signed) certs.
2138 * These can occur with some strategies for key rollover, see [SIRO],
2139 * and should be excluded from max_pathlen checks. */
Manuel Pégourié-Gonnarde670f902015-10-30 09:23:19 +01002140 if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 )
Janos Follath5dd4fe12015-10-12 09:02:20 +02002141 self_cnt++;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002142
Manuel Pégourié-Gonnard6e786742017-07-03 23:47:44 +02002143 /* path_cnt is 0 for the first intermediate CA,
2144 * and if parent is trusted it's not an intermediate CA */
2145 if( ! parent_is_trusted &&
2146 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
Manuel Pégourié-Gonnardfd6c85c2014-11-20 16:34:20 +01002147 {
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002148 /* return immediately to avoid overflow the chain array */
Manuel Pégourié-Gonnard31458a12017-06-26 10:11:49 +02002149 return( MBEDTLS_ERR_X509_FATAL_ERROR );
Manuel Pégourié-Gonnardfd6c85c2014-11-20 16:34:20 +01002150 }
2151
Manuel Pégourié-Gonnard6e786742017-07-03 23:47:44 +02002152 /* if parent is trusted, the signature was checked by find_parent() */
2153 if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002155
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002156 /* check size of signing key */
Manuel Pégourié-Gonnardf82a4d52017-07-03 19:26:25 +02002157 if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 )
2158 *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160#if defined(MBEDTLS_X509_CRL_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002161 /* Check trusted CA's CRL for the given crt */
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002162 *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002163#endif
2164
Manuel Pégourié-Gonnardcb396102017-07-04 00:00:24 +02002165 /* verify the rest of the chain starting from parent */
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002166 return( x509_crt_verify_chain( parent, trust_ca, ca_crl, profile,
Manuel Pégourié-Gonnardcb396102017-07-04 00:00:24 +02002167 parent_is_trusted, path_cnt + 1, self_cnt,
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002168 ver_chain ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002169}
2170
2171/*
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002172 * Check for CN match
2173 */
2174static int x509_crt_check_cn( const mbedtls_x509_buf *name,
2175 const char *cn, size_t cn_len )
2176{
2177 /* try exact match */
2178 if( name->len == cn_len &&
2179 x509_memcasecmp( cn, name->p, cn_len ) == 0 )
2180 {
2181 return( 0 );
2182 }
2183
2184 /* try wildcard match */
2185 if( name->len > 2 &&
2186 memcmp( name->p, "*.", 2 ) == 0 &&
2187 x509_check_wildcard( cn, name ) == 0 )
2188 {
2189 return( 0 );
2190 }
2191
2192 return( -1 );
2193}
2194
2195/*
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002196 * Verify the requested CN - only call this if cn is not NULL!
2197 */
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002198static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002199 const char *cn,
2200 uint32_t *flags )
2201{
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002202 const mbedtls_x509_name *name;
2203 const mbedtls_x509_sequence *cur;
2204 size_t cn_len = strlen( cn );
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002205
2206 if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
2207 {
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002208 for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002209 {
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002210 if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002211 break;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002212 }
2213
2214 if( cur == NULL )
2215 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
2216 }
2217 else
2218 {
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002219 for( name = &crt->subject; name != NULL; name = name->next )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002220 {
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002221 if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 &&
2222 x509_crt_check_cn( &name->val, cn, cn_len ) == 0 )
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002223 {
Manuel Pégourié-Gonnarda468eb12017-07-04 01:31:59 +02002224 break;
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002225 }
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002226 }
2227
2228 if( name == NULL )
2229 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
2230 }
2231}
2232
2233/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002234 * Verify the certificate validity
2235 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
2237 mbedtls_x509_crt *trust_ca,
2238 mbedtls_x509_crl *ca_crl,
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02002239 const char *cn, uint32_t *flags,
2240 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
Paul Bakkerddf26b42013-09-18 13:46:23 +02002241 void *p_vrfy )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002242{
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002243 return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl,
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +02002244 &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) );
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002245}
2246
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002247/*
2248 * Verify the certificate validity, with profile
Manuel Pégourié-Gonnard35407c72017-06-29 10:45:25 +02002249 *
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002250 * This function only checks the requested CN (if any) and then delegates
2251 * chain building/verification to verify_chain(). Before that, it checks the
2252 * key size of the EE certificate, as verify_chain() will only verify that of
2253 * parent certificates.
Manuel Pégourié-Gonnard95051642015-06-15 10:39:46 +02002254 */
2255int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
2256 mbedtls_x509_crt *trust_ca,
2257 mbedtls_x509_crl *ca_crl,
2258 const mbedtls_x509_crt_profile *profile,
2259 const char *cn, uint32_t *flags,
2260 int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
2261 void *p_vrfy )
2262{
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002263 int ret;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02002264 mbedtls_pk_type_t pk_type;
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02002265 x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE];
2266 size_t i;
2267 uint32_t cur_flags;
2268 uint32_t *ee_flags = &ver_chain[0].flags;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002269
2270 *flags = 0;
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02002271 memset( ver_chain, 0, sizeof( ver_chain ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002272
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02002273 if( profile == NULL )
2274 {
2275 ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
2276 goto exit;
2277 }
2278
Manuel Pégourié-Gonnard1300e992017-07-04 01:13:44 +02002279 /* check name if requested */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002280 if( cn != NULL )
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02002281 x509_crt_verify_name( crt, cn, ee_flags );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002282
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02002283 /* Check the type and size of the key */
2284 pk_type = mbedtls_pk_get_type( &crt->pk );
2285
2286 if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02002287 *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02002288
2289 if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 )
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02002290 *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
Manuel Pégourié-Gonnard65eefc82015-10-23 14:08:48 +02002291
Manuel Pégourié-Gonnardbdc54402017-07-04 00:33:39 +02002292 /* Check the chain */
2293 ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
Manuel Pégourié-Gonnardf86f4912017-07-05 16:43:44 +02002294 0, 0, 0,
2295 ver_chain );
Manuel Pégourié-Gonnardc547d1a2017-07-05 13:28:45 +02002296 if( ret != 0 )
2297 goto exit;
2298
2299 /* Build final flags, calling calback on the way if any */
2300 for( i = X509_MAX_VERIFY_CHAIN_SIZE; i != 0; --i )
2301 {
2302 if( ver_chain[i-1].crt == NULL )
2303 continue;
2304
2305 cur_flags = ver_chain[i-1].flags;
2306
2307 if( NULL != f_vrfy )
2308 if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, i-1, &cur_flags ) ) != 0 )
2309 goto exit;
2310
2311 *flags |= cur_flags;
2312 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002313
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02002314exit:
Manuel Pégourié-Gonnard9107b5f2017-07-06 12:16:25 +02002315 /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
2316 * the SSL module for authmode optional, but non-zero return from the
2317 * callback means a fatal error so it shouldn't be ignored */
Manuel Pégourié-Gonnard31458a12017-06-26 10:11:49 +02002318 if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
2319 ret = MBEDTLS_ERR_X509_FATAL_ERROR;
2320
Manuel Pégourié-Gonnardd15795a2017-06-22 12:19:27 +02002321 if( ret != 0 )
2322 {
2323 *flags = (uint32_t) -1;
2324 return( ret );
2325 }
2326
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002327 if( *flags != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002328 return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002329
2330 return( 0 );
2331}
2332
2333/*
Paul Bakker369d2eb2013-09-18 11:58:25 +02002334 * Initialize a certificate chain
2335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002336void mbedtls_x509_crt_init( mbedtls_x509_crt *crt )
Paul Bakker369d2eb2013-09-18 11:58:25 +02002337{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 memset( crt, 0, sizeof(mbedtls_x509_crt) );
Paul Bakker369d2eb2013-09-18 11:58:25 +02002339}
2340
2341/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002342 * Unallocate all certificate data
2343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002345{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346 mbedtls_x509_crt *cert_cur = crt;
2347 mbedtls_x509_crt *cert_prv;
2348 mbedtls_x509_name *name_cur;
2349 mbedtls_x509_name *name_prv;
2350 mbedtls_x509_sequence *seq_cur;
2351 mbedtls_x509_sequence *seq_prv;
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002352
2353 if( crt == NULL )
2354 return;
2355
2356 do
2357 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 mbedtls_pk_free( &cert_cur->pk );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
2361 mbedtls_free( cert_cur->sig_opts );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +02002362#endif
2363
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002364 name_cur = cert_cur->issuer.next;
2365 while( name_cur != NULL )
2366 {
2367 name_prv = name_cur;
2368 name_cur = name_cur->next;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
2370 mbedtls_free( name_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002371 }
2372
2373 name_cur = cert_cur->subject.next;
2374 while( name_cur != NULL )
2375 {
2376 name_prv = name_cur;
2377 name_cur = name_cur->next;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) );
2379 mbedtls_free( name_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002380 }
2381
2382 seq_cur = cert_cur->ext_key_usage.next;
2383 while( seq_cur != NULL )
2384 {
2385 seq_prv = seq_cur;
2386 seq_cur = seq_cur->next;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) );
2388 mbedtls_free( seq_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002389 }
2390
2391 seq_cur = cert_cur->subject_alt_names.next;
2392 while( seq_cur != NULL )
2393 {
2394 seq_prv = seq_cur;
2395 seq_cur = seq_cur->next;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396 mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) );
2397 mbedtls_free( seq_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002398 }
2399
2400 if( cert_cur->raw.p != NULL )
2401 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002402 mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len );
2403 mbedtls_free( cert_cur->raw.p );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002404 }
2405
2406 cert_cur = cert_cur->next;
2407 }
2408 while( cert_cur != NULL );
2409
2410 cert_cur = crt;
2411 do
2412 {
2413 cert_prv = cert_cur;
2414 cert_cur = cert_cur->next;
2415
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002416 mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002417 if( cert_prv != crt )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002418 mbedtls_free( cert_prv );
Paul Bakker7c6b2c32013-09-16 13:49:26 +02002419 }
2420 while( cert_cur != NULL );
2421}
2422
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002423#endif /* MBEDTLS_X509_CRT_PARSE_C */