blob: 17e8b4d5e07674fed033d72d5f41f92b52bebe9a [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
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
Paul Bakker7dc4c442014-02-01 22:50:26 +010048#if defined(POLARSSL_PLATFORM_C)
49#include "polarssl/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020050#else
Paul Bakker7dc4c442014-02-01 22:50:26 +010051#define polarssl_printf printf
Paul Bakker7c6b2c32013-09-16 13:49:26 +020052#define polarssl_malloc malloc
53#define polarssl_free free
54#endif
55
56#include <string.h>
57#include <stdlib.h>
Paul Bakkerfa6a6202013-10-28 18:48:30 +010058#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020059#include <windows.h>
60#else
61#include <time.h>
62#endif
63
Paul Bakkerfa6a6202013-10-28 18:48:30 +010064#if defined(EFIX64) || defined(EFI32)
65#include <stdio.h>
66#endif
67
Paul Bakker7c6b2c32013-09-16 13:49:26 +020068#if defined(POLARSSL_FS_IO)
69#include <stdio.h>
70#if !defined(_WIN32)
71#include <sys/types.h>
72#include <sys/stat.h>
73#include <dirent.h>
74#endif
75#endif
76
77/*
78 * CertificateSerialNumber ::= INTEGER
79 */
80int x509_get_serial( unsigned char **p, const unsigned char *end,
81 x509_buf *serial )
82{
83 int ret;
84
85 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +020086 return( POLARSSL_ERR_X509_INVALID_SERIAL +
Paul Bakker7c6b2c32013-09-16 13:49:26 +020087 POLARSSL_ERR_ASN1_OUT_OF_DATA );
88
89 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
90 **p != ASN1_INTEGER )
Paul Bakker51876562013-09-17 14:36:05 +020091 return( POLARSSL_ERR_X509_INVALID_SERIAL +
Paul Bakker7c6b2c32013-09-16 13:49:26 +020092 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
93
94 serial->tag = *(*p)++;
95
96 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +020097 return( POLARSSL_ERR_X509_INVALID_SERIAL + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +020098
99 serial->p = *p;
100 *p += serial->len;
101
102 return( 0 );
103}
104
105/* Get an algorithm identifier without parameters (eg for signatures)
106 *
107 * AlgorithmIdentifier ::= SEQUENCE {
108 * algorithm OBJECT IDENTIFIER,
109 * parameters ANY DEFINED BY algorithm OPTIONAL }
110 */
111int x509_get_alg_null( unsigned char **p, const unsigned char *end,
112 x509_buf *alg )
113{
114 int ret;
115
116 if( ( ret = asn1_get_alg_null( p, end, alg ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200117 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200118
119 return( 0 );
120}
121
122/*
Manuel Pégourié-Gonnardb1d4eb12014-01-22 10:12:57 +0100123 * Parse an algorithm identifier with (optional) paramaters
124 */
125int x509_get_alg( unsigned char **p, const unsigned char *end,
126 x509_buf *alg, x509_buf *params )
127{
128 int ret;
129
130 if( ( ret = asn1_get_alg( p, end, alg, params ) ) != 0 )
131 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
132
133 return( 0 );
134}
135
Manuel Pégourié-Gonnardce7c6fd2014-01-24 14:37:29 +0100136#if defined(POLARSSL_RSASSA_PSS_CERTIFICATES)
Manuel Pégourié-Gonnardb1d4eb12014-01-22 10:12:57 +0100137/*
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100138 * HashAlgorithm ::= AlgorithmIdentifier
139 *
140 * AlgorithmIdentifier ::= SEQUENCE {
141 * algorithm OBJECT IDENTIFIER,
142 * parameters ANY DEFINED BY algorithm OPTIONAL }
143 *
144 * For HashAlgorithm, parameters MUST be NULL or absent.
145 */
146static int x509_get_hash_alg( const x509_buf *alg, md_type_t *md_alg )
147{
148 int ret;
149 unsigned char *p;
150 const unsigned char *end;
151 x509_buf md_oid;
152 size_t len;
153
154 /* Make sure we got a SEQUENCE and setup bounds */
155 if( alg->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
156 return( POLARSSL_ERR_X509_INVALID_ALG +
157 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
158
159 p = (unsigned char *) alg->p;
160 end = p + alg->len;
161
162 if( p >= end )
163 return( POLARSSL_ERR_X509_INVALID_ALG +
164 POLARSSL_ERR_ASN1_OUT_OF_DATA );
165
166 /* Parse md_oid */
167 md_oid.tag = *p;
168
169 if( ( ret = asn1_get_tag( &p, end, &md_oid.len, ASN1_OID ) ) != 0 )
170 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
171
172 md_oid.p = p;
173 p += md_oid.len;
174
175 /* Get md_alg from md_oid */
176 if( ( ret = oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
177 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
178
179 /* Make sure params is absent of NULL */
180 if( p == end )
181 return( 0 );
182
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100183 if( ( ret = asn1_get_tag( &p, end, &len, ASN1_NULL ) ) != 0 || len != 0 )
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100184 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
185
186 if( p != end )
187 return( POLARSSL_ERR_X509_INVALID_ALG +
188 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
189
190 return( 0 );
191}
192
193/*
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100194 * RSASSA-PSS-params ::= SEQUENCE {
195 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
196 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
197 * saltLength [2] INTEGER DEFAULT 20,
198 * trailerField [3] INTEGER DEFAULT 1 }
199 * -- Note that the tags in this Sequence are explicit.
200 */
201int x509_get_rsassa_pss_params( const x509_buf *params,
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100202 md_type_t *md_alg, md_type_t *mgf_md,
203 int *salt_len, int *trailer_field )
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100204{
205 int ret;
206 unsigned char *p;
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100207 const unsigned char *end, *end2;
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100208 size_t len;
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100209 x509_buf alg_id, alg_params;
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100210
211 /* First set everything to defaults */
212 *md_alg = POLARSSL_MD_SHA1;
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100213 *mgf_md = POLARSSL_MD_SHA1;
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100214 *salt_len = 20;
215 *trailer_field = 1;
216
217 /* Make sure params is a SEQUENCE and setup bounds */
218 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
219 return( POLARSSL_ERR_X509_INVALID_ALG +
220 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
221
222 p = (unsigned char *) params->p;
223 end = p + params->len;
224
225 if( p == end )
226 return( 0 );
227
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100228 /*
229 * HashAlgorithm
230 */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100231 if( ( ret = asn1_get_tag( &p, end, &len,
232 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 )
233 {
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100234 end2 = p + len;
235
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100236 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100237 if( ( ret = x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100238 return( ret );
239
240 if( ( ret = oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
241 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100242
243 if( p != end2 )
244 return( POLARSSL_ERR_X509_INVALID_ALG +
245 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100246 }
247 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
248 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
249
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100250 if( p == end )
251 return( 0 );
252
253 /*
254 * MaskGenAlgorithm
255 */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100256 if( ( ret = asn1_get_tag( &p, end, &len,
257 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 )
258 {
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100259 end2 = p + len;
260
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100261 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100262 if( ( ret = x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
Manuel Pégourié-Gonnard3c1e8b52014-01-23 19:15:29 +0100263 return( ret );
264
265 /* Only MFG1 is recognised for now */
266 if( ! OID_CMP( OID_MGF1, &alg_id ) )
267 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE +
268 POLARSSL_ERR_OID_NOT_FOUND );
269
270 /* Parse HashAlgorithm */
271 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
272 return( ret );
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100273
274 if( p != end2 )
275 return( POLARSSL_ERR_X509_INVALID_ALG +
276 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100277 }
278 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
279 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
280
281 if( p == end )
282 return( 0 );
283
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100284 /*
285 * salt_len
286 */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100287 if( ( ret = asn1_get_tag( &p, end, &len,
288 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2 ) ) == 0 )
289 {
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100290 end2 = p + len;
291
292 if( ( ret = asn1_get_int( &p, end2, salt_len ) ) != 0 )
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100293 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100294
295 if( p != end2 )
296 return( POLARSSL_ERR_X509_INVALID_ALG +
297 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100298 }
299 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
300 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
301
302 if( p == end )
303 return( 0 );
304
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100305 /*
306 * trailer_field
307 */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100308 if( ( ret = asn1_get_tag( &p, end, &len,
309 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) == 0 )
310 {
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100311 end2 = p + len;
312
313 if( ( ret = asn1_get_int( &p, end2, trailer_field ) ) != 0 )
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100314 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
Manuel Pégourié-Gonnardb7de86d2014-01-24 14:15:20 +0100315
316 if( p != end2 )
317 return( POLARSSL_ERR_X509_INVALID_ALG +
318 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100319 }
320 else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
321 return( POLARSSL_ERR_X509_INVALID_ALG + ret );
322
323 if( p != end )
324 return( POLARSSL_ERR_X509_INVALID_ALG +
325 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
326
327 return( 0 );
328}
Manuel Pégourié-Gonnardce7c6fd2014-01-24 14:37:29 +0100329#endif /* POLARSSL_RSASSA_PSS_CERTIFICATES */
Manuel Pégourié-Gonnardd9fd87b2014-01-23 16:24:44 +0100330
331/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200332 * AttributeTypeAndValue ::= SEQUENCE {
333 * type AttributeType,
334 * value AttributeValue }
335 *
336 * AttributeType ::= OBJECT IDENTIFIER
337 *
338 * AttributeValue ::= ANY DEFINED BY AttributeType
339 */
340static int x509_get_attr_type_value( unsigned char **p,
341 const unsigned char *end,
342 x509_name *cur )
343{
344 int ret;
345 size_t len;
346 x509_buf *oid;
347 x509_buf *val;
348
349 if( ( ret = asn1_get_tag( p, end, &len,
350 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200351 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200352
353 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200354 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200355 POLARSSL_ERR_ASN1_OUT_OF_DATA );
356
357 oid = &cur->oid;
358 oid->tag = **p;
359
360 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200361 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200362
363 oid->p = *p;
364 *p += oid->len;
365
366 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200367 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200368 POLARSSL_ERR_ASN1_OUT_OF_DATA );
369
370 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
371 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
372 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker51876562013-09-17 14:36:05 +0200373 return( POLARSSL_ERR_X509_INVALID_NAME +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200374 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
375
376 val = &cur->val;
377 val->tag = *(*p)++;
378
379 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200380 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200381
382 val->p = *p;
383 *p += val->len;
384
385 cur->next = NULL;
386
387 return( 0 );
388}
389
390/*
391 * RelativeDistinguishedName ::=
392 * SET OF AttributeTypeAndValue
393 *
394 * AttributeTypeAndValue ::= SEQUENCE {
395 * type AttributeType,
396 * value AttributeValue }
397 *
398 * AttributeType ::= OBJECT IDENTIFIER
399 *
400 * AttributeValue ::= ANY DEFINED BY AttributeType
401 */
402int x509_get_name( unsigned char **p, const unsigned char *end,
403 x509_name *cur )
404{
405 int ret;
406 size_t len;
407 const unsigned char *end2;
408 x509_name *use;
409
410 if( ( ret = asn1_get_tag( p, end, &len,
411 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200412 return( POLARSSL_ERR_X509_INVALID_NAME + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200413
414 end2 = end;
415 end = *p + len;
416 use = cur;
417
418 do
419 {
420 if( ( ret = x509_get_attr_type_value( p, end, use ) ) != 0 )
421 return( ret );
422
423 if( *p != end )
424 {
425 use->next = (x509_name *) polarssl_malloc(
426 sizeof( x509_name ) );
427
428 if( use->next == NULL )
429 return( POLARSSL_ERR_X509_MALLOC_FAILED );
430
431 memset( use->next, 0, sizeof( x509_name ) );
432
433 use = use->next;
434 }
435 }
436 while( *p != end );
437
438 /*
439 * recurse until end of SEQUENCE is reached
440 */
441 if( *p == end2 )
442 return( 0 );
443
444 cur->next = (x509_name *) polarssl_malloc(
445 sizeof( x509_name ) );
446
447 if( cur->next == NULL )
448 return( POLARSSL_ERR_X509_MALLOC_FAILED );
449
450 memset( cur->next, 0, sizeof( x509_name ) );
451
452 return( x509_get_name( p, end2, cur->next ) );
453}
454
455/*
456 * Time ::= CHOICE {
457 * utcTime UTCTime,
458 * generalTime GeneralizedTime }
459 */
460int x509_get_time( unsigned char **p, const unsigned char *end,
461 x509_time *time )
462{
463 int ret;
464 size_t len;
465 char date[64];
466 unsigned char tag;
467
468 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200469 return( POLARSSL_ERR_X509_INVALID_DATE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200470 POLARSSL_ERR_ASN1_OUT_OF_DATA );
471
472 tag = **p;
473
474 if ( tag == ASN1_UTC_TIME )
475 {
476 (*p)++;
477 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200478
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200479 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200480 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200481
482 memset( date, 0, sizeof( date ) );
483 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
484 len : sizeof( date ) - 1 );
485
486 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
487 &time->year, &time->mon, &time->day,
488 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200489 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200490
491 time->year += 100 * ( time->year < 50 );
492 time->year += 1900;
493
494 *p += len;
495
496 return( 0 );
497 }
498 else if ( tag == ASN1_GENERALIZED_TIME )
499 {
500 (*p)++;
501 ret = asn1_get_len( p, end, &len );
Paul Bakker51876562013-09-17 14:36:05 +0200502
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200503 if( ret != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200504 return( POLARSSL_ERR_X509_INVALID_DATE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200505
506 memset( date, 0, sizeof( date ) );
507 memcpy( date, *p, ( len < sizeof( date ) - 1 ) ?
508 len : sizeof( date ) - 1 );
509
510 if( sscanf( date, "%4d%2d%2d%2d%2d%2d",
511 &time->year, &time->mon, &time->day,
512 &time->hour, &time->min, &time->sec ) < 5 )
Paul Bakker51876562013-09-17 14:36:05 +0200513 return( POLARSSL_ERR_X509_INVALID_DATE );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200514
515 *p += len;
516
517 return( 0 );
518 }
519 else
Paul Bakker51876562013-09-17 14:36:05 +0200520 return( POLARSSL_ERR_X509_INVALID_DATE +
521 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200522}
523
524int x509_get_sig( unsigned char **p, const unsigned char *end, x509_buf *sig )
525{
526 int ret;
527 size_t len;
528
529 if( ( end - *p ) < 1 )
Paul Bakker51876562013-09-17 14:36:05 +0200530 return( POLARSSL_ERR_X509_INVALID_SIGNATURE +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200531 POLARSSL_ERR_ASN1_OUT_OF_DATA );
532
533 sig->tag = **p;
534
535 if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200536 return( POLARSSL_ERR_X509_INVALID_SIGNATURE + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200537
538 sig->len = len;
539 sig->p = *p;
540
541 *p += len;
542
543 return( 0 );
544}
545
Manuel Pégourié-Gonnard5cac5832014-01-24 19:28:43 +0100546/*
547 * Get signature algorithm from alg OID and optional parameters
548 */
549int x509_get_sig_alg( const x509_buf *sig_oid, const x509_buf *sig_params,
550 md_type_t *md_alg, pk_type_t *pk_alg )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200551{
Manuel Pégourié-Gonnard5cac5832014-01-24 19:28:43 +0100552 int ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200553
Manuel Pégourié-Gonnard5cac5832014-01-24 19:28:43 +0100554 if( ( ret = oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200555 return( POLARSSL_ERR_X509_UNKNOWN_SIG_ALG + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200556
Manuel Pégourié-Gonnard5cac5832014-01-24 19:28:43 +0100557#if defined(POLARSSL_RSASSA_PSS_CERTIFICATES)
558 if( *pk_alg == POLARSSL_PK_RSASSA_PSS )
559 {
560 int salt_len, trailer_field;
561 md_type_t mgf_md;
562
563 /* Make sure params are valid */
564 ret = x509_get_rsassa_pss_params( sig_params,
565 md_alg, &mgf_md, &salt_len, &trailer_field );
566 if( ret != 0 )
567 return( ret );
568
569 }
570 else
571#endif
572 {
573 /* Make sure parameters are absent or NULL */
574 if( ( sig_params->tag != ASN1_NULL && sig_params->tag != 0 ) ||
575 sig_params->len != 0 )
576 return( POLARSSL_ERR_X509_INVALID_ALG );
577 }
578
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200579 return( 0 );
580}
581
582/*
583 * X.509 Extensions (No parsing of extensions, pointer should
584 * be either manually updated or extensions should be parsed!
585 */
586int x509_get_ext( unsigned char **p, const unsigned char *end,
587 x509_buf *ext, int tag )
588{
589 int ret;
590 size_t len;
591
592 if( *p == end )
593 return( 0 );
594
595 ext->tag = **p;
596
597 if( ( ret = asn1_get_tag( p, end, &ext->len,
598 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | tag ) ) != 0 )
599 return( ret );
600
601 ext->p = *p;
602 end = *p + ext->len;
603
604 /*
605 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
606 *
607 * Extension ::= SEQUENCE {
608 * extnID OBJECT IDENTIFIER,
609 * critical BOOLEAN DEFAULT FALSE,
610 * extnValue OCTET STRING }
611 */
612 if( ( ret = asn1_get_tag( p, end, &len,
613 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker51876562013-09-17 14:36:05 +0200614 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS + ret );
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200615
616 if( end != *p + len )
Paul Bakker51876562013-09-17 14:36:05 +0200617 return( POLARSSL_ERR_X509_INVALID_EXTENSIONS +
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200618 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
619
620 return( 0 );
621}
622
623#if defined(POLARSSL_FS_IO)
624/*
625 * Load all data from a file into a given buffer.
626 */
627int x509_load_file( const char *path, unsigned char **buf, size_t *n )
628{
629 FILE *f;
630 long size;
631
632 if( ( f = fopen( path, "rb" ) ) == NULL )
633 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
634
635 fseek( f, 0, SEEK_END );
636 if( ( size = ftell( f ) ) == -1 )
637 {
638 fclose( f );
639 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
640 }
641 fseek( f, 0, SEEK_SET );
642
643 *n = (size_t) size;
644
645 if( *n + 1 == 0 ||
646 ( *buf = (unsigned char *) polarssl_malloc( *n + 1 ) ) == NULL )
647 {
648 fclose( f );
649 return( POLARSSL_ERR_X509_MALLOC_FAILED );
650 }
651
652 if( fread( *buf, 1, *n, f ) != *n )
653 {
654 fclose( f );
655 polarssl_free( *buf );
656 return( POLARSSL_ERR_X509_FILE_IO_ERROR );
657 }
658
659 fclose( f );
660
661 (*buf)[*n] = '\0';
662
663 return( 0 );
664}
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200665#endif /* POLARSSL_FS_IO */
666
Paul Bakker6edcd412013-10-29 15:22:54 +0100667#if defined(_MSC_VER) && !defined snprintf && !defined(EFIX64) && \
668 !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200669#include <stdarg.h>
670
671#if !defined vsnprintf
672#define vsnprintf _vsnprintf
673#endif // vsnprintf
674
675/*
676 * Windows _snprintf and _vsnprintf are not compatible to linux versions.
677 * Result value is not size of buffer needed, but -1 if no fit is possible.
678 *
679 * This fuction tries to 'fix' this by at least suggesting enlarging the
680 * size by 20.
681 */
682static int compat_snprintf(char *str, size_t size, const char *format, ...)
683{
684 va_list ap;
685 int res = -1;
686
687 va_start( ap, format );
688
689 res = vsnprintf( str, size, format, ap );
690
691 va_end( ap );
692
693 // No quick fix possible
694 if ( res < 0 )
695 return( (int) size + 20 );
696
697 return res;
698}
699
700#define snprintf compat_snprintf
701#endif
702
703#define POLARSSL_ERR_DEBUG_BUF_TOO_SMALL -2
704
705#define SAFE_SNPRINTF() \
706{ \
707 if( ret == -1 ) \
708 return( -1 ); \
709 \
710 if ( (unsigned int) ret > n ) { \
711 p[n - 1] = '\0'; \
712 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;\
713 } \
714 \
715 n -= (unsigned int) ret; \
716 p += (unsigned int) ret; \
717}
718
719/*
720 * Store the name in printable form into buf; no more
721 * than size characters will be written
722 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200723int x509_dn_gets( char *buf, size_t size, const x509_name *dn )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200724{
725 int ret;
726 size_t i, n;
727 unsigned char c;
728 const x509_name *name;
729 const char *short_name = NULL;
730 char s[128], *p;
731
732 memset( s, 0, sizeof( s ) );
733
734 name = dn;
735 p = buf;
736 n = size;
737
738 while( name != NULL )
739 {
740 if( !name->oid.p )
741 {
742 name = name->next;
743 continue;
744 }
745
746 if( name != dn )
747 {
748 ret = snprintf( p, n, ", " );
749 SAFE_SNPRINTF();
750 }
751
752 ret = oid_get_attr_short_name( &name->oid, &short_name );
753
754 if( ret == 0 )
755 ret = snprintf( p, n, "%s=", short_name );
756 else
757 ret = snprintf( p, n, "\?\?=" );
758 SAFE_SNPRINTF();
759
760 for( i = 0; i < name->val.len; i++ )
761 {
762 if( i >= sizeof( s ) - 1 )
763 break;
764
765 c = name->val.p[i];
766 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
767 s[i] = '?';
768 else s[i] = c;
769 }
770 s[i] = '\0';
771 ret = snprintf( p, n, "%s", s );
772 SAFE_SNPRINTF();
773 name = name->next;
774 }
775
776 return( (int) ( size - n ) );
777}
778
779/*
780 * Store the serial in printable form into buf; no more
781 * than size characters will be written
782 */
Paul Bakker86d0c192013-09-18 11:11:02 +0200783int x509_serial_gets( char *buf, size_t size, const x509_buf *serial )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200784{
785 int ret;
786 size_t i, n, nr;
787 char *p;
788
789 p = buf;
790 n = size;
791
792 nr = ( serial->len <= 32 )
793 ? serial->len : 28;
794
795 for( i = 0; i < nr; i++ )
796 {
797 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
798 continue;
799
800 ret = snprintf( p, n, "%02X%s",
801 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
802 SAFE_SNPRINTF();
803 }
804
805 if( nr != serial->len )
806 {
807 ret = snprintf( p, n, "...." );
808 SAFE_SNPRINTF();
809 }
810
811 return( (int) ( size - n ) );
812}
813
814/*
Manuel Pégourié-Gonnard27b93ad2014-01-25 11:50:59 +0100815 * Helper for writing signature alrogithms
816 */
817int x509_sig_alg_gets( char *buf, size_t size, const x509_buf *sig_oid,
818 pk_type_t pk_alg, const x509_buf *sig_params )
819{
820 int ret;
821 char *p = buf;
822 size_t n = size;
823 const char *desc = NULL;
824
825 ret = oid_get_sig_alg_desc( sig_oid, &desc );
826 if( ret != 0 )
827 ret = snprintf( p, n, "???" );
828 else
829 ret = snprintf( p, n, "%s", desc );
830 SAFE_SNPRINTF();
831
832#if defined(POLARSSL_RSASSA_PSS_CERTIFICATES)
833 if( pk_alg == POLARSSL_PK_RSASSA_PSS )
834 {
835 md_type_t md_alg, mgf_md;
836 const md_info_t *md_info, *mgf_md_info;
837 int salt_len, trailer_field;
838
839 if( ( ret = x509_get_rsassa_pss_params( sig_params,
840 &md_alg, &mgf_md, &salt_len, &trailer_field ) ) != 0 )
841 return( ret );
842
843 md_info = md_info_from_type( md_alg );
844 mgf_md_info = md_info_from_type( mgf_md );
845
846 ret = snprintf( p, n, " (%s, MGF1-%s, 0x%02X, %d)",
847 md_info ? md_info->name : "???",
848 mgf_md_info ? mgf_md_info->name : "???",
849 salt_len, trailer_field );
850 SAFE_SNPRINTF();
851 }
852#else
853 ((void) pk_alg);
854 ((void) sig_params);
855#endif /* POLARSSL_RSASSA_PSS_CERTIFICATES */
856
857 return( (int) size - n );
858}
859
860/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200861 * Helper for writing "RSA key size", "EC key size", etc
862 */
863int x509_key_size_helper( char *buf, size_t size, const char *name )
864{
865 char *p = buf;
866 size_t n = size;
867 int ret;
868
869 if( strlen( name ) + sizeof( " key size" ) > size )
870 return POLARSSL_ERR_DEBUG_BUF_TOO_SMALL;
871
872 ret = snprintf( p, n, "%s key size", name );
873 SAFE_SNPRINTF();
874
875 return( 0 );
876}
877
878/*
879 * Return an informational string describing the given OID
880 */
881const char *x509_oid_get_description( x509_buf *oid )
882{
883 const char *desc = NULL;
884 int ret;
885
886 ret = oid_get_extended_key_usage( oid, &desc );
887
888 if( ret != 0 )
889 return( NULL );
890
891 return( desc );
892}
893
894/* Return the x.y.z.... style numeric string for the given OID */
895int x509_oid_get_numeric_string( char *buf, size_t size, x509_buf *oid )
896{
897 return oid_get_numeric_string( buf, size, oid );
898}
899
900/*
901 * Return 0 if the x509_time is still valid, or 1 otherwise.
902 */
903#if defined(POLARSSL_HAVE_TIME)
Paul Bakker86d0c192013-09-18 11:11:02 +0200904int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200905{
906 int year, mon, day;
907 int hour, min, sec;
908
Paul Bakkerfa6a6202013-10-28 18:48:30 +0100909#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200910 SYSTEMTIME st;
911
912 GetLocalTime(&st);
913
914 year = st.wYear;
915 mon = st.wMonth;
916 day = st.wDay;
917 hour = st.wHour;
918 min = st.wMinute;
919 sec = st.wSecond;
920#else
921 struct tm *lt;
922 time_t tt;
923
924 tt = time( NULL );
925 lt = localtime( &tt );
926
927 year = lt->tm_year + 1900;
928 mon = lt->tm_mon + 1;
929 day = lt->tm_mday;
930 hour = lt->tm_hour;
931 min = lt->tm_min;
932 sec = lt->tm_sec;
933#endif
934
935 if( year > to->year )
936 return( 1 );
937
938 if( year == to->year &&
939 mon > to->mon )
940 return( 1 );
941
942 if( year == to->year &&
943 mon == to->mon &&
944 day > to->day )
945 return( 1 );
946
947 if( year == to->year &&
948 mon == to->mon &&
949 day == to->day &&
950 hour > to->hour )
951 return( 1 );
952
953 if( year == to->year &&
954 mon == to->mon &&
955 day == to->day &&
956 hour == to->hour &&
957 min > to->min )
958 return( 1 );
959
960 if( year == to->year &&
961 mon == to->mon &&
962 day == to->day &&
963 hour == to->hour &&
964 min == to->min &&
965 sec > to->sec )
966 return( 1 );
967
968 return( 0 );
969}
970#else /* POLARSSL_HAVE_TIME */
Paul Bakker86d0c192013-09-18 11:11:02 +0200971int x509_time_expired( const x509_time *to )
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200972{
973 ((void) to);
974 return( 0 );
975}
976#endif /* POLARSSL_HAVE_TIME */
977
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200978#if defined(POLARSSL_SELF_TEST)
979
980#include "polarssl/x509_crt.h"
981#include "polarssl/certs.h"
982
983/*
984 * Checkup routine
985 */
986int x509_self_test( int verbose )
987{
988#if defined(POLARSSL_CERTS_C) && defined(POLARSSL_MD5_C)
989 int ret;
990 int flags;
Paul Bakkerc559c7a2013-09-18 14:13:26 +0200991 x509_crt cacert;
992 x509_crt clicert;
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200993
994 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +0100995 polarssl_printf( " X.509 certificate load: " );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200996
Paul Bakkerb6b09562013-09-18 14:17:41 +0200997 x509_crt_init( &clicert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +0200998
Paul Bakkerddf26b42013-09-18 13:46:23 +0200999 ret = x509_crt_parse( &clicert, (const unsigned char *) test_cli_crt,
1000 strlen( test_cli_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001001 if( ret != 0 )
1002 {
1003 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01001004 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001005
1006 return( ret );
1007 }
1008
Paul Bakkerb6b09562013-09-18 14:17:41 +02001009 x509_crt_init( &cacert );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001010
Paul Bakkerddf26b42013-09-18 13:46:23 +02001011 ret = x509_crt_parse( &cacert, (const unsigned char *) test_ca_crt,
1012 strlen( test_ca_crt ) );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001013 if( ret != 0 )
1014 {
1015 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01001016 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001017
1018 return( ret );
1019 }
1020
1021 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01001022 polarssl_printf( "passed\n X.509 signature verify: ");
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001023
Paul Bakkerddf26b42013-09-18 13:46:23 +02001024 ret = x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001025 if( ret != 0 )
1026 {
1027 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01001028 polarssl_printf( "failed\n" );
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001029
Paul Bakker7dc4c442014-02-01 22:50:26 +01001030 polarssl_printf("ret = %d, &flags = %04x\n", ret, flags);
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001031
1032 return( ret );
1033 }
1034
1035 if( verbose != 0 )
Paul Bakker7dc4c442014-02-01 22:50:26 +01001036 polarssl_printf( "passed\n\n");
Paul Bakkere9e6ae32013-09-16 22:53:25 +02001037
1038 x509_crt_free( &cacert );
1039 x509_crt_free( &clicert );
1040
1041 return( 0 );
1042#else
1043 ((void) verbose);
1044 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
1045#endif
1046}
1047
1048#endif
1049
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001050#endif /* POLARSSL_X509_USE_C */