blob: dbc2e02764848514e4dcbb99838fd1fa2399ae24 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
2 * X.509 certificate and private key decoding
3 *
4 * Copyright (C) 2006-2013, Brainspark B.V.
5 *
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
37#include "polarssl/config.h"
38
39#if defined(POLARSSL_X509_USE_C)
40
41#include "polarssl/x509.h"
42#include "polarssl/asn1.h"
43#include "polarssl/oid.h"
44#if defined(POLARSSL_PEM_PARSE_C)
45#include "polarssl/pem.h"
46#endif
47
48#if defined(POLARSSL_MEMORY_C)
49#include "polarssl/memory.h"
50#else
51#define polarssl_malloc malloc
52#define polarssl_free free
53#endif
54
55#include <string.h>
56#include <stdlib.h>
Paul Bakkerfa6a6202013-10-28 18:48:30 +010057#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020058#include <windows.h>
59#else
60#include <time.h>
61#endif
62
Paul Bakkerfa6a6202013-10-28 18:48:30 +010063#if defined(EFIX64) || defined(EFI32)
64#include <stdio.h>
65#endif
66
Paul Bakker7c6b2c32013-09-16 13:49:26 +020067#if defined(POLARSSL_FS_IO)
68#include <stdio.h>
69#if !defined(_WIN32)
70#include <sys/types.h>
71#include <sys/stat.h>
72#include <dirent.h>
73#endif
74#endif
75
76/*
77 * CertificateSerialNumber ::= INTEGER
78 */
79int x509_get_serial( unsigned char **p, const unsigned char *end,
80 x509_buf *serial )
81{
82 int ret;
83
84 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +020085 return( POLARSSL_ERR_X509_INVALID_SERIAL +
Paul Bakker7c6b2c32013-09-16 13:49:26 +020086 POLARSSL_ERR_ASN1_OUT_OF_DATA );
87
88 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
89 **p != ASN1_INTEGER )
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_UNEXPECTED_TAG );
92
93 serial->tag = *(*p)++;
94
95 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +020096 return( POLARSSL_ERR_X509_INVALID_SERIAL + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020097
98 serial->p = *p;
99 *p += serial->len;
100
101 return( 0 );
102}
103
104/* Get an algorithm identifier without parameters (eg for signatures)
105 *
106 * AlgorithmIdentifier ::= SEQUENCE {
107 * algorithm OBJECT IDENTIFIER,
108 * parameters ANY DEFINED BY algorithm OPTIONAL }
109 */
110int x509_get_alg_null( unsigned char **p, const unsigned char *end,
111 x509_buf *alg )
112{
113 int ret;
114
115 if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200116 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200117
118 return( 0 );
119}
120
121/*
Manuel Pégourié-Gonnardb1d4eb12014-01-22 10:12:57 +0100122 * Parse an algorithm identifier with (optional) paramaters
123 */
124int x509_get_alg( unsigned char **p, const unsigned char *end,
125 x509_buf *alg, x509_buf *params )
126{
127 int ret;
128
129 if( ( ret = asn1_get_alg( p, end, alg, params ) ) != 0 )
130 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
131
132 return( 0 );
133}
134
Manuel Pégourié-Gonnardce7c6fd2014-01-24 14:37:29 +0100135#if defined(POLARSSL_RSASSA_PSS_CERTIFICATES)
Manuel Pégourié-Gonnardb1d4eb12014-01-22 10:12:57 +0100136/*
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100137 * HashAlgorithm ::= AlgorithmIdentifier
138 *
139 * AlgorithmIdentifier ::= SEQUENCE {
140 * algorithm OBJECT IDENTIFIER,
141 * parameters ANY DEFINED BY algorithm OPTIONAL }
142 *
143 * For HashAlgorithm, parameters MUST be NULL or absent.
144 */
145static int x509_get_hash_alg( const x509_buf *alg, md_type_t *md_alg )
146{
147 int ret;
148 unsigned char *p;
149 const unsigned char *end;
150 x509_buf md_oid;
151 size_t len;
152
153 /* Make sure we got a SEQUENCE and setup bounds */
154 if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
155 return( POLARSSL_ERR_X509_INVALID_ALG +
156 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
157
158 p = (unsigned char *) alg->p;
159 end = p + alg->len;
160
161 if( p >= end )
162 return( POLARSSL_ERR_X509_INVALID_ALG +
163 POLARSSL_ERR_ASN1_OUT_OF_DATA );
164
165 /* Parse md_oid */
166 md_oid.tag = *p;
167
168 if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 )
169 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
170
171 md_oid.p = p;
172 p += md_oid.len;
173
174 /* Get md_alg from md_oid */
175 if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
176 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
177
178 /* Make sure params is absent of NULL */
179 if( p == end )
180 return( 0 );
181
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100182 if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 || len != 0 )
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100183 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
184
185 if( p != end )
186 return( POLARSSL_ERR_X509_INVALID_ALG +
187 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
188
189 return( 0 );
190}
191
192/*
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100193 * RSASSA-PSS-params ::= SEQUENCE {
194 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
195 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
196 * saltLength [2] INTEGER DEFAULT 20,
197 * trailerField [3] INTEGER DEFAULT 1 }
198 * -- Note that the tags in this Sequence are explicit.
199 */
200int x509_get_rsassa_pss_params( const x509_buf *params,
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100201 md_type_t *md_alg, md_type_t *mgf_md,
202 int *salt_len, int *trailer_field )
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100203{
204 int ret;
205 unsigned char *p;
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100206 const unsigned char *end, *end2;
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100207 size_t len;
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100208 x509_buf alg_id, alg_params;
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100209
210 /* First set everything to defaults */
211 *md_alg = POLARSSL_MD_SHA1;
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100212 *mgf_md = POLARSSL_MD_SHA1;
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100213 *salt_len = 20;
214 *trailer_field = 1;
215
216 /* Make sure params is a SEQUENCE and setup bounds */
217 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
218 return( POLARSSL_ERR_X509_INVALID_ALG +
219 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
220
221 p = (unsigned char *) params->p;
222 end = p + params->len;
223
224 if( p == end )
225 return( 0 );
226
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100227 /*
228 * HashAlgorithm
229 */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100230 if( ( ret = asn1_get_tag( &p, end, &len,
231 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
232 {
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100233 end2 = p + len;
234
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100235 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100236 if( ( ret = x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100237 return( ret );
238
239 if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
240 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100241
242 if( p != end2 )
243 return( POLARSSL_ERR_X509_INVALID_ALG +
244 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100245 }
246 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
247 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
248
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100249 if( p == end )
250 return( 0 );
251
252 /*
253 * MaskGenAlgorithm
254 */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100255 if( ( ret = asn1_get_tag( &p, end, &len,
256 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
257 {
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100258 end2 = p + len;
259
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100260 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100261 if( ( ret = x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100262 return( ret );
263
264 /* Only MFG1 is recognised for now */
265 if( ! OID_CMP( OID_MGF1, &alg_id ) )
266 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE +
267 POLARSSL_ERR_OID_NOT_FOUND );
268
269 /* Parse HashAlgorithm */
270 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
271 return( ret );
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100272
273 if( p != end2 )
274 return( POLARSSL_ERR_X509_INVALID_ALG +
275 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100276 }
277 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
278 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
279
280 if( p == end )
281 return( 0 );
282
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100283 /*
284 * salt_len
285 */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100286 if( ( ret = asn1_get_tag( &p, end, &len,
287 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 )
288 {
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100289 end2 = p + len;
290
291 if( ( ret = asn1_get_int( &p, end2, salt_len ) ) != 0 )
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100292 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100293
294 if( p != end2 )
295 return( POLARSSL_ERR_X509_INVALID_ALG +
296 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100297 }
298 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
299 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
300
301 if( p == end )
302 return( 0 );
303
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100304 /*
305 * trailer_field
306 */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100307 if( ( ret = asn1_get_tag( &p, end, &len,
308 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 )
309 {
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100310 end2 = p + len;
311
312 if( ( ret = asn1_get_int( &p, end2, trailer_field ) ) != 0 )
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100313 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100314
315 if( p != end2 )
316 return( POLARSSL_ERR_X509_INVALID_ALG +
317 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100318 }
319 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
320 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
321
322 if( p != end )
323 return( POLARSSL_ERR_X509_INVALID_ALG +
324 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
325
326 return( 0 );
327}
Manuel Pégourié-Gonnardce7c6fd2014-01-24 14:37:29 +0100328#endif /* POLARSSL_RSASSA_PSS_CERTIFICATES */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100329
330/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200331 * AttributeTypeAndValue ::= SEQUENCE {
332 * type AttributeType,
333 * value AttributeValue }
334 *
335 * AttributeType ::= OBJECT IDENTIFIER
336 *
337 * AttributeValue ::= ANY DEFINED BY AttributeType
338 */
339static int x509_get_attr_type_value( unsigned char **p,
340 const unsigned char *end,
341 x509_name *cur )
342{
343 int ret;
344 size_t len;
345 x509_buf *oid;
346 x509_buf *val;
347
348 if( ( ret = asn1_get_tag( p, end, &len,
349 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200350 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200351
352 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200353 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200354 POLARSSL_ERR_ASN1_OUT_OF_DATA );
355
356 oid = &cur->oid;
357 oid->tag = **p;
358
359 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200360 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200361
362 oid->p = *p;
363 *p += oid->len;
364
365 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200366 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200367 POLARSSL_ERR_ASN1_OUT_OF_DATA );
368
369 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
370 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
371 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker51876562013-09-17 14:36:05 +0200372 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200373 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
374
375 val = &cur->val;
376 val->tag = *(*p)++;
377
378 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200379 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200380
381 val->p = *p;
382 *p += val->len;
383
384 cur->next = NULL;
385
386 return( 0 );
387}
388
389/*
390 * RelativeDistinguishedName ::=
391 * SET OF AttributeTypeAndValue
392 *
393 * AttributeTypeAndValue ::= SEQUENCE {
394 * type AttributeType,
395 * value AttributeValue }
396 *
397 * AttributeType ::= OBJECT IDENTIFIER
398 *
399 * AttributeValue ::= ANY DEFINED BY AttributeType
400 */
401int x509_get_name( unsigned char **p, const unsigned char *end,
402 x509_name *cur )
403{
404 int ret;
405 size_t len;
406 const unsigned char *end2;
407 x509_name *use;
408
409 if( ( ret = asn1_get_tag( p, end, &len,
410 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200411 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200412
413 end2 = end;
414 end = *p + len;
415 use = cur;
416
417 do
418 {
419 if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
420 return( ret );
421
422 if( *p != end )
423 {
424 use->next = (x509_name *) polarssl_malloc(
425 sizeof( x509_name ) );
426
427 if( use->next == NULL )
428 return( POLARSSL_ERR_X509_MALLOC_FAILED );
429
430 memset( use->next, 0, sizeof( x509_name ) );
431
432 use = use->next;
433 }
434 }
435 while( *p != end );
436
437 /*
438 * recurse until end of SEQUENCE is reached
439 */
440 if( *p == end2 )
441 return( 0 );
442
443 cur->next = (x509_name *) polarssl_malloc(
444 sizeof( x509_name ) );
445
446 if( cur->next == NULL )
447 return( POLARSSL_ERR_X509_MALLOC_FAILED );
448
449 memset( cur->next, 0, sizeof( x509_name ) );
450
451 return( x509_get_name( p, end2, cur->next ) );
452}
453
454/*
455 * Time ::= CHOICE {
456 * utcTime UTCTime,
457 * generalTime GeneralizedTime }
458 */
459int x509_get_time( unsigned char **p, const unsigned char *end,
460 x509_time *time )
461{
462 int ret;
463 size_t len;
464 char date[64];
465 unsigned char tag;
466
467 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200468 return( POLARSSL_ERR_X509_INVALID_DATE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200469 POLARSSL_ERR_ASN1_OUT_OF_DATA );
470
471 tag = **p;
472
473 if ( tag == ASN1_UTC_TIME )
474 {
475 (*p)++;
476 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200477
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200478 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200479 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200480
481 memset( date, 0, sizeof( date ) );
482 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
483 len : sizeof( date ) - 1 );
484
485 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
486 &time->year, &time->mon, &time->day,
487 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200488 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200489
490 time->year += 100 * ( time->year < 50 );
491 time->year += 1900;
492
493 *p += len;
494
495 return( 0 );
496 }
497 else if ( tag == ASN1_GENERALIZED_TIME )
498 {
499 (*p)++;
500 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200501
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200502 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200503 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200504
505 memset( date, 0, sizeof( date ) );
506 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
507 len : sizeof( date ) - 1 );
508
509 if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
510 &time->year, &time->mon, &time->day,
511 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200512 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200513
514 *p += len;
515
516 return( 0 );
517 }
518 else
Paul Bakker51876562013-09-17 14:36:05 +0200519 return( POLARSSL_ERR_X509_INVALID_DATE +
520 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200521}
522
523int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
524{
525 int ret;
526 size_t len;
527
528 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200529 return( POLARSSL_ERR_X509_INVALID_SIGNATURE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200530 POLARSSL_ERR_ASN1_OUT_OF_DATA );
531
532 sig->tag = **p;
533
534 if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200535 return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200536
537 sig->len = len;
538 sig->p = *p;
539
540 *p += len;
541
542 return( 0 );
543}
544
Manuel Pégourié-Gonnard5cac5832014-01-24 19:28:43 +0100545/*
546 * Get signature algorithm from alg OID and optional parameters
547 */
548int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params,
549 md_type_t *md_alg, pk_type_t *pk_alg )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200550{
Manuel Pégourié-Gonnard5cac5832014-01-24 19:28:43 +0100551 int ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200552
Manuel Pégourié-Gonnard5cac5832014-01-24 19:28:43 +0100553 if( ( ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 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
Manuel Pégourié-Gonnard5cac5832014-01-24 19:28:43 +0100556#if defined(POLARSSL_RSASSA_PSS_CERTIFICATES)
557 if( *pk_alg == POLARSSL_PK_RSASSA_PSS )
558 {
559 int salt_len, trailer_field;
560 md_type_t mgf_md;
561
562 /* Make sure params are valid */
563 ret = x509_get_rsassa_pss_params( sig_params,
564 md_alg, &mgf_md, &salt_len, &trailer_field );
565 if( ret != 0 )
566 return( ret );
567
568 }
569 else
570#endif
571 {
572 /* Make sure parameters are absent or NULL */
573 if( ( sig_params->tag != ASN1_NULL && sig_params->tag != 0 ) ||
574 sig_params->len != 0 )
575 return( POLARSSL_ERR_X509_INVALID_ALG );
576 }
577
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200578 return( 0 );
579}
580
581/*
582 * X.509 Extensions (No parsing of extensions, pointer should
583 * be either manually updated or extensions should be parsed!
584 */
585int x509_get_ext( unsigned char **p, const unsigned char *end,
586 x509_buf *ext, int tag )
587{
588 int ret;
589 size_t len;
590
591 if( *p == end )
592 return( 0 );
593
594 ext->tag = **p;
595
596 if( ( ret = asn1_get_tag( p, end, &ext->len,
597 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
598 return( ret );
599
600 ext->p = *p;
601 end = *p + ext->len;
602
603 /*
604 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
605 *
606 * Extension ::= SEQUENCE {
607 * extnID OBJECT IDENTIFIER,
608 * critical BOOLEAN DEFAULT FALSE,
609 * extnValue OCTET STRING }
610 */
611 if( ( ret = asn1_get_tag( p, end, &len,
612 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200613 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200614
615 if( end != *p + len )
Paul Bakker51876562013-09-17 14:36:05 +0200616 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200617 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
618
619 return( 0 );
620}
621
622#if defined(POLARSSL_FS_IO)
623/*
624 * Load all data from a file into a given buffer.
625 */
626int x509_load_file( const char *path, unsigned char **buf, size_t *n )
627{
628 FILE *f;
629 long size;
630
631 if( ( f = fopen( path, "rb" ) ) == NULL )
632 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
633
634 fseek( f, 0, SEEK_END );
635 if( ( size = ftell( f ) ) == -1 )
636 {
637 fclose( f );
638 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
639 }
640 fseek( f, 0, SEEK_SET );
641
642 *n = (size_t) size;
643
644 if( *n + 1 == 0 ||
645 ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
646 {
647 fclose( f );
648 return( POLARSSL_ERR_X509_MALLOC_FAILED );
649 }
650
651 if( fread( *buf, 1, *n, f ) != *n )
652 {
653 fclose( f );
654 polarssl_free( *buf );
655 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
656 }
657
658 fclose( f );
659
660 (*buf)[*n] = '\0';
661
662 return( 0 );
663}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200664#endif /* POLARSSL_FS_IO */
665
Paul Bakker6edcd412013-10-29 15:22:54 +0100666#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
667 !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200668#include <stdarg.h>
669
670#if !defined vsnprintf
671#define vsnprintf _vsnprintf
672#endif // vsnprintf
673
674/*
675 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
676 * Result value is not size of buffer needed, but -1 if no fit is possible.
677 *
678 * This fuction tries to 'fix' this by at least suggesting enlarging the
679 * size by 20.
680 */
681static int compat_snprintf(char *str, size_t size, const char *format, ...)
682{
683 va_list ap;
684 int res = -1;
685
686 va_start( ap, format );
687
688 res = vsnprintf( str, size, format, ap );
689
690 va_end( ap );
691
692 // No quick fix possible
693 if ( res < 0 )
694 return( (int) size + 20 );
695
696 return res;
697}
698
699#define snprintf compat_snprintf
700#endif
701
702#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
703
704#define SAFE_SNPRINTF() \
705{ \
706 if( ret == -1 ) \
707 return( -1 ); \
708 \
709 if ( (unsigned int) ret > n ) { \
710 p[n - 1] = '\0'; \
711 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
712 } \
713 \
714 n -= (unsigned int) ret; \
715 p += (unsigned int) ret; \
716}
717
718/*
719 * Store the name in printable form into buf; no more
720 * than size characters will be written
721 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200722int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200723{
724 int ret;
725 size_t i, n;
726 unsigned char c;
727 const x509_name *name;
728 const char *short_name = NULL;
729 char s[128], *p;
730
731 memset( s, 0, sizeof( s ) );
732
733 name = dn;
734 p = buf;
735 n = size;
736
737 while( name != NULL )
738 {
739 if( !name->oid.p )
740 {
741 name = name->next;
742 continue;
743 }
744
745 if( name != dn )
746 {
747 ret = snprintf( p, n, ", " );
748 SAFE_SNPRINTF();
749 }
750
751 ret = oid_get_attr_short_name( &name->oid, &short_name );
752
753 if( ret == 0 )
754 ret = snprintf( p, n, "%s=", short_name );
755 else
756 ret = snprintf( p, n, "\?\?=" );
757 SAFE_SNPRINTF();
758
759 for( i = 0; i < name->val.len; i++ )
760 {
761 if( i >= sizeof( s ) - 1 )
762 break;
763
764 c = name->val.p[i];
765 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
766 s[i] = '?';
767 else s[i] = c;
768 }
769 s[i] = '\0';
770 ret = snprintf( p, n, "%s", s );
771 SAFE_SNPRINTF();
772 name = name->next;
773 }
774
775 return( (int) ( size - n ) );
776}
777
778/*
779 * Store the serial in printable form into buf; no more
780 * than size characters will be written
781 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200782int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200783{
784 int ret;
785 size_t i, n, nr;
786 char *p;
787
788 p = buf;
789 n = size;
790
791 nr = ( serial->len <= 32 )
792 ? serial->len : 28;
793
794 for( i = 0; i < nr; i++ )
795 {
796 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
797 continue;
798
799 ret = snprintf( p, n, "%02X%s",
800 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
801 SAFE_SNPRINTF();
802 }
803
804 if( nr != serial->len )
805 {
806 ret = snprintf( p, n, "...." );
807 SAFE_SNPRINTF();
808 }
809
810 return( (int) ( size - n ) );
811}
812
813/*
814 * Helper for writing "RSA key size", "EC key size", etc
815 */
816int x509_key_size_helper( char *buf, size_t size, const char *name )
817{
818 char *p = buf;
819 size_t n = size;
820 int ret;
821
822 if( strlen( name ) + sizeof( " key size" ) > size )
823 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
824
825 ret = snprintf( p, n, "%s key size", name );
826 SAFE_SNPRINTF();
827
828 return( 0 );
829}
830
831/*
832 * Return an informational string describing the given OID
833 */
834const char *x509_oid_get_description( x509_buf *oid )
835{
836 const char *desc = NULL;
837 int ret;
838
839 ret = oid_get_extended_key_usage( oid, &desc );
840
841 if( ret != 0 )
842 return( NULL );
843
844 return( desc );
845}
846
847/* Return the x.y.z.... style numeric string for the given OID */
848int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
849{
850 return oid_get_numeric_string( buf, size, oid );
851}
852
853/*
854 * Return 0 if the x509_time is still valid, or 1 otherwise.
855 */
856#if defined(POLARSSL_HAVE_TIME)
Paul Bakker86d0c192013-09-18 11:11:02 +0200857int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200858{
859 int year, mon, day;
860 int hour, min, sec;
861
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100862#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200863 SYSTEMTIME st;
864
865 GetLocalTime(&st);
866
867 year = st.wYear;
868 mon = st.wMonth;
869 day = st.wDay;
870 hour = st.wHour;
871 min = st.wMinute;
872 sec = st.wSecond;
873#else
874 struct tm *lt;
875 time_t tt;
876
877 tt = time( NULL );
878 lt = localtime( &tt );
879
880 year = lt->tm_year + 1900;
881 mon = lt->tm_mon + 1;
882 day = lt->tm_mday;
883 hour = lt->tm_hour;
884 min = lt->tm_min;
885 sec = lt->tm_sec;
886#endif
887
888 if( year > to->year )
889 return( 1 );
890
891 if( year == to->year &&
892 mon > to->mon )
893 return( 1 );
894
895 if( year == to->year &&
896 mon == to->mon &&
897 day > to->day )
898 return( 1 );
899
900 if( year == to->year &&
901 mon == to->mon &&
902 day == to->day &&
903 hour > to->hour )
904 return( 1 );
905
906 if( year == to->year &&
907 mon == to->mon &&
908 day == to->day &&
909 hour == to->hour &&
910 min > to->min )
911 return( 1 );
912
913 if( year == to->year &&
914 mon == to->mon &&
915 day == to->day &&
916 hour == to->hour &&
917 min == to->min &&
918 sec > to->sec )
919 return( 1 );
920
921 return( 0 );
922}
923#else /* POLARSSL_HAVE_TIME */
Paul Bakker86d0c192013-09-18 11:11:02 +0200924int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200925{
926 ((void) to);
927 return( 0 );
928}
929#endif /* POLARSSL_HAVE_TIME */
930
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200931#if defined(POLARSSL_SELF_TEST)
932
933#include "polarssl/x509_crt.h"
934#include "polarssl/certs.h"
935
936/*
937 * Checkup routine
938 */
939int x509_self_test( int verbose )
940{
941#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
942 int ret;
943 int flags;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200944 x509_crt cacert;
945 x509_crt clicert;
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200946
947 if( verbose != 0 )
948 printf( " X.509 certificate load: " );
949
Paul Bakkerb6b09562013-09-18 14:17:41 +0200950 x509_crt_init( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200951
Paul Bakkerddf26b42013-09-18 13:46:23 +0200952 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
953 strlen( test_cli_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200954 if( ret != 0 )
955 {
956 if( verbose != 0 )
957 printf( "failed\n" );
958
959 return( ret );
960 }
961
Paul Bakkerb6b09562013-09-18 14:17:41 +0200962 x509_crt_init( &cacert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200963
Paul Bakkerddf26b42013-09-18 13:46:23 +0200964 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
965 strlen( test_ca_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200966 if( ret != 0 )
967 {
968 if( verbose != 0 )
969 printf( "failed\n" );
970
971 return( ret );
972 }
973
974 if( verbose != 0 )
975 printf( "passed\n X.509 signature verify: ");
976
Paul Bakkerddf26b42013-09-18 13:46:23 +0200977 ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200978 if( ret != 0 )
979 {
980 if( verbose != 0 )
981 printf( "failed\n" );
982
983 printf("ret = %d, &flags = %04x\n", ret, flags);
984
985 return( ret );
986 }
987
988 if( verbose != 0 )
989 printf( "passed\n\n");
990
991 x509_crt_free( &cacert );
992 x509_crt_free( &clicert );
993
994 return( 0 );
995#else
996 ((void) verbose);
997 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
998#endif
999}
1000
1001#endif
1002
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001003#endif /* POLARSSL_X509_USE_C */