blob: 9915518652cab92c78799403befb103a691d3731 [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/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200141 * AttributeTypeAndValue ::= SEQUENCE {
142 * type AttributeType,
143 * value AttributeValue }
144 *
145 * AttributeType ::= OBJECT IDENTIFIER
146 *
147 * AttributeValue ::= ANY DEFINED BY AttributeType
148 */
149static int x509_get_attr_type_value( unsigned char **p,
150 const unsigned char *end,
151 x509_name *cur )
152{
153 int ret;
154 size_t len;
155 x509_buf *oid;
156 x509_buf *val;
157
158 if( ( ret = asn1_get_tag( p, end, &len,
159 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200160 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200161
162 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200163 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200164 POLARSSL_ERR_ASN1_OUT_OF_DATA );
165
166 oid = &cur->oid;
167 oid->tag = **p;
168
169 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200170 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200171
172 oid->p = *p;
173 *p += oid->len;
174
175 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200176 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200177 POLARSSL_ERR_ASN1_OUT_OF_DATA );
178
179 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
180 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
181 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker51876562013-09-17 14:36:05 +0200182 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200183 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
184
185 val = &cur->val;
186 val->tag = *(*p)++;
187
188 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200189 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200190
191 val->p = *p;
192 *p += val->len;
193
194 cur->next = NULL;
195
196 return( 0 );
197}
198
199/*
200 * RelativeDistinguishedName ::=
201 * SET OF AttributeTypeAndValue
202 *
203 * AttributeTypeAndValue ::= SEQUENCE {
204 * type AttributeType,
205 * value AttributeValue }
206 *
207 * AttributeType ::= OBJECT IDENTIFIER
208 *
209 * AttributeValue ::= ANY DEFINED BY AttributeType
210 */
211int x509_get_name( unsigned char **p, const unsigned char *end,
212 x509_name *cur )
213{
214 int ret;
215 size_t len;
216 const unsigned char *end2;
217 x509_name *use;
218
219 if( ( ret = asn1_get_tag( p, end, &len,
220 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200221 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200222
223 end2 = end;
224 end = *p + len;
225 use = cur;
226
227 do
228 {
229 if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
230 return( ret );
231
232 if( *p != end )
233 {
234 use->next = (x509_name *) polarssl_malloc(
235 sizeof( x509_name ) );
236
237 if( use->next == NULL )
238 return( POLARSSL_ERR_X509_MALLOC_FAILED );
239
240 memset( use->next, 0, sizeof( x509_name ) );
241
242 use = use->next;
243 }
244 }
245 while( *p != end );
246
247 /*
248 * recurse until end of SEQUENCE is reached
249 */
250 if( *p == end2 )
251 return( 0 );
252
253 cur->next = (x509_name *) polarssl_malloc(
254 sizeof( x509_name ) );
255
256 if( cur->next == NULL )
257 return( POLARSSL_ERR_X509_MALLOC_FAILED );
258
259 memset( cur->next, 0, sizeof( x509_name ) );
260
261 return( x509_get_name( p, end2, cur->next ) );
262}
263
264/*
265 * Time ::= CHOICE {
266 * utcTime UTCTime,
267 * generalTime GeneralizedTime }
268 */
269int x509_get_time( unsigned char **p, const unsigned char *end,
270 x509_time *time )
271{
272 int ret;
273 size_t len;
274 char date[64];
275 unsigned char tag;
276
277 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200278 return( POLARSSL_ERR_X509_INVALID_DATE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200279 POLARSSL_ERR_ASN1_OUT_OF_DATA );
280
281 tag = **p;
282
283 if ( tag == ASN1_UTC_TIME )
284 {
285 (*p)++;
286 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200287
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200288 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200289 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200290
291 memset( date, 0, sizeof( date ) );
292 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
293 len : sizeof( date ) - 1 );
294
Manuel Pégourié-Gonnard9655e452014-04-11 12:29:49 +0200295 if( sscanf( date, "%2d%2d%2d%2d%2d%2dZ",
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200296 &time->year, &time->mon, &time->day,
297 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200298 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200299
300 time->year += 100 * ( time->year < 50 );
301 time->year += 1900;
302
303 *p += len;
304
305 return( 0 );
306 }
307 else if ( tag == ASN1_GENERALIZED_TIME )
308 {
309 (*p)++;
310 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200311
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200312 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200313 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200314
315 memset( date, 0, sizeof( date ) );
316 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
317 len : sizeof( date ) - 1 );
318
Manuel Pégourié-Gonnard9655e452014-04-11 12:29:49 +0200319 if( sscanf( date, "%4d%2d%2d%2d%2d%2dZ",
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200320 &time->year, &time->mon, &time->day,
321 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200322 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200323
324 *p += len;
325
326 return( 0 );
327 }
328 else
Paul Bakker51876562013-09-17 14:36:05 +0200329 return( POLARSSL_ERR_X509_INVALID_DATE +
330 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200331}
332
333int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
334{
335 int ret;
336 size_t len;
337
338 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200339 return( POLARSSL_ERR_X509_INVALID_SIGNATURE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200340 POLARSSL_ERR_ASN1_OUT_OF_DATA );
341
342 sig->tag = **p;
343
344 if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200345 return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200346
347 sig->len = len;
348 sig->p = *p;
349
350 *p += len;
351
352 return( 0 );
353}
354
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100355int x509_get_sig_alg( const x509_buf *sig_oid, md_type_t *md_alg,
356 pk_type_t *pk_alg )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200357{
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100358 int ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200359
Manuel Pégourié-Gonnardc9093082014-02-12 09:39:59 +0100360 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200361 return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200362
363 return( 0 );
364}
365
366/*
367 * X.509 Extensions (No parsing of extensions, pointer should
368 * be either manually updated or extensions should be parsed!
369 */
370int x509_get_ext( unsigned char **p, const unsigned char *end,
371 x509_buf *ext, int tag )
372{
373 int ret;
374 size_t len;
375
376 if( *p == end )
377 return( 0 );
378
379 ext->tag = **p;
380
381 if( ( ret = asn1_get_tag( p, end, &ext->len,
382 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
383 return( ret );
384
385 ext->p = *p;
386 end = *p + ext->len;
387
388 /*
389 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
390 *
391 * Extension ::= SEQUENCE {
392 * extnID OBJECT IDENTIFIER,
393 * critical BOOLEAN DEFAULT FALSE,
394 * extnValue OCTET STRING }
395 */
396 if( ( ret = asn1_get_tag( p, end, &len,
397 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200398 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200399
400 if( end != *p + len )
Paul Bakker51876562013-09-17 14:36:05 +0200401 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200402 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
403
404 return( 0 );
405}
406
407#if defined(POLARSSL_FS_IO)
408/*
409 * Load all data from a file into a given buffer.
410 */
411int x509_load_file( const char *path, unsigned char **buf, size_t *n )
412{
413 FILE *f;
414 long size;
415
416 if( ( f = fopen( path, "rb" ) ) == NULL )
417 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
418
419 fseek( f, 0, SEEK_END );
420 if( ( size = ftell( f ) ) == -1 )
421 {
422 fclose( f );
423 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
424 }
425 fseek( f, 0, SEEK_SET );
426
427 *n = (size_t) size;
428
429 if( *n + 1 == 0 ||
430 ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
431 {
432 fclose( f );
433 return( POLARSSL_ERR_X509_MALLOC_FAILED );
434 }
435
436 if( fread( *buf, 1, *n, f ) != *n )
437 {
438 fclose( f );
439 polarssl_free( *buf );
440 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
441 }
442
443 fclose( f );
444
445 (*buf)[*n] = '\0';
446
447 return( 0 );
448}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200449#endif /* POLARSSL_FS_IO */
450
Paul Bakker6edcd412013-10-29 15:22:54 +0100451#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
452 !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200453#include <stdarg.h>
454
455#if !defined vsnprintf
456#define vsnprintf _vsnprintf
457#endif // vsnprintf
458
459/*
460 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
461 * Result value is not size of buffer needed, but -1 if no fit is possible.
462 *
463 * This fuction tries to 'fix' this by at least suggesting enlarging the
464 * size by 20.
465 */
466static int compat_snprintf(char *str, size_t size, const char *format, ...)
467{
468 va_list ap;
469 int res = -1;
470
471 va_start( ap, format );
472
473 res = vsnprintf( str, size, format, ap );
474
475 va_end( ap );
476
477 // No quick fix possible
478 if ( res < 0 )
479 return( (int) size + 20 );
480
481 return res;
482}
483
484#define snprintf compat_snprintf
Paul Bakker9af723c2014-05-01 13:03:14 +0200485#endif /* _MSC_VER && !snprintf && !EFIX64 && !EFI32 */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200486
487#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
488
489#define SAFE_SNPRINTF() \
490{ \
491 if( ret == -1 ) \
492 return( -1 ); \
493 \
494 if ( (unsigned int) ret > n ) { \
495 p[n - 1] = '\0'; \
496 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
497 } \
498 \
499 n -= (unsigned int) ret; \
500 p += (unsigned int) ret; \
501}
502
503/*
504 * Store the name in printable form into buf; no more
505 * than size characters will be written
506 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200507int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200508{
509 int ret;
510 size_t i, n;
511 unsigned char c;
512 const x509_name *name;
513 const char *short_name = NULL;
514 char s[128], *p;
515
516 memset( s, 0, sizeof( s ) );
517
518 name = dn;
519 p = buf;
520 n = size;
521
522 while( name != NULL )
523 {
524 if( !name->oid.p )
525 {
526 name = name->next;
527 continue;
528 }
529
530 if( name != dn )
531 {
532 ret = snprintf( p, n, ", " );
533 SAFE_SNPRINTF();
534 }
535
536 ret = oid_get_attr_short_name( &name->oid, &short_name );
537
538 if( ret == 0 )
539 ret = snprintf( p, n, "%s=", short_name );
540 else
541 ret = snprintf( p, n, "\?\?=" );
542 SAFE_SNPRINTF();
543
544 for( i = 0; i < name->val.len; i++ )
545 {
546 if( i >= sizeof( s ) - 1 )
547 break;
548
549 c = name->val.p[i];
550 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
551 s[i] = '?';
552 else s[i] = c;
553 }
554 s[i] = '\0';
555 ret = snprintf( p, n, "%s", s );
556 SAFE_SNPRINTF();
557 name = name->next;
558 }
559
560 return( (int) ( size - n ) );
561}
562
563/*
564 * Store the serial in printable form into buf; no more
565 * than size characters will be written
566 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200567int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200568{
569 int ret;
570 size_t i, n, nr;
571 char *p;
572
573 p = buf;
574 n = size;
575
576 nr = ( serial->len <= 32 )
577 ? serial->len : 28;
578
579 for( i = 0; i < nr; i++ )
580 {
581 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
582 continue;
583
584 ret = snprintf( p, n, "%02X%s",
585 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
586 SAFE_SNPRINTF();
587 }
588
589 if( nr != serial->len )
590 {
591 ret = snprintf( p, n, "...." );
592 SAFE_SNPRINTF();
593 }
594
595 return( (int) ( size - n ) );
596}
597
598/*
599 * Helper for writing "RSA key size", "EC key size", etc
600 */
601int x509_key_size_helper( char *buf, size_t size, const char *name )
602{
603 char *p = buf;
604 size_t n = size;
605 int ret;
606
607 if( strlen( name ) + sizeof( " key size" ) > size )
608 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
609
610 ret = snprintf( p, n, "%s key size", name );
611 SAFE_SNPRINTF();
612
613 return( 0 );
614}
615
616/*
617 * Return an informational string describing the given OID
618 */
619const char *x509_oid_get_description( x509_buf *oid )
620{
621 const char *desc = NULL;
622 int ret;
623
624 ret = oid_get_extended_key_usage( oid, &desc );
625
626 if( ret != 0 )
627 return( NULL );
628
629 return( desc );
630}
631
632/* Return the x.y.z.... style numeric string for the given OID */
633int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
634{
635 return oid_get_numeric_string( buf, size, oid );
636}
637
638/*
639 * Return 0 if the x509_time is still valid, or 1 otherwise.
640 */
641#if defined(POLARSSL_HAVE_TIME)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200642
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100643static void x509_get_current_time( x509_time *now )
644{
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100645#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200646 SYSTEMTIME st;
647
Manuel Pégourié-Gonnard0776a432014-04-11 12:25:45 +0200648 GetSystemTime(&st);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200649
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100650 now->year = st.wYear;
651 now->mon = st.wMonth;
652 now->day = st.wDay;
653 now->hour = st.wHour;
654 now->min = st.wMinute;
655 now->sec = st.wSecond;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200656#else
Paul Bakker5fff23b2014-03-26 15:34:54 +0100657 struct tm lt;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200658 time_t tt;
659
660 tt = time( NULL );
Manuel Pégourié-Gonnard0776a432014-04-11 12:25:45 +0200661 gmtime_r( &tt, &lt );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200662
Paul Bakker5fff23b2014-03-26 15:34:54 +0100663 now->year = lt.tm_year + 1900;
664 now->mon = lt.tm_mon + 1;
665 now->day = lt.tm_mday;
666 now->hour = lt.tm_hour;
667 now->min = lt.tm_min;
668 now->sec = lt.tm_sec;
Paul Bakker9af723c2014-05-01 13:03:14 +0200669#endif /* _WIN32 && !EFIX64 && !EFI32 */
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100670}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200671
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100672/*
673 * Return 0 if before <= after, 1 otherwise
674 */
675static int x509_check_time( const x509_time *before, const x509_time *after )
676{
677 if( before->year > after->year )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200678 return( 1 );
679
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100680 if( before->year == after->year &&
681 before->mon > after->mon )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200682 return( 1 );
683
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100684 if( before->year == after->year &&
685 before->mon == after->mon &&
686 before->day > after->day )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200687 return( 1 );
688
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100689 if( before->year == after->year &&
690 before->mon == after->mon &&
691 before->day == after->day &&
692 before->hour > after->hour )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200693 return( 1 );
694
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100695 if( before->year == after->year &&
696 before->mon == after->mon &&
697 before->day == after->day &&
698 before->hour == after->hour &&
699 before->min > after->min )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200700 return( 1 );
701
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100702 if( before->year == after->year &&
703 before->mon == after->mon &&
704 before->day == after->day &&
705 before->hour == after->hour &&
706 before->min == after->min &&
707 before->sec > after->sec )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200708 return( 1 );
709
710 return( 0 );
711}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100712
713int x509_time_expired( const x509_time *to )
714{
715 x509_time now;
716
717 x509_get_current_time( &now );
718
719 return( x509_check_time( &now, to ) );
720}
721
722int x509_time_future( const x509_time *from )
723{
724 x509_time now;
725
726 x509_get_current_time( &now );
727
728 return( x509_check_time( from, &now ) );
729}
730
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200731#else /* POLARSSL_HAVE_TIME */
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100732
Paul Bakker86d0c192013-09-18 11:11:02 +0200733int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200734{
735 ((void) to);
736 return( 0 );
737}
Manuel Pégourié-Gonnard6304f782014-03-10 12:26:11 +0100738
739int x509_time_future( const x509_time *from )
740{
741 ((void) from);
742 return( 0 );
743}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200744#endif /* POLARSSL_HAVE_TIME */
745
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200746#if defined(POLARSSL_SELF_TEST)
747
748#include "polarssl/x509_crt.h"
749#include "polarssl/certs.h"
750
751/*
752 * Checkup routine
753 */
754int x509_self_test( int verbose )
755{
Manuel Pégourié-Gonnard3d413702014-04-29 15:29:41 +0200756#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_SHA1_C)
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200757 int ret;
758 int flags;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200759 x509_crt cacert;
760 x509_crt clicert;
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200761
762 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100763 polarssl_printf( " X.509 certificate load: " );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200764
Paul Bakkerb6b09562013-09-18 14:17:41 +0200765 x509_crt_init( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200766
Paul Bakkerddf26b42013-09-18 13:46:23 +0200767 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
768 strlen( test_cli_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200769 if( ret != 0 )
770 {
771 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100772 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200773
774 return( ret );
775 }
776
Paul Bakkerb6b09562013-09-18 14:17:41 +0200777 x509_crt_init( &cacert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200778
Paul Bakkerddf26b42013-09-18 13:46:23 +0200779 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
780 strlen( test_ca_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200781 if( ret != 0 )
782 {
783 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100784 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200785
786 return( ret );
787 }
788
789 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100790 polarssl_printf( "passed\n X.509 signature verify: ");
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200791
Paul Bakkerddf26b42013-09-18 13:46:23 +0200792 ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200793 if( ret != 0 )
794 {
795 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100796 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200797
Paul Bakker7dc4c442014-02-01 22:50:26 +0100798 polarssl_printf("ret = %d, &flags = %04x\n", ret, flags);
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200799
800 return( ret );
801 }
802
803 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100804 polarssl_printf( "passed\n\n");
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200805
806 x509_crt_free( &cacert );
807 x509_crt_free( &clicert );
808
809 return( 0 );
810#else
811 ((void) verbose);
812 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker9af723c2014-05-01 13:03:14 +0200813#endif /* POLARSSL_CERTS_C && POLARSSL_SHA1_C */
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200814}
815
Paul Bakker9af723c2014-05-01 13:03:14 +0200816#endif /* POLARSSL_SELF_TEST */
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200817
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200818#endif /* POLARSSL_X509_USE_C */