blob: aaf7f7e88e249e6a625d884f1739b1f01c85dfd6 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
Manuel Pégourié-Gonnard1c082f32014-06-12 22:34:55 +02002 * X.509 common functions for 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
30 */
31
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020034#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020036#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020037
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_X509_USE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/x509.h"
41#include "mbedtls/asn1.h"
42#include "mbedtls/oid.h"
Rich Evans00ab4702015-02-06 13:43:58 +000043
Rich Evans36796df2015-02-12 18:27:14 +000044#include <stdio.h>
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <string.h>
46
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000048#include "mbedtls/pem.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020049#endif
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020053#else
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <stdio.h>
55#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_printf printf
59#define mbedtls_snprintf snprintf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020060#endif
61
Paul Bakkerfa6a6202013-10-28 18:48:30 +010062#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020063#include <windows.h>
64#else
65#include <time.h>
66#endif
67
Rich Evans7d5a55a2015-02-13 11:48:02 +000068#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
Andres AG53d77132016-09-23 13:16:02 +010069#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
Rich Evans7d5a55a2015-02-13 11:48:02 +000070
Paul Bakker7c6b2c32013-09-16 13:49:26 +020071/*
72 * CertificateSerialNumber ::= INTEGER
73 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
75 mbedtls_x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +020076{
77 int ret;
78
79 if( ( end - *p ) < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080 return( MBEDTLS_ERR_X509_INVALID_SERIAL +
81 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083 if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) &&
84 **p != MBEDTLS_ASN1_INTEGER )
85 return( MBEDTLS_ERR_X509_INVALID_SERIAL +
86 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020087
88 serial->tag = *(*p)++;
89
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090 if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 )
91 return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020092
93 serial->p = *p;
94 *p += serial->len;
95
96 return( 0 );
97}
98
99/* Get an algorithm identifier without parameters (eg for signatures)
100 *
101 * AlgorithmIdentifier ::= SEQUENCE {
102 * algorithm OBJECT IDENTIFIER,
103 * parameters ANY DEFINED BY algorithm OPTIONAL }
104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
106 mbedtls_x509_buf *alg )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200107{
108 int ret;
109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
111 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200112
113 return( 0 );
114}
115
116/*
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100117 * Parse an algorithm identifier with (optional) paramaters
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
120 mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100121{
122 int ret;
123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
125 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100126
127 return( 0 );
128}
129
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100131/*
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100132 * HashAlgorithm ::= AlgorithmIdentifier
133 *
134 * AlgorithmIdentifier ::= SEQUENCE {
135 * algorithm OBJECT IDENTIFIER,
136 * parameters ANY DEFINED BY algorithm OPTIONAL }
137 *
138 * For HashAlgorithm, parameters MUST be NULL or absent.
139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100141{
142 int ret;
143 unsigned char *p;
144 const unsigned char *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 mbedtls_x509_buf md_oid;
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100146 size_t len;
147
148 /* Make sure we got a SEQUENCE and setup bounds */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
150 return( MBEDTLS_ERR_X509_INVALID_ALG +
151 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100152
153 p = (unsigned char *) alg->p;
154 end = p + alg->len;
155
156 if( p >= end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 return( MBEDTLS_ERR_X509_INVALID_ALG +
158 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100159
160 /* Parse md_oid */
161 md_oid.tag = *p;
162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
164 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100165
166 md_oid.p = p;
167 p += md_oid.len;
168
169 /* Get md_alg from md_oid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
171 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100172
173 /* Make sure params is absent of NULL */
174 if( p == end )
175 return( 0 );
176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 )
178 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100179
180 if( p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 return( MBEDTLS_ERR_X509_INVALID_ALG +
182 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100183
184 return( 0 );
185}
186
187/*
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100188 * RSASSA-PSS-params ::= SEQUENCE {
189 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
190 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
191 * saltLength [2] INTEGER DEFAULT 20,
192 * trailerField [3] INTEGER DEFAULT 1 }
193 * -- Note that the tags in this Sequence are explicit.
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200194 *
195 * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
196 * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
197 * option. Enfore this at parsing time.
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100198 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
200 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200201 int *salt_len )
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100202{
203 int ret;
204 unsigned char *p;
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100205 const unsigned char *end, *end2;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100206 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 mbedtls_x509_buf alg_id, alg_params;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100208
209 /* First set everything to defaults */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 *md_alg = MBEDTLS_MD_SHA1;
211 *mgf_md = MBEDTLS_MD_SHA1;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100212 *salt_len = 20;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100213
214 /* Make sure params is a SEQUENCE and setup bounds */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
216 return( MBEDTLS_ERR_X509_INVALID_ALG +
217 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100218
219 p = (unsigned char *) params->p;
220 end = p + params->len;
221
222 if( p == end )
223 return( 0 );
224
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100225 /*
226 * HashAlgorithm
227 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200228 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
229 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100230 {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100231 end2 = p + len;
232
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100233 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100235 return( ret );
236
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200237 if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
238 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100239
240 if( p != end2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 return( MBEDTLS_ERR_X509_INVALID_ALG +
242 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100243 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
245 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100246
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100247 if( p == end )
248 return( 0 );
249
250 /*
251 * MaskGenAlgorithm
252 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
254 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100255 {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100256 end2 = p + len;
257
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100258 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100260 return( ret );
261
262 /* Only MFG1 is recognised for now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 )
264 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +
265 MBEDTLS_ERR_OID_NOT_FOUND );
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100266
267 /* Parse HashAlgorithm */
268 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
269 return( ret );
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100270
271 if( p != end2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 return( MBEDTLS_ERR_X509_INVALID_ALG +
273 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100274 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
276 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100277
278 if( p == end )
279 return( 0 );
280
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100281 /*
282 * salt_len
283 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
285 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 )
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100286 {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100287 end2 = p + len;
288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 )
290 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100291
292 if( p != end2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 return( MBEDTLS_ERR_X509_INVALID_ALG +
294 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100295 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
297 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100298
299 if( p == end )
300 return( 0 );
301
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100302 /*
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200303 * trailer_field (if present, must be 1)
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100304 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
306 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 )
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100307 {
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200308 int trailer_field;
309
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100310 end2 = p + len;
311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312 if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
313 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100314
315 if( p != end2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 return( MBEDTLS_ERR_X509_INVALID_ALG +
317 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnard78117d52014-05-31 17:08:16 +0200318
319 if( trailer_field != 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 return( MBEDTLS_ERR_X509_INVALID_ALG );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100321 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
323 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100324
325 if( p != end )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 return( MBEDTLS_ERR_X509_INVALID_ALG +
327 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100328
329 return( 0 );
330}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100332
333/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200334 * AttributeTypeAndValue ::= SEQUENCE {
335 * type AttributeType,
336 * value AttributeValue }
337 *
338 * AttributeType ::= OBJECT IDENTIFIER
339 *
340 * AttributeValue ::= ANY DEFINED BY AttributeType
341 */
342static int x509_get_attr_type_value( unsigned char **p,
343 const unsigned char *end,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200344 mbedtls_x509_name *cur )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200345{
346 int ret;
347 size_t len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 mbedtls_x509_buf *oid;
349 mbedtls_x509_buf *val;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
352 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
353 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200354
355 if( ( end - *p ) < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 return( MBEDTLS_ERR_X509_INVALID_NAME +
357 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200358
359 oid = &cur->oid;
360 oid->tag = **p;
361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362 if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 )
363 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200364
365 oid->p = *p;
366 *p += oid->len;
367
368 if( ( end - *p ) < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 return( MBEDTLS_ERR_X509_INVALID_NAME +
370 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING &&
373 **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
374 **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
375 **p != MBEDTLS_ASN1_BIT_STRING )
376 return( MBEDTLS_ERR_X509_INVALID_NAME +
377 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200378
379 val = &cur->val;
380 val->tag = *(*p)++;
381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 )
383 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200384
385 val->p = *p;
386 *p += val->len;
387
388 cur->next = NULL;
389
390 return( 0 );
391}
392
393/*
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000394 * Name ::= CHOICE { -- only one possibility for now --
395 * rdnSequence RDNSequence }
396 *
397 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
398 *
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200399 * RelativeDistinguishedName ::=
400 * SET OF AttributeTypeAndValue
401 *
402 * AttributeTypeAndValue ::= SEQUENCE {
403 * type AttributeType,
404 * value AttributeValue }
405 *
406 * AttributeType ::= OBJECT IDENTIFIER
407 *
408 * AttributeValue ::= ANY DEFINED BY AttributeType
Manuel Pégourié-Gonnard5d861852014-10-17 12:41:41 +0200409 *
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000410 * The data structure is optimized for the common case where each RDN has only
411 * one element, which is represented as a list of AttributeTypeAndValue.
412 * For the general case we still use a flat list, but we mark elements of the
413 * same set so that they are "merged" together in the functions that consume
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414 * this list, eg mbedtls_x509_dn_gets().
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
417 mbedtls_x509_name *cur )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200418{
419 int ret;
Manuel Pégourié-Gonnard5d861852014-10-17 12:41:41 +0200420 size_t set_len;
421 const unsigned char *end_set;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200422
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100423 /* don't use recursion, we'd risk stack overflow if not optimized */
424 while( 1 )
425 {
426 /*
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000427 * parse SET
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100428 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
430 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
431 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200432
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100433 end_set = *p + set_len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200434
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000435 while( 1 )
436 {
437 if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
438 return( ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200439
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000440 if( *p == end_set )
441 break;
442
Manuel Pégourié-Gonnardeecb43c2015-05-12 12:56:41 +0200443 /* Mark this item as being no the only one in a set */
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000444 cur->next_merged = 1;
445
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200446 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000447
448 if( cur->next == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200449 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000450
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000451 cur = cur->next;
452 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200453
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100454 /*
455 * continue until end of SEQUENCE is reached
456 */
457 if( *p == end )
458 return( 0 );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200459
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200460 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200461
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100462 if( cur->next == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200463 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200464
Manuel Pégourié-Gonnardd6814432014-11-12 01:25:31 +0100465 cur = cur->next;
466 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200467}
468
Janos Follath5ad40452017-02-03 12:36:59 +0000469static int x509_parse_int( unsigned char **p, size_t n, int *res )
470{
Rich Evans7d5a55a2015-02-13 11:48:02 +0000471 *res = 0;
Janos Follath5ad40452017-02-03 12:36:59 +0000472
473 for( ; n > 0; --n )
474 {
475 if( ( **p < '0') || ( **p > '9' ) )
476 return ( MBEDTLS_ERR_X509_INVALID_DATE );
477
Rich Evans7d5a55a2015-02-13 11:48:02 +0000478 *res *= 10;
Janos Follath5ad40452017-02-03 12:36:59 +0000479 *res += ( *(*p)++ - '0' );
Rich Evans7d5a55a2015-02-13 11:48:02 +0000480 }
Janos Follath5ad40452017-02-03 12:36:59 +0000481
482 return( 0 );
Rich Evans7d5a55a2015-02-13 11:48:02 +0000483}
484
Andres Amaya Garciabc041132016-11-21 15:38:02 +0000485static int x509_date_is_valid(const mbedtls_x509_time *t )
Andres AG53d77132016-09-23 13:16:02 +0100486{
487 int ret = MBEDTLS_ERR_X509_INVALID_DATE;
Andres Amaya Garciabc041132016-11-21 15:38:02 +0000488 int month_len;
Andres AG53d77132016-09-23 13:16:02 +0100489
Hanno Becker6ad82d72017-04-26 15:01:23 +0100490 CHECK_RANGE( 0, 9999, t->year );
491 CHECK_RANGE( 0, 23, t->hour );
492 CHECK_RANGE( 0, 59, t->min );
493 CHECK_RANGE( 0, 59, t->sec );
Andres AG53d77132016-09-23 13:16:02 +0100494
Hanno Becker6ad82d72017-04-26 15:01:23 +0100495 switch( t->mon )
Andres AG53d77132016-09-23 13:16:02 +0100496 {
497 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
Andres Amaya Garciabc041132016-11-21 15:38:02 +0000498 month_len = 31;
Andres AG53d77132016-09-23 13:16:02 +0100499 break;
500 case 4: case 6: case 9: case 11:
Andres Amaya Garciabc041132016-11-21 15:38:02 +0000501 month_len = 30;
Andres AG53d77132016-09-23 13:16:02 +0100502 break;
503 case 2:
Andres Amaya Garciabc041132016-11-21 15:38:02 +0000504 if( ( !( t->year % 4 ) && t->year % 100 ) ||
505 !( t->year % 400 ) )
506 month_len = 29;
507 else
508 month_len = 28;
Andres AG53d77132016-09-23 13:16:02 +0100509 break;
510 default:
511 return( ret );
512 }
Andres Amaya Garciabc041132016-11-21 15:38:02 +0000513 CHECK_RANGE( 1, month_len, t->day );
Andres AG53d77132016-09-23 13:16:02 +0100514
515 return( 0 );
516}
517
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200518/*
Janos Follath5ad40452017-02-03 12:36:59 +0000519 * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
520 * field.
521 */
522static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
Hanno Becker6ad82d72017-04-26 15:01:23 +0100523 mbedtls_x509_time *tm )
Janos Follath5ad40452017-02-03 12:36:59 +0000524{
525 int ret;
526
527 /*
528 * Minimum length is 10 or 12 depending on yearlen
529 */
530 if ( len < yearlen + 8 )
531 return ( MBEDTLS_ERR_X509_INVALID_DATE );
532 len -= yearlen + 8;
533
534 /*
535 * Parse year, month, day, hour, minute
536 */
Hanno Becker6ad82d72017-04-26 15:01:23 +0100537 CHECK( x509_parse_int( p, yearlen, &tm->year ) );
Janos Follath5ad40452017-02-03 12:36:59 +0000538 if ( 2 == yearlen )
539 {
Hanno Becker6ad82d72017-04-26 15:01:23 +0100540 if ( tm->year < 50 )
541 tm->year += 100;
Janos Follath5ad40452017-02-03 12:36:59 +0000542
Hanno Becker6ad82d72017-04-26 15:01:23 +0100543 tm->year += 1900;
Janos Follath5ad40452017-02-03 12:36:59 +0000544 }
545
Hanno Becker6ad82d72017-04-26 15:01:23 +0100546 CHECK( x509_parse_int( p, 2, &tm->mon ) );
547 CHECK( x509_parse_int( p, 2, &tm->day ) );
548 CHECK( x509_parse_int( p, 2, &tm->hour ) );
549 CHECK( x509_parse_int( p, 2, &tm->min ) );
Janos Follath5ad40452017-02-03 12:36:59 +0000550
551 /*
552 * Parse seconds if present
553 */
554 if ( len >= 2 )
555 {
Hanno Becker6ad82d72017-04-26 15:01:23 +0100556 CHECK( x509_parse_int( p, 2, &tm->sec ) );
Janos Follath5ad40452017-02-03 12:36:59 +0000557 len -= 2;
558 }
559 else
560 return ( MBEDTLS_ERR_X509_INVALID_DATE );
561
562 /*
563 * Parse trailing 'Z' if present
564 */
565 if ( 1 == len && 'Z' == **p )
566 {
567 (*p)++;
568 len--;
569 }
570
571 /*
572 * We should have parsed all characters at this point
573 */
574 if ( 0 != len )
575 return ( MBEDTLS_ERR_X509_INVALID_DATE );
576
Hanno Becker6ad82d72017-04-26 15:01:23 +0100577 CHECK( x509_date_is_valid( tm ) );
Janos Follath5ad40452017-02-03 12:36:59 +0000578
579 return ( 0 );
580}
581
582/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200583 * Time ::= CHOICE {
584 * utcTime UTCTime,
585 * generalTime GeneralizedTime }
586 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200587int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
Hanno Becker6ad82d72017-04-26 15:01:23 +0100588 mbedtls_x509_time *tm )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200589{
590 int ret;
Janos Follath5ad40452017-02-03 12:36:59 +0000591 size_t len, year_len;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200592 unsigned char tag;
593
594 if( ( end - *p ) < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 return( MBEDTLS_ERR_X509_INVALID_DATE +
596 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200597
598 tag = **p;
599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600 if( tag == MBEDTLS_ASN1_UTC_TIME )
Janos Follath5ad40452017-02-03 12:36:59 +0000601 year_len = 2;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME )
Janos Follath5ad40452017-02-03 12:36:59 +0000603 year_len = 4;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200604 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605 return( MBEDTLS_ERR_X509_INVALID_DATE +
606 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
Janos Follath5ad40452017-02-03 12:36:59 +0000607
608 (*p)++;
609 ret = mbedtls_asn1_get_len( p, end, &len );
610
611 if( ret != 0 )
612 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
613
Hanno Becker6ad82d72017-04-26 15:01:23 +0100614 return x509_parse_time( p, len, year_len, tm );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200615}
616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200618{
619 int ret;
620 size_t len;
Andres AG6a3fa212016-09-19 16:58:45 +0100621 int tag_type;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200622
623 if( ( end - *p ) < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE +
625 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200626
Andres AG6a3fa212016-09-19 16:58:45 +0100627 tag_type = **p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200629 if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
630 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200631
Andres AG6a3fa212016-09-19 16:58:45 +0100632 sig->tag = tag_type;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200633 sig->len = len;
634 sig->p = *p;
635
636 *p += len;
637
638 return( 0 );
639}
640
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100641/*
642 * Get signature algorithm from alg OID and optional parameters
643 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
645 mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200646 void **sig_opts )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200647{
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100648 int ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200649
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200650 if( *sig_opts != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
654 return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200655
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
657 if( *pk_alg == MBEDTLS_PK_RSASSA_PSS )
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100658 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 mbedtls_pk_rsassa_pss_options *pss_opts;
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100660
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200661 pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200662 if( pss_opts == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200663 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 ret = mbedtls_x509_get_rsassa_pss_params( sig_params,
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200666 md_alg,
667 &pss_opts->mgf1_hash_id,
668 &pss_opts->expected_salt_len );
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100669 if( ret != 0 )
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200670 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 mbedtls_free( pss_opts );
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100672 return( ret );
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200673 }
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100674
Manuel Pégourié-Gonnardf75f2f72014-06-05 15:14:28 +0200675 *sig_opts = (void *) pss_opts;
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100676 }
677 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100679 {
680 /* Make sure parameters are absent or NULL */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) ||
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100682 sig_params->len != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 return( MBEDTLS_ERR_X509_INVALID_ALG );
Manuel Pégourié-Gonnardcf975a32014-01-24 19:28:43 +0100684 }
685
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200686 return( 0 );
687}
688
689/*
690 * X.509 Extensions (No parsing of extensions, pointer should
Brian J Murray7a77cb22016-11-06 04:45:15 -0800691 * be either manually updated or extensions should be parsed!)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200692 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
694 mbedtls_x509_buf *ext, int tag )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200695{
696 int ret;
697 size_t len;
698
699 if( *p == end )
700 return( 0 );
701
702 ext->tag = **p;
703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len,
705 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200706 return( ret );
707
708 ext->p = *p;
709 end = *p + ext->len;
710
711 /*
712 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
713 *
714 * Extension ::= SEQUENCE {
715 * extnID OBJECT IDENTIFIER,
716 * critical BOOLEAN DEFAULT FALSE,
717 * extnValue OCTET STRING }
718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
720 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
721 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200722
723 if( end != *p + len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
725 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200726
727 return( 0 );
728}
729
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200730/*
731 * Store the name in printable form into buf; no more
732 * than size characters will be written
733 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200735{
736 int ret;
737 size_t i, n;
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000738 unsigned char c, merge = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 const mbedtls_x509_name *name;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200740 const char *short_name = NULL;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200742
743 memset( s, 0, sizeof( s ) );
744
745 name = dn;
746 p = buf;
747 n = size;
748
749 while( name != NULL )
750 {
751 if( !name->oid.p )
752 {
753 name = name->next;
754 continue;
755 }
756
757 if( name != dn )
758 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 ret = mbedtls_snprintf( p, n, merge ? " + " : ", " );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200760 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200761 }
762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200764
765 if( ret == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 ret = mbedtls_snprintf( p, n, "%s=", short_name );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200767 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 ret = mbedtls_snprintf( p, n, "\?\?=" );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200769 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200770
771 for( i = 0; i < name->val.len; i++ )
772 {
773 if( i >= sizeof( s ) - 1 )
774 break;
775
776 c = name->val.p[i];
777 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
778 s[i] = '?';
779 else s[i] = c;
780 }
781 s[i] = '\0';
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782 ret = mbedtls_snprintf( p, n, "%s", s );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200783 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnard555fbf82015-02-04 17:11:55 +0000784
785 merge = name->next_merged;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200786 name = name->next;
787 }
788
789 return( (int) ( size - n ) );
790}
791
792/*
793 * Store the serial in printable form into buf; no more
794 * than size characters will be written
795 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200797{
798 int ret;
799 size_t i, n, nr;
800 char *p;
801
802 p = buf;
803 n = size;
804
805 nr = ( serial->len <= 32 )
806 ? serial->len : 28;
807
808 for( i = 0; i < nr; i++ )
809 {
810 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
811 continue;
812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200813 ret = mbedtls_snprintf( p, n, "%02X%s",
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200814 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200815 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200816 }
817
818 if( nr != serial->len )
819 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820 ret = mbedtls_snprintf( p, n, "...." );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200821 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200822 }
823
824 return( (int) ( size - n ) );
825}
826
827/*
Manuel Pégourié-Gonnard91136032014-06-05 15:41:39 +0200828 * Helper for writing signature algorithms
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100829 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200830int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
831 mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
Manuel Pégourié-Gonnard91136032014-06-05 15:41:39 +0200832 const void *sig_opts )
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100833{
834 int ret;
835 char *p = buf;
836 size_t n = size;
837 const char *desc = NULL;
838
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200839 ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc );
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100840 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 ret = mbedtls_snprintf( p, n, "???" );
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100842 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200843 ret = mbedtls_snprintf( p, n, "%s", desc );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200844 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100845
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200846#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
847 if( pk_alg == MBEDTLS_PK_RSASSA_PSS )
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100848 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849 const mbedtls_pk_rsassa_pss_options *pss_opts;
850 const mbedtls_md_info_t *md_info, *mgf_md_info;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852 pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854 md_info = mbedtls_md_info_from_type( md_alg );
855 mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id );
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
858 md_info ? mbedtls_md_get_name( md_info ) : "???",
859 mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???",
Manuel Pégourié-Gonnard91136032014-06-05 15:41:39 +0200860 pss_opts->expected_salt_len );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200861 MBEDTLS_X509_SAFE_SNPRINTF;
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100862 }
863#else
864 ((void) pk_alg);
Manuel Pégourié-Gonnard91136032014-06-05 15:41:39 +0200865 ((void) md_alg);
866 ((void) sig_opts);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100868
Sander Niemeijeref5087d2014-08-16 12:45:52 +0200869 return( (int)( size - n ) );
Manuel Pégourié-Gonnardcac31ee2014-01-25 11:50:59 +0100870}
871
872/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200873 * Helper for writing "RSA key size", "EC key size", etc
874 */
Manuel Pégourié-Gonnardfb317c52015-06-18 16:25:56 +0200875int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200876{
877 char *p = buf;
Manuel Pégourié-Gonnardfb317c52015-06-18 16:25:56 +0200878 size_t n = buf_size;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200879 int ret;
880
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 ret = mbedtls_snprintf( p, n, "%s key size", name );
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200882 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200883
884 return( 0 );
885}
886
Manuel Pégourié-Gonnard60c793b2015-06-18 20:52:58 +0200887#if defined(MBEDTLS_HAVE_TIME_DATE)
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +0200888/*
889 * Set the time structure to the current time.
890 * Return 0 on success, non-zero on failure.
891 */
892#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200893static int x509_get_current_time( mbedtls_x509_time *now )
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100894{
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200895 SYSTEMTIME st;
896
Paul Bakker66d5d072014-06-17 16:39:18 +0200897 GetSystemTime( &st );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200898
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100899 now->year = st.wYear;
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200900 now->mon = st.wMonth;
901 now->day = st.wDay;
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100902 now->hour = st.wHour;
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200903 now->min = st.wMinute;
904 now->sec = st.wSecond;
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +0200905
906 return( 0 );
907}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200908#else
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +0200909static int x509_get_current_time( mbedtls_x509_time *now )
910{
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200911 struct tm *lt;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200912 time_t tt;
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +0200913 int ret = 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200914
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200915#if defined(MBEDTLS_THREADING_C)
916 if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
917 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
918#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200919
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200920 tt = time( NULL );
921 lt = gmtime( &tt );
922
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +0200923 if( lt == NULL )
924 ret = -1;
925 else
926 {
927 now->year = lt->tm_year + 1900;
928 now->mon = lt->tm_mon + 1;
929 now->day = lt->tm_mday;
930 now->hour = lt->tm_hour;
931 now->min = lt->tm_min;
932 now->sec = lt->tm_sec;
933 }
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200934
935#if defined(MBEDTLS_THREADING_C)
936 if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
937 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
938#endif
939
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +0200940 return( ret );
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100941}
Manuel Pégourié-Gonnard57e10d72015-06-22 18:59:21 +0200942#endif /* _WIN32 && !EFIX64 && !EFI32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200943
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100944/*
945 * Return 0 if before <= after, 1 otherwise
946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after )
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100948{
949 if( before->year > after->year )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200950 return( 1 );
951
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100952 if( before->year == after->year &&
953 before->mon > after->mon )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200954 return( 1 );
955
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100956 if( before->year == after->year &&
957 before->mon == after->mon &&
958 before->day > after->day )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200959 return( 1 );
960
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100961 if( before->year == after->year &&
962 before->mon == after->mon &&
963 before->day == after->day &&
964 before->hour > after->hour )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200965 return( 1 );
966
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100967 if( before->year == after->year &&
968 before->mon == after->mon &&
969 before->day == after->day &&
970 before->hour == after->hour &&
971 before->min > after->min )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200972 return( 1 );
973
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100974 if( before->year == after->year &&
975 before->mon == after->mon &&
976 before->day == after->day &&
977 before->hour == after->hour &&
978 before->min == after->min &&
979 before->sec > after->sec )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200980 return( 1 );
981
982 return( 0 );
983}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100984
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100985int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100986{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 mbedtls_x509_time now;
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100988
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200989 if( x509_get_current_time( &now ) != 0 )
Manuel Pégourié-Gonnarde7e89842015-06-22 19:15:32 +0200990 return( 1 );
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100991
992 return( x509_check_time( &now, to ) );
993}
994
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +0100995int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100996{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 mbedtls_x509_time now;
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100998
Manuel Pégourié-Gonnard864108d2015-05-29 10:11:03 +0200999 if( x509_get_current_time( &now ) != 0 )
Manuel Pégourié-Gonnarde7e89842015-06-22 19:15:32 +02001000 return( 1 );
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001001
1002 return( x509_check_time( from, &now ) );
1003}
1004
Manuel Pégourié-Gonnard60c793b2015-06-18 20:52:58 +02001005#else /* MBEDTLS_HAVE_TIME_DATE */
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001006
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01001007int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001008{
1009 ((void) to);
1010 return( 0 );
1011}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001012
Manuel Pégourié-Gonnardc730ed32015-06-02 10:38:50 +01001013int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +01001014{
1015 ((void) from);
1016 return( 0 );
1017}
Manuel Pégourié-Gonnard60c793b2015-06-18 20:52:58 +02001018#endif /* MBEDTLS_HAVE_TIME_DATE */
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020#if defined(MBEDTLS_SELF_TEST)
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001021
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00001022#include "mbedtls/x509_crt.h"
1023#include "mbedtls/certs.h"
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001024
1025/*
1026 * Checkup routine
1027 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028int mbedtls_x509_self_test( int verbose )
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001029{
Gilles Peskine5877c272017-05-05 18:56:30 +02001030#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001031 int ret;
Manuel Pégourié-Gonnarde6ef16f2015-05-11 19:54:43 +02001032 uint32_t flags;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 mbedtls_x509_crt cacert;
1034 mbedtls_x509_crt clicert;
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001035
1036 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001037 mbedtls_printf( " X.509 certificate load: " );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001038
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039 mbedtls_x509_crt_init( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001042 mbedtls_test_cli_crt_len );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001043 if( ret != 0 )
1044 {
1045 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 mbedtls_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001047
1048 return( ret );
1049 }
1050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001051 mbedtls_x509_crt_init( &cacert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001052
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001053 ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +02001054 mbedtls_test_ca_crt_len );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001055 if( ret != 0 )
1056 {
1057 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001058 mbedtls_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001059
1060 return( ret );
1061 }
1062
1063 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064 mbedtls_printf( "passed\n X.509 signature verify: ");
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001065
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001067 if( ret != 0 )
1068 {
1069 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 mbedtls_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001071
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001072 return( ret );
1073 }
1074
1075 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001076 mbedtls_printf( "passed\n\n");
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001077
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 mbedtls_x509_crt_free( &cacert );
1079 mbedtls_x509_crt_free( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001080
1081 return( 0 );
1082#else
1083 ((void) verbose);
Manuel Pégourié-Gonnard620ee192015-08-07 10:56:09 +02001084 return( 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001086}
1087
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088#endif /* MBEDTLS_SELF_TEST */
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001089
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090#endif /* MBEDTLS_X509_USE_C */