blob: 2f7d32c8e9841b58203ee83d61342ffb48920515 [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
135/*
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100136 * HashAlgorithm ::= AlgorithmIdentifier
137 *
138 * AlgorithmIdentifier ::= SEQUENCE {
139 * algorithm OBJECT IDENTIFIER,
140 * parameters ANY DEFINED BY algorithm OPTIONAL }
141 *
142 * For HashAlgorithm, parameters MUST be NULL or absent.
143 */
144static int x509_get_hash_alg( const x509_buf *alg, md_type_t *md_alg )
145{
146 int ret;
147 unsigned char *p;
148 const unsigned char *end;
149 x509_buf md_oid;
150 size_t len;
151
152 /* Make sure we got a SEQUENCE and setup bounds */
153 if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
154 return( POLARSSL_ERR_X509_INVALID_ALG +
155 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
156
157 p = (unsigned char *) alg->p;
158 end = p + alg->len;
159
160 if( p >= end )
161 return( POLARSSL_ERR_X509_INVALID_ALG +
162 POLARSSL_ERR_ASN1_OUT_OF_DATA );
163
164 /* Parse md_oid */
165 md_oid.tag = *p;
166
167 if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 )
168 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
169
170 md_oid.p = p;
171 p += md_oid.len;
172
173 /* Get md_alg from md_oid */
174 if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
175 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
176
177 /* Make sure params is absent of NULL */
178 if( p == end )
179 return( 0 );
180
181 if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 )
182 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
183
184 if( p != end )
185 return( POLARSSL_ERR_X509_INVALID_ALG +
186 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
187
188 return( 0 );
189}
190
191/*
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100192 * RSASSA-PSS-params ::= SEQUENCE {
193 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
194 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
195 * saltLength [2] INTEGER DEFAULT 20,
196 * trailerField [3] INTEGER DEFAULT 1 }
197 * -- Note that the tags in this Sequence are explicit.
198 */
199int x509_get_rsassa_pss_params( const x509_buf *params,
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100200 md_type_t *md_alg, md_type_t *mgf_md,
201 int *salt_len, int *trailer_field )
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100202{
203 int ret;
204 unsigned char *p;
205 const unsigned char *end;
206 size_t len;
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100207 x509_buf alg_id, alg_params;
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100208
209 /* First set everything to defaults */
210 *md_alg = POLARSSL_MD_SHA1;
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100211 *mgf_md = POLARSSL_MD_SHA1;
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100212 *salt_len = 20;
213 *trailer_field = 1;
214
215 /* Make sure params is a SEQUENCE and setup bounds */
216 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
217 return( POLARSSL_ERR_X509_INVALID_ALG +
218 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
219
220 p = (unsigned char *) params->p;
221 end = p + params->len;
222
223 if( p == end )
224 return( 0 );
225
226 if( ( ret = asn1_get_tag( &p, end, &len,
227 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
228 {
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100229 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
230 if( ( ret = x509_get_alg_null( &p, p + len, &alg_id ) ) != 0 )
231 return( ret );
232
233 if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
234 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100235 }
236 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
237 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
238
239 if( ( ret = asn1_get_tag( &p, end, &len,
240 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
241 {
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100242 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
243 if( ( ret = x509_get_alg( &p, p + len, &alg_id, &alg_params ) ) != 0 )
244 return( ret );
245
246 /* Only MFG1 is recognised for now */
247 if( ! OID_CMP( OID_MGF1, &alg_id ) )
248 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE +
249 POLARSSL_ERR_OID_NOT_FOUND );
250
251 /* Parse HashAlgorithm */
252 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
253 return( ret );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100254 }
255 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
256 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
257
258 if( p == end )
259 return( 0 );
260
261 if( ( ret = asn1_get_tag( &p, end, &len,
262 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 )
263 {
264 /* salt_len */
265 if( ( ret = asn1_get_int( &p, p + len, salt_len ) ) != 0 )
266 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
267 }
268 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
269 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
270
271 if( p == end )
272 return( 0 );
273
274 if( ( ret = asn1_get_tag( &p, end, &len,
275 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 )
276 {
277 /* trailer_field */
278 if( ( ret = asn1_get_int( &p, p + len, trailer_field ) ) != 0 )
279 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
280 }
281 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
282 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
283
284 if( p != end )
285 return( POLARSSL_ERR_X509_INVALID_ALG +
286 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
287
288 return( 0 );
289}
290
291/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200292 * AttributeTypeAndValue ::= SEQUENCE {
293 * type AttributeType,
294 * value AttributeValue }
295 *
296 * AttributeType ::= OBJECT IDENTIFIER
297 *
298 * AttributeValue ::= ANY DEFINED BY AttributeType
299 */
300static int x509_get_attr_type_value( unsigned char **p,
301 const unsigned char *end,
302 x509_name *cur )
303{
304 int ret;
305 size_t len;
306 x509_buf *oid;
307 x509_buf *val;
308
309 if( ( ret = asn1_get_tag( p, end, &len,
310 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200311 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200312
313 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200314 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200315 POLARSSL_ERR_ASN1_OUT_OF_DATA );
316
317 oid = &cur->oid;
318 oid->tag = **p;
319
320 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200321 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200322
323 oid->p = *p;
324 *p += oid->len;
325
326 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200327 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200328 POLARSSL_ERR_ASN1_OUT_OF_DATA );
329
330 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
331 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
332 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker51876562013-09-17 14:36:05 +0200333 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200334 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
335
336 val = &cur->val;
337 val->tag = *(*p)++;
338
339 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200340 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200341
342 val->p = *p;
343 *p += val->len;
344
345 cur->next = NULL;
346
347 return( 0 );
348}
349
350/*
351 * RelativeDistinguishedName ::=
352 * SET OF AttributeTypeAndValue
353 *
354 * AttributeTypeAndValue ::= SEQUENCE {
355 * type AttributeType,
356 * value AttributeValue }
357 *
358 * AttributeType ::= OBJECT IDENTIFIER
359 *
360 * AttributeValue ::= ANY DEFINED BY AttributeType
361 */
362int x509_get_name( unsigned char **p, const unsigned char *end,
363 x509_name *cur )
364{
365 int ret;
366 size_t len;
367 const unsigned char *end2;
368 x509_name *use;
369
370 if( ( ret = asn1_get_tag( p, end, &len,
371 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200372 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200373
374 end2 = end;
375 end = *p + len;
376 use = cur;
377
378 do
379 {
380 if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
381 return( ret );
382
383 if( *p != end )
384 {
385 use->next = (x509_name *) polarssl_malloc(
386 sizeof( x509_name ) );
387
388 if( use->next == NULL )
389 return( POLARSSL_ERR_X509_MALLOC_FAILED );
390
391 memset( use->next, 0, sizeof( x509_name ) );
392
393 use = use->next;
394 }
395 }
396 while( *p != end );
397
398 /*
399 * recurse until end of SEQUENCE is reached
400 */
401 if( *p == end2 )
402 return( 0 );
403
404 cur->next = (x509_name *) polarssl_malloc(
405 sizeof( x509_name ) );
406
407 if( cur->next == NULL )
408 return( POLARSSL_ERR_X509_MALLOC_FAILED );
409
410 memset( cur->next, 0, sizeof( x509_name ) );
411
412 return( x509_get_name( p, end2, cur->next ) );
413}
414
415/*
416 * Time ::= CHOICE {
417 * utcTime UTCTime,
418 * generalTime GeneralizedTime }
419 */
420int x509_get_time( unsigned char **p, const unsigned char *end,
421 x509_time *time )
422{
423 int ret;
424 size_t len;
425 char date[64];
426 unsigned char tag;
427
428 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200429 return( POLARSSL_ERR_X509_INVALID_DATE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200430 POLARSSL_ERR_ASN1_OUT_OF_DATA );
431
432 tag = **p;
433
434 if ( tag == ASN1_UTC_TIME )
435 {
436 (*p)++;
437 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200438
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200439 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200440 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200441
442 memset( date, 0, sizeof( date ) );
443 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
444 len : sizeof( date ) - 1 );
445
446 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
447 &time->year, &time->mon, &time->day,
448 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200449 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200450
451 time->year += 100 * ( time->year < 50 );
452 time->year += 1900;
453
454 *p += len;
455
456 return( 0 );
457 }
458 else if ( tag == ASN1_GENERALIZED_TIME )
459 {
460 (*p)++;
461 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200462
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200463 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200464 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200465
466 memset( date, 0, sizeof( date ) );
467 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
468 len : sizeof( date ) - 1 );
469
470 if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
471 &time->year, &time->mon, &time->day,
472 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200473 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200474
475 *p += len;
476
477 return( 0 );
478 }
479 else
Paul Bakker51876562013-09-17 14:36:05 +0200480 return( POLARSSL_ERR_X509_INVALID_DATE +
481 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200482}
483
484int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
485{
486 int ret;
487 size_t len;
488
489 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200490 return( POLARSSL_ERR_X509_INVALID_SIGNATURE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200491 POLARSSL_ERR_ASN1_OUT_OF_DATA );
492
493 sig->tag = **p;
494
495 if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200496 return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200497
498 sig->len = len;
499 sig->p = *p;
500
501 *p += len;
502
503 return( 0 );
504}
505
506int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
507 pk_type_t *pk_alg )
508{
509 int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
510
511 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200512 return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200513
514 return( 0 );
515}
516
517/*
518 * X.509 Extensions (No parsing of extensions, pointer should
519 * be either manually updated or extensions should be parsed!
520 */
521int x509_get_ext( unsigned char **p, const unsigned char *end,
522 x509_buf *ext, int tag )
523{
524 int ret;
525 size_t len;
526
527 if( *p == end )
528 return( 0 );
529
530 ext->tag = **p;
531
532 if( ( ret = asn1_get_tag( p, end, &ext->len,
533 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
534 return( ret );
535
536 ext->p = *p;
537 end = *p + ext->len;
538
539 /*
540 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
541 *
542 * Extension ::= SEQUENCE {
543 * extnID OBJECT IDENTIFIER,
544 * critical BOOLEAN DEFAULT FALSE,
545 * extnValue OCTET STRING }
546 */
547 if( ( ret = asn1_get_tag( p, end, &len,
548 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200549 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200550
551 if( end != *p + len )
Paul Bakker51876562013-09-17 14:36:05 +0200552 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200553 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
554
555 return( 0 );
556}
557
558#if defined(POLARSSL_FS_IO)
559/*
560 * Load all data from a file into a given buffer.
561 */
562int x509_load_file( const char *path, unsigned char **buf, size_t *n )
563{
564 FILE *f;
565 long size;
566
567 if( ( f = fopen( path, "rb" ) ) == NULL )
568 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
569
570 fseek( f, 0, SEEK_END );
571 if( ( size = ftell( f ) ) == -1 )
572 {
573 fclose( f );
574 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
575 }
576 fseek( f, 0, SEEK_SET );
577
578 *n = (size_t) size;
579
580 if( *n + 1 == 0 ||
581 ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
582 {
583 fclose( f );
584 return( POLARSSL_ERR_X509_MALLOC_FAILED );
585 }
586
587 if( fread( *buf, 1, *n, f ) != *n )
588 {
589 fclose( f );
590 polarssl_free( *buf );
591 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
592 }
593
594 fclose( f );
595
596 (*buf)[*n] = '\0';
597
598 return( 0 );
599}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200600#endif /* POLARSSL_FS_IO */
601
Paul Bakker6edcd412013-10-29 15:22:54 +0100602#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
603 !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200604#include <stdarg.h>
605
606#if !defined vsnprintf
607#define vsnprintf _vsnprintf
608#endif // vsnprintf
609
610/*
611 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
612 * Result value is not size of buffer needed, but -1 if no fit is possible.
613 *
614 * This fuction tries to 'fix' this by at least suggesting enlarging the
615 * size by 20.
616 */
617static int compat_snprintf(char *str, size_t size, const char *format, ...)
618{
619 va_list ap;
620 int res = -1;
621
622 va_start( ap, format );
623
624 res = vsnprintf( str, size, format, ap );
625
626 va_end( ap );
627
628 // No quick fix possible
629 if ( res < 0 )
630 return( (int) size + 20 );
631
632 return res;
633}
634
635#define snprintf compat_snprintf
636#endif
637
638#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
639
640#define SAFE_SNPRINTF() \
641{ \
642 if( ret == -1 ) \
643 return( -1 ); \
644 \
645 if ( (unsigned int) ret > n ) { \
646 p[n - 1] = '\0'; \
647 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
648 } \
649 \
650 n -= (unsigned int) ret; \
651 p += (unsigned int) ret; \
652}
653
654/*
655 * Store the name in printable form into buf; no more
656 * than size characters will be written
657 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200658int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200659{
660 int ret;
661 size_t i, n;
662 unsigned char c;
663 const x509_name *name;
664 const char *short_name = NULL;
665 char s[128], *p;
666
667 memset( s, 0, sizeof( s ) );
668
669 name = dn;
670 p = buf;
671 n = size;
672
673 while( name != NULL )
674 {
675 if( !name->oid.p )
676 {
677 name = name->next;
678 continue;
679 }
680
681 if( name != dn )
682 {
683 ret = snprintf( p, n, ", " );
684 SAFE_SNPRINTF();
685 }
686
687 ret = oid_get_attr_short_name( &name->oid, &short_name );
688
689 if( ret == 0 )
690 ret = snprintf( p, n, "%s=", short_name );
691 else
692 ret = snprintf( p, n, "\?\?=" );
693 SAFE_SNPRINTF();
694
695 for( i = 0; i < name->val.len; i++ )
696 {
697 if( i >= sizeof( s ) - 1 )
698 break;
699
700 c = name->val.p[i];
701 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
702 s[i] = '?';
703 else s[i] = c;
704 }
705 s[i] = '\0';
706 ret = snprintf( p, n, "%s", s );
707 SAFE_SNPRINTF();
708 name = name->next;
709 }
710
711 return( (int) ( size - n ) );
712}
713
714/*
715 * Store the serial in printable form into buf; no more
716 * than size characters will be written
717 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200718int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200719{
720 int ret;
721 size_t i, n, nr;
722 char *p;
723
724 p = buf;
725 n = size;
726
727 nr = ( serial->len <= 32 )
728 ? serial->len : 28;
729
730 for( i = 0; i < nr; i++ )
731 {
732 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
733 continue;
734
735 ret = snprintf( p, n, "%02X%s",
736 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
737 SAFE_SNPRINTF();
738 }
739
740 if( nr != serial->len )
741 {
742 ret = snprintf( p, n, "...." );
743 SAFE_SNPRINTF();
744 }
745
746 return( (int) ( size - n ) );
747}
748
749/*
750 * Helper for writing "RSA key size", "EC key size", etc
751 */
752int x509_key_size_helper( char *buf, size_t size, const char *name )
753{
754 char *p = buf;
755 size_t n = size;
756 int ret;
757
758 if( strlen( name ) + sizeof( " key size" ) > size )
759 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
760
761 ret = snprintf( p, n, "%s key size", name );
762 SAFE_SNPRINTF();
763
764 return( 0 );
765}
766
767/*
768 * Return an informational string describing the given OID
769 */
770const char *x509_oid_get_description( x509_buf *oid )
771{
772 const char *desc = NULL;
773 int ret;
774
775 ret = oid_get_extended_key_usage( oid, &desc );
776
777 if( ret != 0 )
778 return( NULL );
779
780 return( desc );
781}
782
783/* Return the x.y.z.... style numeric string for the given OID */
784int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
785{
786 return oid_get_numeric_string( buf, size, oid );
787}
788
789/*
790 * Return 0 if the x509_time is still valid, or 1 otherwise.
791 */
792#if defined(POLARSSL_HAVE_TIME)
Paul Bakker86d0c192013-09-18 11:11:02 +0200793int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200794{
795 int year, mon, day;
796 int hour, min, sec;
797
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100798#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200799 SYSTEMTIME st;
800
801 GetLocalTime(&st);
802
803 year = st.wYear;
804 mon = st.wMonth;
805 day = st.wDay;
806 hour = st.wHour;
807 min = st.wMinute;
808 sec = st.wSecond;
809#else
810 struct tm *lt;
811 time_t tt;
812
813 tt = time( NULL );
814 lt = localtime( &tt );
815
816 year = lt->tm_year + 1900;
817 mon = lt->tm_mon + 1;
818 day = lt->tm_mday;
819 hour = lt->tm_hour;
820 min = lt->tm_min;
821 sec = lt->tm_sec;
822#endif
823
824 if( year > to->year )
825 return( 1 );
826
827 if( year == to->year &&
828 mon > to->mon )
829 return( 1 );
830
831 if( year == to->year &&
832 mon == to->mon &&
833 day > to->day )
834 return( 1 );
835
836 if( year == to->year &&
837 mon == to->mon &&
838 day == to->day &&
839 hour > to->hour )
840 return( 1 );
841
842 if( year == to->year &&
843 mon == to->mon &&
844 day == to->day &&
845 hour == to->hour &&
846 min > to->min )
847 return( 1 );
848
849 if( year == to->year &&
850 mon == to->mon &&
851 day == to->day &&
852 hour == to->hour &&
853 min == to->min &&
854 sec > to->sec )
855 return( 1 );
856
857 return( 0 );
858}
859#else /* POLARSSL_HAVE_TIME */
Paul Bakker86d0c192013-09-18 11:11:02 +0200860int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200861{
862 ((void) to);
863 return( 0 );
864}
865#endif /* POLARSSL_HAVE_TIME */
866
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200867#if defined(POLARSSL_SELF_TEST)
868
869#include "polarssl/x509_crt.h"
870#include "polarssl/certs.h"
871
872/*
873 * Checkup routine
874 */
875int x509_self_test( int verbose )
876{
877#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
878 int ret;
879 int flags;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200880 x509_crt cacert;
881 x509_crt clicert;
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200882
883 if( verbose != 0 )
884 printf( " X.509 certificate load: " );
885
Paul Bakkerb6b09562013-09-18 14:17:41 +0200886 x509_crt_init( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200887
Paul Bakkerddf26b42013-09-18 13:46:23 +0200888 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
889 strlen( test_cli_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200890 if( ret != 0 )
891 {
892 if( verbose != 0 )
893 printf( "failed\n" );
894
895 return( ret );
896 }
897
Paul Bakkerb6b09562013-09-18 14:17:41 +0200898 x509_crt_init( &cacert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200899
Paul Bakkerddf26b42013-09-18 13:46:23 +0200900 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
901 strlen( test_ca_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200902 if( ret != 0 )
903 {
904 if( verbose != 0 )
905 printf( "failed\n" );
906
907 return( ret );
908 }
909
910 if( verbose != 0 )
911 printf( "passed\n X.509 signature verify: ");
912
Paul Bakkerddf26b42013-09-18 13:46:23 +0200913 ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200914 if( ret != 0 )
915 {
916 if( verbose != 0 )
917 printf( "failed\n" );
918
919 printf("ret = %d, &flags = %04x\n", ret, flags);
920
921 return( ret );
922 }
923
924 if( verbose != 0 )
925 printf( "passed\n\n");
926
927 x509_crt_free( &cacert );
928 x509_crt_free( &clicert );
929
930 return( 0 );
931#else
932 ((void) verbose);
933 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
934#endif
935}
936
937#endif
938
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200939#endif /* POLARSSL_X509_USE_C */