blob: 3114076bd90bec8e4d0e71ab0cc582ada928edc7 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
2 * X.509 certificate and private key decoding
3 *
Paul Bakker7dc4c442014-02-01 22:50:26 +01004 * Copyright (C) 2006-2014, Brainspark B.V.
Paul Bakker7c6b2c32013-09-16 13:49:26 +02005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25/*
26 * The ITU-T X.509 standard defines a certificate format for PKI.
27 *
28 * http://www.ietf.org/rfc/rfc3279.txt
29 * http://www.ietf.org/rfc/rfc3280.txt
30 *
31 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
32 *
33 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
34 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
35 */
36
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020037#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020038#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020039#else
40#include POLARSSL_CONFIG_FILE
41#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020042
43#if defined(POLARSSL_X509_USE_C)
44
45#include "polarssl/x509.h"
46#include "polarssl/asn1.h"
47#include "polarssl/oid.h"
48#if defined(POLARSSL_PEM_PARSE_C)
49#include "polarssl/pem.h"
50#endif
51
Paul Bakker7dc4c442014-02-01 22:50:26 +010052#if defined(POLARSSL_PLATFORM_C)
53#include "polarssl/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020054#else
Paul Bakker7dc4c442014-02-01 22:50:26 +010055#define polarssl_printf printf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020056#define polarssl_malloc malloc
57#define polarssl_free free
58#endif
59
60#include <string.h>
61#include <stdlib.h>
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
Paul Bakkerfa6a6202013-10-28 18:48:30 +010068#if defined(EFIX64) || defined(EFI32)
69#include <stdio.h>
70#endif
71
Paul Bakker7c6b2c32013-09-16 13:49:26 +020072#if defined(POLARSSL_FS_IO)
73#include <stdio.h>
74#if !defined(_WIN32)
75#include <sys/types.h>
76#include <sys/stat.h>
77#include <dirent.h>
78#endif
79#endif
80
81/*
82 * CertificateSerialNumber ::= INTEGER
83 */
84int x509_get_serial( unsigned char **p, const unsigned char *end,
85 x509_buf *serial )
86{
87 int ret;
88
89 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +020090 return( POLARSSL_ERR_X509_INVALID_SERIAL +
Paul Bakker7c6b2c32013-09-16 13:49:26 +020091 POLARSSL_ERR_ASN1_OUT_OF_DATA );
92
93 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
94 **p != ASN1_INTEGER )
Paul Bakker51876562013-09-17 14:36:05 +020095 return( POLARSSL_ERR_X509_INVALID_SERIAL +
Paul Bakker7c6b2c32013-09-16 13:49:26 +020096 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
97
98 serial->tag = *(*p)++;
99
100 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200101 return( POLARSSL_ERR_X509_INVALID_SERIAL + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200102
103 serial->p = *p;
104 *p += serial->len;
105
106 return( 0 );
107}
108
109/* Get an algorithm identifier without parameters (eg for signatures)
110 *
111 * AlgorithmIdentifier ::= SEQUENCE {
112 * algorithm OBJECT IDENTIFIER,
113 * parameters ANY DEFINED BY algorithm OPTIONAL }
114 */
115int x509_get_alg_null( unsigned char **p, const unsigned char *end,
116 x509_buf *alg )
117{
118 int ret;
119
120 if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200121 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200122
123 return( 0 );
124}
125
126/*
Manuel Pégourié-Gonnard59a75d52014-01-22 10:12:57 +0100127 * Parse an algorithm identifier with (optional) paramaters
128 */
129int x509_get_alg( unsigned char **p, const unsigned char *end,
130 x509_buf *alg, x509_buf *params )
131{
132 int ret;
133
134 if( ( ret = asn1_get_alg( p, end, alg, params ) ) != 0 )
135 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
136
137 return( 0 );
138}
139
140/*
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100141 * HashAlgorithm ::= AlgorithmIdentifier
142 *
143 * AlgorithmIdentifier ::= SEQUENCE {
144 * algorithm OBJECT IDENTIFIER,
145 * parameters ANY DEFINED BY algorithm OPTIONAL }
146 *
147 * For HashAlgorithm, parameters MUST be NULL or absent.
148 */
149static int x509_get_hash_alg( const x509_buf *alg, md_type_t *md_alg )
150{
151 int ret;
152 unsigned char *p;
153 const unsigned char *end;
154 x509_buf md_oid;
155 size_t len;
156
157 /* Make sure we got a SEQUENCE and setup bounds */
158 if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
159 return( POLARSSL_ERR_X509_INVALID_ALG +
160 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
161
162 p = (unsigned char *) alg->p;
163 end = p + alg->len;
164
165 if( p >= end )
166 return( POLARSSL_ERR_X509_INVALID_ALG +
167 POLARSSL_ERR_ASN1_OUT_OF_DATA );
168
169 /* Parse md_oid */
170 md_oid.tag = *p;
171
172 if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 )
173 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
174
175 md_oid.p = p;
176 p += md_oid.len;
177
178 /* Get md_alg from md_oid */
179 if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
180 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
181
182 /* Make sure params is absent of NULL */
183 if( p == end )
184 return( 0 );
185
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100186 if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 || len != 0 )
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100187 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
188
189 if( p != end )
190 return( POLARSSL_ERR_X509_INVALID_ALG +
191 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
192
193 return( 0 );
194}
195
196/*
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100197 * RSASSA-PSS-params ::= SEQUENCE {
198 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
199 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
200 * saltLength [2] INTEGER DEFAULT 20,
201 * trailerField [3] INTEGER DEFAULT 1 }
202 * -- Note that the tags in this Sequence are explicit.
203 */
204int x509_get_rsassa_pss_params( const x509_buf *params,
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100205 md_type_t *md_alg, md_type_t *mgf_md,
206 int *salt_len, int *trailer_field )
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100207{
208 int ret;
209 unsigned char *p;
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100210 const unsigned char *end, *end2;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100211 size_t len;
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100212 x509_buf alg_id, alg_params;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100213
214 /* First set everything to defaults */
215 *md_alg = POLARSSL_MD_SHA1;
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100216 *mgf_md = POLARSSL_MD_SHA1;
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100217 *salt_len = 20;
218 *trailer_field = 1;
219
220 /* Make sure params is a SEQUENCE and setup bounds */
221 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
222 return( POLARSSL_ERR_X509_INVALID_ALG +
223 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
224
225 p = (unsigned char *) params->p;
226 end = p + params->len;
227
228 if( p == end )
229 return( 0 );
230
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100231 /*
232 * HashAlgorithm
233 */
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100234 if( ( ret = asn1_get_tag( &p, end, &len,
235 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
236 {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100237 end2 = p + len;
238
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100239 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100240 if( ( ret = x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100241 return( ret );
242
243 if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
244 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100245
246 if( p != end2 )
247 return( POLARSSL_ERR_X509_INVALID_ALG +
248 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100249 }
250 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
251 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
252
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100253 if( p == end )
254 return( 0 );
255
256 /*
257 * MaskGenAlgorithm
258 */
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100259 if( ( ret = asn1_get_tag( &p, end, &len,
260 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
261 {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100262 end2 = p + len;
263
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100264 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100265 if( ( ret = x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
Manuel Pégourié-Gonnarde76b7502014-01-23 19:15:29 +0100266 return( ret );
267
268 /* Only MFG1 is recognised for now */
269 if( ! OID_CMP( OID_MGF1, &alg_id ) )
270 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE +
271 POLARSSL_ERR_OID_NOT_FOUND );
272
273 /* Parse HashAlgorithm */
274 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
275 return( ret );
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100276
277 if( p != end2 )
278 return( POLARSSL_ERR_X509_INVALID_ALG +
279 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100280 }
281 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
282 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
283
284 if( p == end )
285 return( 0 );
286
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100287 /*
288 * salt_len
289 */
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100290 if( ( ret = asn1_get_tag( &p, end, &len,
291 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 )
292 {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100293 end2 = p + len;
294
295 if( ( ret = asn1_get_int( &p, end2, salt_len ) ) != 0 )
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100296 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100297
298 if( p != end2 )
299 return( POLARSSL_ERR_X509_INVALID_ALG +
300 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100301 }
302 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
303 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
304
305 if( p == end )
306 return( 0 );
307
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100308 /*
309 * trailer_field
310 */
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100311 if( ( ret = asn1_get_tag( &p, end, &len,
312 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 )
313 {
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100314 end2 = p + len;
315
316 if( ( ret = asn1_get_int( &p, end2, trailer_field ) ) != 0 )
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100317 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnard9c9cf5b2014-01-24 14:15:20 +0100318
319 if( p != end2 )
320 return( POLARSSL_ERR_X509_INVALID_ALG +
321 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardf346bab2014-01-23 16:24:44 +0100322 }
323 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
324 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
325
326 if( p != end )
327 return( POLARSSL_ERR_X509_INVALID_ALG +
328 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
329
330 return( 0 );
331}
332
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,
344 x509_name *cur )
345{
346 int ret;
347 size_t len;
348 x509_buf *oid;
349 x509_buf *val;
350
351 if( ( ret = asn1_get_tag( p, end, &len,
352 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200353 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200354
355 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200356 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200357 POLARSSL_ERR_ASN1_OUT_OF_DATA );
358
359 oid = &cur->oid;
360 oid->tag = **p;
361
362 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200363 return( POLARSSL_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 )
Paul Bakker51876562013-09-17 14:36:05 +0200369 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200370 POLARSSL_ERR_ASN1_OUT_OF_DATA );
371
372 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
373 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
374 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker51876562013-09-17 14:36:05 +0200375 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200376 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
377
378 val = &cur->val;
379 val->tag = *(*p)++;
380
381 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200382 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200383
384 val->p = *p;
385 *p += val->len;
386
387 cur->next = NULL;
388
389 return( 0 );
390}
391
392/*
393 * RelativeDistinguishedName ::=
394 * SET OF AttributeTypeAndValue
395 *
396 * AttributeTypeAndValue ::= SEQUENCE {
397 * type AttributeType,
398 * value AttributeValue }
399 *
400 * AttributeType ::= OBJECT IDENTIFIER
401 *
402 * AttributeValue ::= ANY DEFINED BY AttributeType
403 */
404int x509_get_name( unsigned char **p, const unsigned char *end,
405 x509_name *cur )
406{
407 int ret;
408 size_t len;
409 const unsigned char *end2;
410 x509_name *use;
411
412 if( ( ret = asn1_get_tag( p, end, &len,
413 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200414 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200415
416 end2 = end;
417 end = *p + len;
418 use = cur;
419
420 do
421 {
422 if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
423 return( ret );
424
425 if( *p != end )
426 {
427 use->next = (x509_name *) polarssl_malloc(
428 sizeof( x509_name ) );
429
430 if( use->next == NULL )
431 return( POLARSSL_ERR_X509_MALLOC_FAILED );
432
433 memset( use->next, 0, sizeof( x509_name ) );
434
435 use = use->next;
436 }
437 }
438 while( *p != end );
439
440 /*
441 * recurse until end of SEQUENCE is reached
442 */
443 if( *p == end2 )
444 return( 0 );
445
446 cur->next = (x509_name *) polarssl_malloc(
447 sizeof( x509_name ) );
448
449 if( cur->next == NULL )
450 return( POLARSSL_ERR_X509_MALLOC_FAILED );
451
452 memset( cur->next, 0, sizeof( x509_name ) );
453
454 return( x509_get_name( p, end2, cur->next ) );
455}
456
457/*
458 * Time ::= CHOICE {
459 * utcTime UTCTime,
460 * generalTime GeneralizedTime }
461 */
462int x509_get_time( unsigned char **p, const unsigned char *end,
463 x509_time *time )
464{
465 int ret;
466 size_t len;
467 char date[64];
468 unsigned char tag;
469
470 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200471 return( POLARSSL_ERR_X509_INVALID_DATE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200472 POLARSSL_ERR_ASN1_OUT_OF_DATA );
473
474 tag = **p;
475
476 if ( tag == ASN1_UTC_TIME )
477 {
478 (*p)++;
479 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200480
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200481 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200482 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200483
484 memset( date, 0, sizeof( date ) );
485 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
486 len : sizeof( date ) - 1 );
487
Manuel Pégourié-Gonnard9655e452014-04-11 12:29:49 +0200488 if( sscanf( date, "%2d%2d%2d%2d%2d%2dZ",
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200489 &time->year, &time->mon, &time->day,
490 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200491 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200492
493 time->year += 100 * ( time->year < 50 );
494 time->year += 1900;
495
496 *p += len;
497
498 return( 0 );
499 }
500 else if ( tag == ASN1_GENERALIZED_TIME )
501 {
502 (*p)++;
503 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200504
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200505 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200506 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200507
508 memset( date, 0, sizeof( date ) );
509 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
510 len : sizeof( date ) - 1 );
511
Manuel Pégourié-Gonnard9655e452014-04-11 12:29:49 +0200512 if( sscanf( date, "%4d%2d%2d%2d%2d%2dZ",
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200513 &time->year, &time->mon, &time->day,
514 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200515 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200516
517 *p += len;
518
519 return( 0 );
520 }
521 else
Paul Bakker51876562013-09-17 14:36:05 +0200522 return( POLARSSL_ERR_X509_INVALID_DATE +
523 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200524}
525
526int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
527{
528 int ret;
529 size_t len;
530
531 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200532 return( POLARSSL_ERR_X509_INVALID_SIGNATURE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200533 POLARSSL_ERR_ASN1_OUT_OF_DATA );
534
535 sig->tag = **p;
536
537 if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200538 return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200539
540 sig->len = len;
541 sig->p = *p;
542
543 *p += len;
544
545 return( 0 );
546}
547
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100548int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
549 pk_type_t *pk_alg )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200550{
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100551 int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200552
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100553 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200554 return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200555
556 return( 0 );
557}
558
559/*
560 * X.509 Extensions (No parsing of extensions, pointer should
561 * be either manually updated or extensions should be parsed!
562 */
563int x509_get_ext( unsigned char **p, const unsigned char *end,
564 x509_buf *ext, int tag )
565{
566 int ret;
567 size_t len;
568
569 if( *p == end )
570 return( 0 );
571
572 ext->tag = **p;
573
574 if( ( ret = asn1_get_tag( p, end, &ext->len,
575 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
576 return( ret );
577
578 ext->p = *p;
579 end = *p + ext->len;
580
581 /*
582 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
583 *
584 * Extension ::= SEQUENCE {
585 * extnID OBJECT IDENTIFIER,
586 * critical BOOLEAN DEFAULT FALSE,
587 * extnValue OCTET STRING }
588 */
589 if( ( ret = asn1_get_tag( p, end, &len,
590 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200591 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200592
593 if( end != *p + len )
Paul Bakker51876562013-09-17 14:36:05 +0200594 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200595 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
596
597 return( 0 );
598}
599
600#if defined(POLARSSL_FS_IO)
601/*
602 * Load all data from a file into a given buffer.
603 */
604int x509_load_file( const char *path, unsigned char **buf, size_t *n )
605{
606 FILE *f;
607 long size;
608
609 if( ( f = fopen( path, "rb" ) ) == NULL )
610 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
611
612 fseek( f, 0, SEEK_END );
613 if( ( size = ftell( f ) ) == -1 )
614 {
615 fclose( f );
616 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
617 }
618 fseek( f, 0, SEEK_SET );
619
620 *n = (size_t) size;
621
622 if( *n + 1 == 0 ||
623 ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
624 {
625 fclose( f );
626 return( POLARSSL_ERR_X509_MALLOC_FAILED );
627 }
628
629 if( fread( *buf, 1, *n, f ) != *n )
630 {
631 fclose( f );
632 polarssl_free( *buf );
633 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
634 }
635
636 fclose( f );
637
638 (*buf)[*n] = '\0';
639
640 return( 0 );
641}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200642#endif /* POLARSSL_FS_IO */
643
Paul Bakker6edcd412013-10-29 15:22:54 +0100644#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
645 !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200646#include <stdarg.h>
647
648#if !defined vsnprintf
649#define vsnprintf _vsnprintf
650#endif // vsnprintf
651
652/*
653 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
654 * Result value is not size of buffer needed, but -1 if no fit is possible.
655 *
656 * This fuction tries to 'fix' this by at least suggesting enlarging the
657 * size by 20.
658 */
659static int compat_snprintf(char *str, size_t size, const char *format, ...)
660{
661 va_list ap;
662 int res = -1;
663
664 va_start( ap, format );
665
666 res = vsnprintf( str, size, format, ap );
667
668 va_end( ap );
669
670 // No quick fix possible
671 if ( res < 0 )
672 return( (int) size + 20 );
673
674 return res;
675}
676
677#define snprintf compat_snprintf
Paul Bakker9af723c2014-05-01 13:03:14 +0200678#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200679
680#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
681
682#define SAFE_SNPRINTF() \
683{ \
684 if( ret == -1 ) \
685 return( -1 ); \
686 \
687 if ( (unsigned int) ret > n ) { \
688 p[n - 1] = '\0'; \
689 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
690 } \
691 \
692 n -= (unsigned int) ret; \
693 p += (unsigned int) ret; \
694}
695
696/*
697 * Store the name in printable form into buf; no more
698 * than size characters will be written
699 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200700int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200701{
702 int ret;
703 size_t i, n;
704 unsigned char c;
705 const x509_name *name;
706 const char *short_name = NULL;
707 char s[128], *p;
708
709 memset( s, 0, sizeof( s ) );
710
711 name = dn;
712 p = buf;
713 n = size;
714
715 while( name != NULL )
716 {
717 if( !name->oid.p )
718 {
719 name = name->next;
720 continue;
721 }
722
723 if( name != dn )
724 {
725 ret = snprintf( p, n, ", " );
726 SAFE_SNPRINTF();
727 }
728
729 ret = oid_get_attr_short_name( &name->oid, &short_name );
730
731 if( ret == 0 )
732 ret = snprintf( p, n, "%s=", short_name );
733 else
734 ret = snprintf( p, n, "\?\?=" );
735 SAFE_SNPRINTF();
736
737 for( i = 0; i < name->val.len; i++ )
738 {
739 if( i >= sizeof( s ) - 1 )
740 break;
741
742 c = name->val.p[i];
743 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
744 s[i] = '?';
745 else s[i] = c;
746 }
747 s[i] = '\0';
748 ret = snprintf( p, n, "%s", s );
749 SAFE_SNPRINTF();
750 name = name->next;
751 }
752
753 return( (int) ( size - n ) );
754}
755
756/*
757 * Store the serial in printable form into buf; no more
758 * than size characters will be written
759 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200760int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200761{
762 int ret;
763 size_t i, n, nr;
764 char *p;
765
766 p = buf;
767 n = size;
768
769 nr = ( serial->len <= 32 )
770 ? serial->len : 28;
771
772 for( i = 0; i < nr; i++ )
773 {
774 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
775 continue;
776
777 ret = snprintf( p, n, "%02X%s",
778 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
779 SAFE_SNPRINTF();
780 }
781
782 if( nr != serial->len )
783 {
784 ret = snprintf( p, n, "...." );
785 SAFE_SNPRINTF();
786 }
787
788 return( (int) ( size - n ) );
789}
790
791/*
792 * Helper for writing "RSA key size", "EC key size", etc
793 */
794int x509_key_size_helper( char *buf, size_t size, const char *name )
795{
796 char *p = buf;
797 size_t n = size;
798 int ret;
799
800 if( strlen( name ) + sizeof( " key size" ) > size )
801 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
802
803 ret = snprintf( p, n, "%s key size", name );
804 SAFE_SNPRINTF();
805
806 return( 0 );
807}
808
809/*
810 * Return an informational string describing the given OID
811 */
812const char *x509_oid_get_description( x509_buf *oid )
813{
814 const char *desc = NULL;
815 int ret;
816
817 ret = oid_get_extended_key_usage( oid, &desc );
818
819 if( ret != 0 )
820 return( NULL );
821
822 return( desc );
823}
824
825/* Return the x.y.z.... style numeric string for the given OID */
826int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
827{
828 return oid_get_numeric_string( buf, size, oid );
829}
830
831/*
832 * Return 0 if the x509_time is still valid, or 1 otherwise.
833 */
834#if defined(POLARSSL_HAVE_TIME)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200835
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100836static void x509_get_current_time( x509_time *now )
837{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100838#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200839 SYSTEMTIME st;
840
Manuel Pégourié-Gonnard0776a432014-04-11 12:25:45 +0200841 GetSystemTime(&st);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200842
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100843 now->year = st.wYear;
844 now->mon = st.wMonth;
845 now->day = st.wDay;
846 now->hour = st.wHour;
847 now->min = st.wMinute;
848 now->sec = st.wSecond;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200849#else
Paul Bakker5fff23b2014-03-26 15:34:54 +0100850 struct tm lt;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200851 time_t tt;
852
853 tt = time( NULL );
Manuel Pégourié-Gonnard0776a432014-04-11 12:25:45 +0200854 gmtime_r( &tt, &lt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200855
Paul Bakker5fff23b2014-03-26 15:34:54 +0100856 now->year = lt.tm_year + 1900;
857 now->mon = lt.tm_mon + 1;
858 now->day = lt.tm_mday;
859 now->hour = lt.tm_hour;
860 now->min = lt.tm_min;
861 now->sec = lt.tm_sec;
Paul Bakker9af723c2014-05-01 13:03:14 +0200862#endif /* _WIN32 && !EFIX64 && !EFI32 */
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100863}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200864
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100865/*
866 * Return 0 if before <= after, 1 otherwise
867 */
868static int x509_check_time( const x509_time *before, const x509_time *after )
869{
870 if( before->year > after->year )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200871 return( 1 );
872
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100873 if( before->year == after->year &&
874 before->mon > after->mon )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200875 return( 1 );
876
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100877 if( before->year == after->year &&
878 before->mon == after->mon &&
879 before->day > after->day )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200880 return( 1 );
881
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100882 if( before->year == after->year &&
883 before->mon == after->mon &&
884 before->day == after->day &&
885 before->hour > after->hour )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200886 return( 1 );
887
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100888 if( before->year == after->year &&
889 before->mon == after->mon &&
890 before->day == after->day &&
891 before->hour == after->hour &&
892 before->min > after->min )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200893 return( 1 );
894
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100895 if( before->year == after->year &&
896 before->mon == after->mon &&
897 before->day == after->day &&
898 before->hour == after->hour &&
899 before->min == after->min &&
900 before->sec > after->sec )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200901 return( 1 );
902
903 return( 0 );
904}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100905
906int x509_time_expired( const x509_time *to )
907{
908 x509_time now;
909
910 x509_get_current_time( &now );
911
912 return( x509_check_time( &now, to ) );
913}
914
915int x509_time_future( const x509_time *from )
916{
917 x509_time now;
918
919 x509_get_current_time( &now );
920
921 return( x509_check_time( from, &now ) );
922}
923
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200924#else /* POLARSSL_HAVE_TIME */
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100925
Paul Bakker86d0c192013-09-18 11:11:02 +0200926int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200927{
928 ((void) to);
929 return( 0 );
930}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100931
932int x509_time_future( const x509_time *from )
933{
934 ((void) from);
935 return( 0 );
936}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200937#endif /* POLARSSL_HAVE_TIME */
938
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200939#if defined(POLARSSL_SELF_TEST)
940
941#include "polarssl/x509_crt.h"
942#include "polarssl/certs.h"
943
944/*
945 * Checkup routine
946 */
947int x509_self_test( int verbose )
948{
Manuel Pégourié-Gonnard3d413702014-04-29 15:29:41 +0200949#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_SHA1_C)
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200950 int ret;
951 int flags;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200952 x509_crt cacert;
953 x509_crt clicert;
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200954
955 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100956 polarssl_printf( " X.509 certificate load: " );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200957
Paul Bakkerb6b09562013-09-18 14:17:41 +0200958 x509_crt_init( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200959
Paul Bakkerddf26b42013-09-18 13:46:23 +0200960 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
961 strlen( test_cli_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200962 if( ret != 0 )
963 {
964 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100965 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200966
967 return( ret );
968 }
969
Paul Bakkerb6b09562013-09-18 14:17:41 +0200970 x509_crt_init( &cacert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200971
Paul Bakkerddf26b42013-09-18 13:46:23 +0200972 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
973 strlen( test_ca_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200974 if( ret != 0 )
975 {
976 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100977 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200978
979 return( ret );
980 }
981
982 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100983 polarssl_printf( "passed\n X.509 signature verify: ");
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200984
Paul Bakkerddf26b42013-09-18 13:46:23 +0200985 ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200986 if( ret != 0 )
987 {
988 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100989 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200990
Paul Bakker7dc4c442014-02-01 22:50:26 +0100991 polarssl_printf("ret = %d, &flags = %04x\n", ret, flags);
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200992
993 return( ret );
994 }
995
996 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100997 polarssl_printf( "passed\n\n");
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200998
999 x509_crt_free( &cacert );
1000 x509_crt_free( &clicert );
1001
1002 return( 0 );
1003#else
1004 ((void) verbose);
1005 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker9af723c2014-05-01 13:03:14 +02001006#endif /* POLARSSL_CERTS_C && POLARSSL_SHA1_C */
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001007}
1008
Paul Bakker9af723c2014-05-01 13:03:14 +02001009#endif /* POLARSSL_SELF_TEST */
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001010
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001011#endif /* POLARSSL_X509_USE_C */