blob: 45dcea0fd63ac07a0179e722ab77dcb5297b653b [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é-Gonnardf346bab2014-01-23 16:24:44 +0100141 * RSASSA-PSS-params ::= SEQUENCE {
142 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
143 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
144 * saltLength [2] INTEGER DEFAULT 20,
145 * trailerField [3] INTEGER DEFAULT 1 }
146 * -- Note that the tags in this Sequence are explicit.
147 */
148int x509_get_rsassa_pss_params( const x509_buf *params,
149 md_type_t *md_alg,
150 int *salt_len,
151 int *trailer_field )
152{
153 int ret;
154 unsigned char *p;
155 const unsigned char *end;
156 size_t len;
157 x509_buf alg_id;
158
159 /* First set everything to defaults */
160 *md_alg = POLARSSL_MD_SHA1;
161 *salt_len = 20;
162 *trailer_field = 1;
163
164 /* Make sure params is a SEQUENCE and setup bounds */
165 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
166 return( POLARSSL_ERR_X509_INVALID_ALG +
167 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
168
169 p = (unsigned char *) params->p;
170 end = p + params->len;
171
172 if( p == end )
173 return( 0 );
174
175 if( ( ret = asn1_get_tag( &p, end, &len,
176 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
177 {
178 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
179 // TODO: WIP
180 }
181 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
182 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
183
184 if( ( ret = asn1_get_tag( &p, end, &len,
185 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
186 {
187 /* MaskGenAlgorithm ::= AlgorithmIdentifier */
188 // TODO: WIP
189 }
190 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
191 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
192
193 if( p == end )
194 return( 0 );
195
196 if( ( ret = asn1_get_tag( &p, end, &len,
197 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 )
198 {
199 /* salt_len */
200 if( ( ret = asn1_get_int( &p, p + len, salt_len ) ) != 0 )
201 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
202 }
203 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
204 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
205
206 if( p == end )
207 return( 0 );
208
209 if( ( ret = asn1_get_tag( &p, end, &len,
210 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 )
211 {
212 /* trailer_field */
213 if( ( ret = asn1_get_int( &p, p + len, trailer_field ) ) != 0 )
214 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
215 }
216 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
217 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
218
219 if( p != end )
220 return( POLARSSL_ERR_X509_INVALID_ALG +
221 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
222
223 return( 0 );
224}
225
226/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200227 * AttributeTypeAndValue ::= SEQUENCE {
228 * type AttributeType,
229 * value AttributeValue }
230 *
231 * AttributeType ::= OBJECT IDENTIFIER
232 *
233 * AttributeValue ::= ANY DEFINED BY AttributeType
234 */
235static int x509_get_attr_type_value( unsigned char **p,
236 const unsigned char *end,
237 x509_name *cur )
238{
239 int ret;
240 size_t len;
241 x509_buf *oid;
242 x509_buf *val;
243
244 if( ( ret = asn1_get_tag( p, end, &len,
245 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200246 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200247
248 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200249 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200250 POLARSSL_ERR_ASN1_OUT_OF_DATA );
251
252 oid = &cur->oid;
253 oid->tag = **p;
254
255 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200256 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200257
258 oid->p = *p;
259 *p += oid->len;
260
261 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200262 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200263 POLARSSL_ERR_ASN1_OUT_OF_DATA );
264
265 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
266 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
267 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker51876562013-09-17 14:36:05 +0200268 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200269 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
270
271 val = &cur->val;
272 val->tag = *(*p)++;
273
274 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200275 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200276
277 val->p = *p;
278 *p += val->len;
279
280 cur->next = NULL;
281
282 return( 0 );
283}
284
285/*
286 * RelativeDistinguishedName ::=
287 * SET OF AttributeTypeAndValue
288 *
289 * AttributeTypeAndValue ::= SEQUENCE {
290 * type AttributeType,
291 * value AttributeValue }
292 *
293 * AttributeType ::= OBJECT IDENTIFIER
294 *
295 * AttributeValue ::= ANY DEFINED BY AttributeType
296 */
297int x509_get_name( unsigned char **p, const unsigned char *end,
298 x509_name *cur )
299{
300 int ret;
301 size_t len;
302 const unsigned char *end2;
303 x509_name *use;
304
305 if( ( ret = asn1_get_tag( p, end, &len,
306 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200307 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200308
309 end2 = end;
310 end = *p + len;
311 use = cur;
312
313 do
314 {
315 if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
316 return( ret );
317
318 if( *p != end )
319 {
320 use->next = (x509_name *) polarssl_malloc(
321 sizeof( x509_name ) );
322
323 if( use->next == NULL )
324 return( POLARSSL_ERR_X509_MALLOC_FAILED );
325
326 memset( use->next, 0, sizeof( x509_name ) );
327
328 use = use->next;
329 }
330 }
331 while( *p != end );
332
333 /*
334 * recurse until end of SEQUENCE is reached
335 */
336 if( *p == end2 )
337 return( 0 );
338
339 cur->next = (x509_name *) polarssl_malloc(
340 sizeof( x509_name ) );
341
342 if( cur->next == NULL )
343 return( POLARSSL_ERR_X509_MALLOC_FAILED );
344
345 memset( cur->next, 0, sizeof( x509_name ) );
346
347 return( x509_get_name( p, end2, cur->next ) );
348}
349
350/*
351 * Time ::= CHOICE {
352 * utcTime UTCTime,
353 * generalTime GeneralizedTime }
354 */
355int x509_get_time( unsigned char **p, const unsigned char *end,
356 x509_time *time )
357{
358 int ret;
359 size_t len;
360 char date[64];
361 unsigned char tag;
362
363 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200364 return( POLARSSL_ERR_X509_INVALID_DATE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200365 POLARSSL_ERR_ASN1_OUT_OF_DATA );
366
367 tag = **p;
368
369 if ( tag == ASN1_UTC_TIME )
370 {
371 (*p)++;
372 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200373
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200374 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200375 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200376
377 memset( date, 0, sizeof( date ) );
378 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
379 len : sizeof( date ) - 1 );
380
Manuel Pégourié-Gonnard9655e452014-04-11 12:29:49 +0200381 if( sscanf( date, "%2d%2d%2d%2d%2d%2dZ",
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200382 &time->year, &time->mon, &time->day,
383 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200384 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200385
386 time->year += 100 * ( time->year < 50 );
387 time->year += 1900;
388
389 *p += len;
390
391 return( 0 );
392 }
393 else if ( tag == ASN1_GENERALIZED_TIME )
394 {
395 (*p)++;
396 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200397
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200398 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200399 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200400
401 memset( date, 0, sizeof( date ) );
402 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
403 len : sizeof( date ) - 1 );
404
Manuel Pégourié-Gonnard9655e452014-04-11 12:29:49 +0200405 if( sscanf( date, "%4d%2d%2d%2d%2d%2dZ",
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200406 &time->year, &time->mon, &time->day,
407 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200408 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200409
410 *p += len;
411
412 return( 0 );
413 }
414 else
Paul Bakker51876562013-09-17 14:36:05 +0200415 return( POLARSSL_ERR_X509_INVALID_DATE +
416 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200417}
418
419int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
420{
421 int ret;
422 size_t len;
423
424 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200425 return( POLARSSL_ERR_X509_INVALID_SIGNATURE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200426 POLARSSL_ERR_ASN1_OUT_OF_DATA );
427
428 sig->tag = **p;
429
430 if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200431 return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200432
433 sig->len = len;
434 sig->p = *p;
435
436 *p += len;
437
438 return( 0 );
439}
440
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100441int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
442 pk_type_t *pk_alg )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200443{
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100444 int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200445
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100446 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200447 return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200448
449 return( 0 );
450}
451
452/*
453 * X.509 Extensions (No parsing of extensions, pointer should
454 * be either manually updated or extensions should be parsed!
455 */
456int x509_get_ext( unsigned char **p, const unsigned char *end,
457 x509_buf *ext, int tag )
458{
459 int ret;
460 size_t len;
461
462 if( *p == end )
463 return( 0 );
464
465 ext->tag = **p;
466
467 if( ( ret = asn1_get_tag( p, end, &ext->len,
468 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
469 return( ret );
470
471 ext->p = *p;
472 end = *p + ext->len;
473
474 /*
475 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
476 *
477 * Extension ::= SEQUENCE {
478 * extnID OBJECT IDENTIFIER,
479 * critical BOOLEAN DEFAULT FALSE,
480 * extnValue OCTET STRING }
481 */
482 if( ( ret = asn1_get_tag( p, end, &len,
483 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200484 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200485
486 if( end != *p + len )
Paul Bakker51876562013-09-17 14:36:05 +0200487 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200488 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
489
490 return( 0 );
491}
492
493#if defined(POLARSSL_FS_IO)
494/*
495 * Load all data from a file into a given buffer.
496 */
497int x509_load_file( const char *path, unsigned char **buf, size_t *n )
498{
499 FILE *f;
500 long size;
501
502 if( ( f = fopen( path, "rb" ) ) == NULL )
503 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
504
505 fseek( f, 0, SEEK_END );
506 if( ( size = ftell( f ) ) == -1 )
507 {
508 fclose( f );
509 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
510 }
511 fseek( f, 0, SEEK_SET );
512
513 *n = (size_t) size;
514
515 if( *n + 1 == 0 ||
516 ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
517 {
518 fclose( f );
519 return( POLARSSL_ERR_X509_MALLOC_FAILED );
520 }
521
522 if( fread( *buf, 1, *n, f ) != *n )
523 {
524 fclose( f );
525 polarssl_free( *buf );
526 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
527 }
528
529 fclose( f );
530
531 (*buf)[*n] = '\0';
532
533 return( 0 );
534}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200535#endif /* POLARSSL_FS_IO */
536
Paul Bakker6edcd412013-10-29 15:22:54 +0100537#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
538 !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200539#include <stdarg.h>
540
541#if !defined vsnprintf
542#define vsnprintf _vsnprintf
543#endif // vsnprintf
544
545/*
546 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
547 * Result value is not size of buffer needed, but -1 if no fit is possible.
548 *
549 * This fuction tries to 'fix' this by at least suggesting enlarging the
550 * size by 20.
551 */
552static int compat_snprintf(char *str, size_t size, const char *format, ...)
553{
554 va_list ap;
555 int res = -1;
556
557 va_start( ap, format );
558
559 res = vsnprintf( str, size, format, ap );
560
561 va_end( ap );
562
563 // No quick fix possible
564 if ( res < 0 )
565 return( (int) size + 20 );
566
567 return res;
568}
569
570#define snprintf compat_snprintf
Paul Bakker9af723c2014-05-01 13:03:14 +0200571#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200572
573#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
574
575#define SAFE_SNPRINTF() \
576{ \
577 if( ret == -1 ) \
578 return( -1 ); \
579 \
580 if ( (unsigned int) ret > n ) { \
581 p[n - 1] = '\0'; \
582 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
583 } \
584 \
585 n -= (unsigned int) ret; \
586 p += (unsigned int) ret; \
587}
588
589/*
590 * Store the name in printable form into buf; no more
591 * than size characters will be written
592 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200593int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200594{
595 int ret;
596 size_t i, n;
597 unsigned char c;
598 const x509_name *name;
599 const char *short_name = NULL;
600 char s[128], *p;
601
602 memset( s, 0, sizeof( s ) );
603
604 name = dn;
605 p = buf;
606 n = size;
607
608 while( name != NULL )
609 {
610 if( !name->oid.p )
611 {
612 name = name->next;
613 continue;
614 }
615
616 if( name != dn )
617 {
618 ret = snprintf( p, n, ", " );
619 SAFE_SNPRINTF();
620 }
621
622 ret = oid_get_attr_short_name( &name->oid, &short_name );
623
624 if( ret == 0 )
625 ret = snprintf( p, n, "%s=", short_name );
626 else
627 ret = snprintf( p, n, "\?\?=" );
628 SAFE_SNPRINTF();
629
630 for( i = 0; i < name->val.len; i++ )
631 {
632 if( i >= sizeof( s ) - 1 )
633 break;
634
635 c = name->val.p[i];
636 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
637 s[i] = '?';
638 else s[i] = c;
639 }
640 s[i] = '\0';
641 ret = snprintf( p, n, "%s", s );
642 SAFE_SNPRINTF();
643 name = name->next;
644 }
645
646 return( (int) ( size - n ) );
647}
648
649/*
650 * Store the serial in printable form into buf; no more
651 * than size characters will be written
652 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200653int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200654{
655 int ret;
656 size_t i, n, nr;
657 char *p;
658
659 p = buf;
660 n = size;
661
662 nr = ( serial->len <= 32 )
663 ? serial->len : 28;
664
665 for( i = 0; i < nr; i++ )
666 {
667 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
668 continue;
669
670 ret = snprintf( p, n, "%02X%s",
671 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
672 SAFE_SNPRINTF();
673 }
674
675 if( nr != serial->len )
676 {
677 ret = snprintf( p, n, "...." );
678 SAFE_SNPRINTF();
679 }
680
681 return( (int) ( size - n ) );
682}
683
684/*
685 * Helper for writing "RSA key size", "EC key size", etc
686 */
687int x509_key_size_helper( char *buf, size_t size, const char *name )
688{
689 char *p = buf;
690 size_t n = size;
691 int ret;
692
693 if( strlen( name ) + sizeof( " key size" ) > size )
694 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
695
696 ret = snprintf( p, n, "%s key size", name );
697 SAFE_SNPRINTF();
698
699 return( 0 );
700}
701
702/*
703 * Return an informational string describing the given OID
704 */
705const char *x509_oid_get_description( x509_buf *oid )
706{
707 const char *desc = NULL;
708 int ret;
709
710 ret = oid_get_extended_key_usage( oid, &desc );
711
712 if( ret != 0 )
713 return( NULL );
714
715 return( desc );
716}
717
718/* Return the x.y.z.... style numeric string for the given OID */
719int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
720{
721 return oid_get_numeric_string( buf, size, oid );
722}
723
724/*
725 * Return 0 if the x509_time is still valid, or 1 otherwise.
726 */
727#if defined(POLARSSL_HAVE_TIME)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200728
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100729static void x509_get_current_time( x509_time *now )
730{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100731#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200732 SYSTEMTIME st;
733
Manuel Pégourié-Gonnard0776a432014-04-11 12:25:45 +0200734 GetSystemTime(&st);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200735
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100736 now->year = st.wYear;
737 now->mon = st.wMonth;
738 now->day = st.wDay;
739 now->hour = st.wHour;
740 now->min = st.wMinute;
741 now->sec = st.wSecond;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200742#else
Paul Bakker5fff23b2014-03-26 15:34:54 +0100743 struct tm lt;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200744 time_t tt;
745
746 tt = time( NULL );
Manuel Pégourié-Gonnard0776a432014-04-11 12:25:45 +0200747 gmtime_r( &tt, &lt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200748
Paul Bakker5fff23b2014-03-26 15:34:54 +0100749 now->year = lt.tm_year + 1900;
750 now->mon = lt.tm_mon + 1;
751 now->day = lt.tm_mday;
752 now->hour = lt.tm_hour;
753 now->min = lt.tm_min;
754 now->sec = lt.tm_sec;
Paul Bakker9af723c2014-05-01 13:03:14 +0200755#endif /* _WIN32 && !EFIX64 && !EFI32 */
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100756}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200757
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100758/*
759 * Return 0 if before <= after, 1 otherwise
760 */
761static int x509_check_time( const x509_time *before, const x509_time *after )
762{
763 if( before->year > after->year )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200764 return( 1 );
765
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100766 if( before->year == after->year &&
767 before->mon > after->mon )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200768 return( 1 );
769
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100770 if( before->year == after->year &&
771 before->mon == after->mon &&
772 before->day > after->day )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200773 return( 1 );
774
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100775 if( before->year == after->year &&
776 before->mon == after->mon &&
777 before->day == after->day &&
778 before->hour > after->hour )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200779 return( 1 );
780
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100781 if( before->year == after->year &&
782 before->mon == after->mon &&
783 before->day == after->day &&
784 before->hour == after->hour &&
785 before->min > after->min )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200786 return( 1 );
787
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100788 if( before->year == after->year &&
789 before->mon == after->mon &&
790 before->day == after->day &&
791 before->hour == after->hour &&
792 before->min == after->min &&
793 before->sec > after->sec )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200794 return( 1 );
795
796 return( 0 );
797}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100798
799int x509_time_expired( const x509_time *to )
800{
801 x509_time now;
802
803 x509_get_current_time( &now );
804
805 return( x509_check_time( &now, to ) );
806}
807
808int x509_time_future( const x509_time *from )
809{
810 x509_time now;
811
812 x509_get_current_time( &now );
813
814 return( x509_check_time( from, &now ) );
815}
816
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200817#else /* POLARSSL_HAVE_TIME */
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100818
Paul Bakker86d0c192013-09-18 11:11:02 +0200819int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200820{
821 ((void) to);
822 return( 0 );
823}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100824
825int x509_time_future( const x509_time *from )
826{
827 ((void) from);
828 return( 0 );
829}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200830#endif /* POLARSSL_HAVE_TIME */
831
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200832#if defined(POLARSSL_SELF_TEST)
833
834#include "polarssl/x509_crt.h"
835#include "polarssl/certs.h"
836
837/*
838 * Checkup routine
839 */
840int x509_self_test( int verbose )
841{
Manuel Pégourié-Gonnard3d413702014-04-29 15:29:41 +0200842#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_SHA1_C)
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200843 int ret;
844 int flags;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200845 x509_crt cacert;
846 x509_crt clicert;
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200847
848 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100849 polarssl_printf( " X.509 certificate load: " );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200850
Paul Bakkerb6b09562013-09-18 14:17:41 +0200851 x509_crt_init( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200852
Paul Bakkerddf26b42013-09-18 13:46:23 +0200853 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
854 strlen( test_cli_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200855 if( ret != 0 )
856 {
857 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100858 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200859
860 return( ret );
861 }
862
Paul Bakkerb6b09562013-09-18 14:17:41 +0200863 x509_crt_init( &cacert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200864
Paul Bakkerddf26b42013-09-18 13:46:23 +0200865 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
866 strlen( test_ca_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200867 if( ret != 0 )
868 {
869 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100870 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200871
872 return( ret );
873 }
874
875 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100876 polarssl_printf( "passed\n X.509 signature verify: ");
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200877
Paul Bakkerddf26b42013-09-18 13:46:23 +0200878 ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200879 if( ret != 0 )
880 {
881 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100882 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200883
Paul Bakker7dc4c442014-02-01 22:50:26 +0100884 polarssl_printf("ret = %d, &flags = %04x\n", ret, flags);
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200885
886 return( ret );
887 }
888
889 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100890 polarssl_printf( "passed\n\n");
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200891
892 x509_crt_free( &cacert );
893 x509_crt_free( &clicert );
894
895 return( 0 );
896#else
897 ((void) verbose);
898 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker9af723c2014-05-01 13:03:14 +0200899#endif /* POLARSSL_CERTS_C && POLARSSL_SHA1_C */
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200900}
901
Paul Bakker9af723c2014-05-01 13:03:14 +0200902#endif /* POLARSSL_SELF_TEST */
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200903
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200904#endif /* POLARSSL_X509_USE_C */