blob: 1a5f98a1b152c59eab150e5de8e3e72a02e3b973 [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
545int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
546 pk_type_t *pk_alg )
547{
548 int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
549
550 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200551 return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200552
553 return( 0 );
554}
555
556/*
557 * X.509 Extensions (No parsing of extensions, pointer should
558 * be either manually updated or extensions should be parsed!
559 */
560int x509_get_ext( unsigned char **p, const unsigned char *end,
561 x509_buf *ext, int tag )
562{
563 int ret;
564 size_t len;
565
566 if( *p == end )
567 return( 0 );
568
569 ext->tag = **p;
570
571 if( ( ret = asn1_get_tag( p, end, &ext->len,
572 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
573 return( ret );
574
575 ext->p = *p;
576 end = *p + ext->len;
577
578 /*
579 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
580 *
581 * Extension ::= SEQUENCE {
582 * extnID OBJECT IDENTIFIER,
583 * critical BOOLEAN DEFAULT FALSE,
584 * extnValue OCTET STRING }
585 */
586 if( ( ret = asn1_get_tag( p, end, &len,
587 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200588 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200589
590 if( end != *p + len )
Paul Bakker51876562013-09-17 14:36:05 +0200591 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200592 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
593
594 return( 0 );
595}
596
597#if defined(POLARSSL_FS_IO)
598/*
599 * Load all data from a file into a given buffer.
600 */
601int x509_load_file( const char *path, unsigned char **buf, size_t *n )
602{
603 FILE *f;
604 long size;
605
606 if( ( f = fopen( path, "rb" ) ) == NULL )
607 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
608
609 fseek( f, 0, SEEK_END );
610 if( ( size = ftell( f ) ) == -1 )
611 {
612 fclose( f );
613 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
614 }
615 fseek( f, 0, SEEK_SET );
616
617 *n = (size_t) size;
618
619 if( *n + 1 == 0 ||
620 ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
621 {
622 fclose( f );
623 return( POLARSSL_ERR_X509_MALLOC_FAILED );
624 }
625
626 if( fread( *buf, 1, *n, f ) != *n )
627 {
628 fclose( f );
629 polarssl_free( *buf );
630 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
631 }
632
633 fclose( f );
634
635 (*buf)[*n] = '\0';
636
637 return( 0 );
638}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200639#endif /* POLARSSL_FS_IO */
640
Paul Bakker6edcd412013-10-29 15:22:54 +0100641#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
642 !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200643#include <stdarg.h>
644
645#if !defined vsnprintf
646#define vsnprintf _vsnprintf
647#endif // vsnprintf
648
649/*
650 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
651 * Result value is not size of buffer needed, but -1 if no fit is possible.
652 *
653 * This fuction tries to 'fix' this by at least suggesting enlarging the
654 * size by 20.
655 */
656static int compat_snprintf(char *str, size_t size, const char *format, ...)
657{
658 va_list ap;
659 int res = -1;
660
661 va_start( ap, format );
662
663 res = vsnprintf( str, size, format, ap );
664
665 va_end( ap );
666
667 // No quick fix possible
668 if ( res < 0 )
669 return( (int) size + 20 );
670
671 return res;
672}
673
674#define snprintf compat_snprintf
675#endif
676
677#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
678
679#define SAFE_SNPRINTF() \
680{ \
681 if( ret == -1 ) \
682 return( -1 ); \
683 \
684 if ( (unsigned int) ret > n ) { \
685 p[n - 1] = '\0'; \
686 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
687 } \
688 \
689 n -= (unsigned int) ret; \
690 p += (unsigned int) ret; \
691}
692
693/*
694 * Store the name in printable form into buf; no more
695 * than size characters will be written
696 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200697int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200698{
699 int ret;
700 size_t i, n;
701 unsigned char c;
702 const x509_name *name;
703 const char *short_name = NULL;
704 char s[128], *p;
705
706 memset( s, 0, sizeof( s ) );
707
708 name = dn;
709 p = buf;
710 n = size;
711
712 while( name != NULL )
713 {
714 if( !name->oid.p )
715 {
716 name = name->next;
717 continue;
718 }
719
720 if( name != dn )
721 {
722 ret = snprintf( p, n, ", " );
723 SAFE_SNPRINTF();
724 }
725
726 ret = oid_get_attr_short_name( &name->oid, &short_name );
727
728 if( ret == 0 )
729 ret = snprintf( p, n, "%s=", short_name );
730 else
731 ret = snprintf( p, n, "\?\?=" );
732 SAFE_SNPRINTF();
733
734 for( i = 0; i < name->val.len; i++ )
735 {
736 if( i >= sizeof( s ) - 1 )
737 break;
738
739 c = name->val.p[i];
740 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
741 s[i] = '?';
742 else s[i] = c;
743 }
744 s[i] = '\0';
745 ret = snprintf( p, n, "%s", s );
746 SAFE_SNPRINTF();
747 name = name->next;
748 }
749
750 return( (int) ( size - n ) );
751}
752
753/*
754 * Store the serial in printable form into buf; no more
755 * than size characters will be written
756 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200757int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200758{
759 int ret;
760 size_t i, n, nr;
761 char *p;
762
763 p = buf;
764 n = size;
765
766 nr = ( serial->len <= 32 )
767 ? serial->len : 28;
768
769 for( i = 0; i < nr; i++ )
770 {
771 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
772 continue;
773
774 ret = snprintf( p, n, "%02X%s",
775 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
776 SAFE_SNPRINTF();
777 }
778
779 if( nr != serial->len )
780 {
781 ret = snprintf( p, n, "...." );
782 SAFE_SNPRINTF();
783 }
784
785 return( (int) ( size - n ) );
786}
787
788/*
789 * Helper for writing "RSA key size", "EC key size", etc
790 */
791int x509_key_size_helper( char *buf, size_t size, const char *name )
792{
793 char *p = buf;
794 size_t n = size;
795 int ret;
796
797 if( strlen( name ) + sizeof( " key size" ) > size )
798 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
799
800 ret = snprintf( p, n, "%s key size", name );
801 SAFE_SNPRINTF();
802
803 return( 0 );
804}
805
806/*
807 * Return an informational string describing the given OID
808 */
809const char *x509_oid_get_description( x509_buf *oid )
810{
811 const char *desc = NULL;
812 int ret;
813
814 ret = oid_get_extended_key_usage( oid, &desc );
815
816 if( ret != 0 )
817 return( NULL );
818
819 return( desc );
820}
821
822/* Return the x.y.z.... style numeric string for the given OID */
823int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
824{
825 return oid_get_numeric_string( buf, size, oid );
826}
827
828/*
829 * Return 0 if the x509_time is still valid, or 1 otherwise.
830 */
831#if defined(POLARSSL_HAVE_TIME)
Paul Bakker86d0c192013-09-18 11:11:02 +0200832int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200833{
834 int year, mon, day;
835 int hour, min, sec;
836
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100837#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200838 SYSTEMTIME st;
839
840 GetLocalTime(&st);
841
842 year = st.wYear;
843 mon = st.wMonth;
844 day = st.wDay;
845 hour = st.wHour;
846 min = st.wMinute;
847 sec = st.wSecond;
848#else
849 struct tm *lt;
850 time_t tt;
851
852 tt = time( NULL );
853 lt = localtime( &tt );
854
855 year = lt->tm_year + 1900;
856 mon = lt->tm_mon + 1;
857 day = lt->tm_mday;
858 hour = lt->tm_hour;
859 min = lt->tm_min;
860 sec = lt->tm_sec;
861#endif
862
863 if( year > to->year )
864 return( 1 );
865
866 if( year == to->year &&
867 mon > to->mon )
868 return( 1 );
869
870 if( year == to->year &&
871 mon == to->mon &&
872 day > to->day )
873 return( 1 );
874
875 if( year == to->year &&
876 mon == to->mon &&
877 day == to->day &&
878 hour > to->hour )
879 return( 1 );
880
881 if( year == to->year &&
882 mon == to->mon &&
883 day == to->day &&
884 hour == to->hour &&
885 min > to->min )
886 return( 1 );
887
888 if( year == to->year &&
889 mon == to->mon &&
890 day == to->day &&
891 hour == to->hour &&
892 min == to->min &&
893 sec > to->sec )
894 return( 1 );
895
896 return( 0 );
897}
898#else /* POLARSSL_HAVE_TIME */
Paul Bakker86d0c192013-09-18 11:11:02 +0200899int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200900{
901 ((void) to);
902 return( 0 );
903}
904#endif /* POLARSSL_HAVE_TIME */
905
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200906#if defined(POLARSSL_SELF_TEST)
907
908#include "polarssl/x509_crt.h"
909#include "polarssl/certs.h"
910
911/*
912 * Checkup routine
913 */
914int x509_self_test( int verbose )
915{
916#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
917 int ret;
918 int flags;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200919 x509_crt cacert;
920 x509_crt clicert;
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200921
922 if( verbose != 0 )
923 printf( " X.509 certificate load: " );
924
Paul Bakkerb6b09562013-09-18 14:17:41 +0200925 x509_crt_init( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200926
Paul Bakkerddf26b42013-09-18 13:46:23 +0200927 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
928 strlen( test_cli_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200929 if( ret != 0 )
930 {
931 if( verbose != 0 )
932 printf( "failed\n" );
933
934 return( ret );
935 }
936
Paul Bakkerb6b09562013-09-18 14:17:41 +0200937 x509_crt_init( &cacert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200938
Paul Bakkerddf26b42013-09-18 13:46:23 +0200939 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
940 strlen( test_ca_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200941 if( ret != 0 )
942 {
943 if( verbose != 0 )
944 printf( "failed\n" );
945
946 return( ret );
947 }
948
949 if( verbose != 0 )
950 printf( "passed\n X.509 signature verify: ");
951
Paul Bakkerddf26b42013-09-18 13:46:23 +0200952 ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200953 if( ret != 0 )
954 {
955 if( verbose != 0 )
956 printf( "failed\n" );
957
958 printf("ret = %d, &flags = %04x\n", ret, flags);
959
960 return( ret );
961 }
962
963 if( verbose != 0 )
964 printf( "passed\n\n");
965
966 x509_crt_free( &cacert );
967 x509_crt_free( &clicert );
968
969 return( 0 );
970#else
971 ((void) verbose);
972 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
973#endif
974}
975
976#endif
977
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200978#endif /* POLARSSL_X509_USE_C */