blob: 9b68af4efe14e5b8d68dbe0e4d0fa504323fd55f [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * X.509 certificate and private key decoding
3 *
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00004 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
5 *
Paul Bakker785a9ee2009-01-25 14:15:10 +00006 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
Paul Bakker5121ce52009-01-03 21:22:43 +00007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The ITU-T X.509 standard defines a certificat format for PKI.
24 *
25 * http://www.ietf.org/rfc/rfc2459.txt
26 * http://www.ietf.org/rfc/rfc3279.txt
27 *
28 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
29 *
30 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
31 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
32 */
33
Paul Bakker40e46942009-01-03 21:51:57 +000034#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Paul Bakker40e46942009-01-03 21:51:57 +000036#if defined(POLARSSL_X509_PARSE_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Paul Bakker40e46942009-01-03 21:51:57 +000038#include "polarssl/x509.h"
39#include "polarssl/base64.h"
40#include "polarssl/des.h"
41#include "polarssl/md2.h"
42#include "polarssl/md4.h"
43#include "polarssl/md5.h"
44#include "polarssl/sha1.h"
Paul Bakker026c03b2009-03-28 17:53:03 +000045#include "polarssl/sha2.h"
46#include "polarssl/sha4.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000047
48#include <string.h>
49#include <stdlib.h>
50#include <stdio.h>
51#include <time.h>
52
53/*
54 * ASN.1 DER decoding routines
55 */
56static int asn1_get_len( unsigned char **p,
57 unsigned char *end,
58 int *len )
59{
60 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +000061 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000062
63 if( ( **p & 0x80 ) == 0 )
64 *len = *(*p)++;
65 else
66 {
67 switch( **p & 0x7F )
68 {
69 case 1:
70 if( ( end - *p ) < 2 )
Paul Bakker40e46942009-01-03 21:51:57 +000071 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000072
73 *len = (*p)[1];
74 (*p) += 2;
75 break;
76
77 case 2:
78 if( ( end - *p ) < 3 )
Paul Bakker40e46942009-01-03 21:51:57 +000079 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000080
81 *len = ( (*p)[1] << 8 ) | (*p)[2];
82 (*p) += 3;
83 break;
84
85 default:
Paul Bakker40e46942009-01-03 21:51:57 +000086 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +000087 break;
88 }
89 }
90
91 if( *len > (int) ( end - *p ) )
Paul Bakker40e46942009-01-03 21:51:57 +000092 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000093
94 return( 0 );
95}
96
97static int asn1_get_tag( unsigned char **p,
98 unsigned char *end,
99 int *len, int tag )
100{
101 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000102 return( POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000103
104 if( **p != tag )
Paul Bakker40e46942009-01-03 21:51:57 +0000105 return( POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
107 (*p)++;
108
109 return( asn1_get_len( p, end, len ) );
110}
111
112static int asn1_get_bool( unsigned char **p,
113 unsigned char *end,
114 int *val )
115{
116 int ret, len;
117
118 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BOOLEAN ) ) != 0 )
119 return( ret );
120
121 if( len != 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000122 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000123
124 *val = ( **p != 0 ) ? 1 : 0;
125 (*p)++;
126
127 return( 0 );
128}
129
130static int asn1_get_int( unsigned char **p,
131 unsigned char *end,
132 int *val )
133{
134 int ret, len;
135
136 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
137 return( ret );
138
139 if( len > (int) sizeof( int ) || ( **p & 0x80 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000140 return( POLARSSL_ERR_ASN1_INVALID_LENGTH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000141
142 *val = 0;
143
144 while( len-- > 0 )
145 {
146 *val = ( *val << 8 ) | **p;
147 (*p)++;
148 }
149
150 return( 0 );
151}
152
153static int asn1_get_mpi( unsigned char **p,
154 unsigned char *end,
155 mpi *X )
156{
157 int ret, len;
158
159 if( ( ret = asn1_get_tag( p, end, &len, ASN1_INTEGER ) ) != 0 )
160 return( ret );
161
162 ret = mpi_read_binary( X, *p, len );
163
164 *p += len;
165
166 return( ret );
167}
168
169/*
170 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
171 */
172static int x509_get_version( unsigned char **p,
173 unsigned char *end,
174 int *ver )
175{
176 int ret, len;
177
178 if( ( ret = asn1_get_tag( p, end, &len,
179 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) != 0 )
180 {
Paul Bakker40e46942009-01-03 21:51:57 +0000181 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000182 return( *ver = 0 );
183
184 return( ret );
185 }
186
187 end = *p + len;
188
189 if( ( ret = asn1_get_int( p, end, ver ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000190 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000191
192 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000193 return( POLARSSL_ERR_X509_CERT_INVALID_VERSION |
194 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000195
196 return( 0 );
197}
198
199/*
200 * CertificateSerialNumber ::= INTEGER
201 */
202static int x509_get_serial( unsigned char **p,
203 unsigned char *end,
204 x509_buf *serial )
205{
206 int ret;
207
208 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000209 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
210 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
212 if( **p != ( ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2 ) &&
213 **p != ASN1_INTEGER )
Paul Bakker40e46942009-01-03 21:51:57 +0000214 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL |
215 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000216
217 serial->tag = *(*p)++;
218
219 if( ( ret = asn1_get_len( p, end, &serial->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000220 return( POLARSSL_ERR_X509_CERT_INVALID_SERIAL | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
222 serial->p = *p;
223 *p += serial->len;
224
225 return( 0 );
226}
227
228/*
229 * AlgorithmIdentifier ::= SEQUENCE {
230 * algorithm OBJECT IDENTIFIER,
231 * parameters ANY DEFINED BY algorithm OPTIONAL }
232 */
233static int x509_get_alg( unsigned char **p,
234 unsigned char *end,
235 x509_buf *alg )
236{
237 int ret, len;
238
239 if( ( ret = asn1_get_tag( p, end, &len,
240 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000241 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242
243 end = *p + len;
244 alg->tag = **p;
245
246 if( ( ret = asn1_get_tag( p, end, &alg->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000247 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
249 alg->p = *p;
250 *p += alg->len;
251
252 if( *p == end )
253 return( 0 );
254
255 /*
256 * assume the algorithm parameters must be NULL
257 */
258 if( ( ret = asn1_get_tag( p, end, &len, ASN1_NULL ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000259 return( POLARSSL_ERR_X509_CERT_INVALID_ALG | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000260
261 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000262 return( POLARSSL_ERR_X509_CERT_INVALID_ALG |
263 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000264
265 return( 0 );
266}
267
268/*
269 * RelativeDistinguishedName ::=
270 * SET OF AttributeTypeAndValue
271 *
272 * AttributeTypeAndValue ::= SEQUENCE {
273 * type AttributeType,
274 * value AttributeValue }
275 *
276 * AttributeType ::= OBJECT IDENTIFIER
277 *
278 * AttributeValue ::= ANY DEFINED BY AttributeType
279 */
280static int x509_get_name( unsigned char **p,
281 unsigned char *end,
282 x509_name *cur )
283{
284 int ret, len;
285 unsigned char *end2;
286 x509_buf *oid;
287 x509_buf *val;
288
289 if( ( ret = asn1_get_tag( p, end, &len,
290 ASN1_CONSTRUCTED | ASN1_SET ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000291 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000292
293 end2 = end;
294 end = *p + len;
295
296 if( ( ret = asn1_get_tag( p, end, &len,
297 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000298 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000299
300 if( *p + len != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000301 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
302 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000303
304 oid = &cur->oid;
305 oid->tag = **p;
306
307 if( ( ret = asn1_get_tag( p, end, &oid->len, ASN1_OID ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000308 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000309
310 oid->p = *p;
311 *p += oid->len;
312
313 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000314 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
315 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000316
317 if( **p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
318 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
319 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING )
Paul Bakker40e46942009-01-03 21:51:57 +0000320 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
321 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000322
323 val = &cur->val;
324 val->tag = *(*p)++;
325
326 if( ( ret = asn1_get_len( p, end, &val->len ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000327 return( POLARSSL_ERR_X509_CERT_INVALID_NAME | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000328
329 val->p = *p;
330 *p += val->len;
331
332 cur->next = NULL;
333
334 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000335 return( POLARSSL_ERR_X509_CERT_INVALID_NAME |
336 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000337
338 /*
339 * recurse until end of SEQUENCE is reached
340 */
341 if( *p == end2 )
342 return( 0 );
343
344 cur->next = (x509_name *) malloc(
345 sizeof( x509_name ) );
346
347 if( cur->next == NULL )
348 return( 1 );
349
350 return( x509_get_name( p, end2, cur->next ) );
351}
352
353/*
354 * Validity ::= SEQUENCE {
355 * notBefore Time,
356 * notAfter Time }
357 *
358 * Time ::= CHOICE {
359 * utcTime UTCTime,
360 * generalTime GeneralizedTime }
361 */
362static int x509_get_dates( unsigned char **p,
363 unsigned char *end,
364 x509_time *from,
365 x509_time *to )
366{
367 int ret, len;
368 char date[64];
369
370 if( ( ret = asn1_get_tag( p, end, &len,
371 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000372 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000373
374 end = *p + len;
375
376 /*
377 * TODO: also handle GeneralizedTime
378 */
379 if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000380 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000381
382 memset( date, 0, sizeof( date ) );
383 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
384 len : (int) sizeof( date ) - 1 );
385
386 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
387 &from->year, &from->mon, &from->day,
388 &from->hour, &from->min, &from->sec ) < 5 )
Paul Bakker40e46942009-01-03 21:51:57 +0000389 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000390
391 from->year += 100 * ( from->year < 90 );
392 from->year += 1900;
393
394 *p += len;
395
396 if( ( ret = asn1_get_tag( p, end, &len, ASN1_UTC_TIME ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000397 return( POLARSSL_ERR_X509_CERT_INVALID_DATE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000398
399 memset( date, 0, sizeof( date ) );
400 memcpy( date, *p, ( len < (int) sizeof( date ) - 1 ) ?
401 len : (int) sizeof( date ) - 1 );
402
403 if( sscanf( date, "%2d%2d%2d%2d%2d%2d",
404 &to->year, &to->mon, &to->day,
405 &to->hour, &to->min, &to->sec ) < 5 )
Paul Bakker40e46942009-01-03 21:51:57 +0000406 return( POLARSSL_ERR_X509_CERT_INVALID_DATE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
408 to->year += 100 * ( to->year < 90 );
409 to->year += 1900;
410
411 *p += len;
412
413 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000414 return( POLARSSL_ERR_X509_CERT_INVALID_DATE |
415 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000416
417 return( 0 );
418}
419
420/*
421 * SubjectPublicKeyInfo ::= SEQUENCE {
422 * algorithm AlgorithmIdentifier,
423 * subjectPublicKey BIT STRING }
424 */
425static int x509_get_pubkey( unsigned char **p,
426 unsigned char *end,
427 x509_buf *pk_alg_oid,
428 mpi *N, mpi *E )
429{
430 int ret, len;
431 unsigned char *end2;
432
433 if( ( ret = x509_get_alg( p, end, pk_alg_oid ) ) != 0 )
434 return( ret );
435
436 /*
437 * only RSA public keys handled at this time
438 */
439 if( pk_alg_oid->len != 9 ||
440 memcmp( pk_alg_oid->p, OID_PKCS1_RSA, 9 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000441 return( POLARSSL_ERR_X509_CERT_UNKNOWN_PK_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000444 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000445
446 if( ( end - *p ) < 1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000447 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
448 POLARSSL_ERR_ASN1_OUT_OF_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450 end2 = *p + len;
451
452 if( *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000453 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
455 /*
456 * RSAPublicKey ::= SEQUENCE {
457 * modulus INTEGER, -- n
458 * publicExponent INTEGER -- e
459 * }
460 */
461 if( ( ret = asn1_get_tag( p, end2, &len,
462 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000463 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
465 if( *p + len != end2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000466 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
467 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 if( ( ret = asn1_get_mpi( p, end2, N ) ) != 0 ||
470 ( ret = asn1_get_mpi( p, end2, E ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000471 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
473 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000474 return( POLARSSL_ERR_X509_CERT_INVALID_PUBKEY |
475 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000476
477 return( 0 );
478}
479
480static int x509_get_sig( unsigned char **p,
481 unsigned char *end,
482 x509_buf *sig )
483{
484 int ret, len;
485
486 sig->tag = **p;
487
488 if( ( ret = asn1_get_tag( p, end, &len, ASN1_BIT_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000489 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000490
491 if( --len < 1 || *(*p)++ != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000492 return( POLARSSL_ERR_X509_CERT_INVALID_SIGNATURE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000493
494 sig->len = len;
495 sig->p = *p;
496
497 *p += len;
498
499 return( 0 );
500}
501
502/*
503 * X.509 v2/v3 unique identifier (not parsed)
504 */
505static int x509_get_uid( unsigned char **p,
506 unsigned char *end,
507 x509_buf *uid, int n )
508{
509 int ret;
510
511 if( *p == end )
512 return( 0 );
513
514 uid->tag = **p;
515
516 if( ( ret = asn1_get_tag( p, end, &uid->len,
517 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n ) ) != 0 )
518 {
Paul Bakker40e46942009-01-03 21:51:57 +0000519 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000520 return( 0 );
521
522 return( ret );
523 }
524
525 uid->p = *p;
526 *p += uid->len;
527
528 return( 0 );
529}
530
531/*
532 * X.509 v3 extensions (only BasicConstraints are parsed)
533 */
534static int x509_get_ext( unsigned char **p,
535 unsigned char *end,
536 x509_buf *ext,
537 int *ca_istrue,
538 int *max_pathlen )
539{
540 int ret, len;
541 int is_critical = 1;
542 int is_cacert = 0;
543 unsigned char *end2;
544
545 if( *p == end )
546 return( 0 );
547
548 ext->tag = **p;
549
550 if( ( ret = asn1_get_tag( p, end, &ext->len,
551 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ) != 0 )
552 {
Paul Bakker40e46942009-01-03 21:51:57 +0000553 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000554 return( 0 );
555
556 return( ret );
557 }
558
559 ext->p = *p;
560 end = *p + ext->len;
561
562 /*
563 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
564 *
565 * Extension ::= SEQUENCE {
566 * extnID OBJECT IDENTIFIER,
567 * critical BOOLEAN DEFAULT FALSE,
568 * extnValue OCTET STRING }
569 */
570 if( ( ret = asn1_get_tag( p, end, &len,
571 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000572 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
574 if( end != *p + len )
Paul Bakker40e46942009-01-03 21:51:57 +0000575 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
576 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
578 while( *p < end )
579 {
580 if( ( ret = asn1_get_tag( p, end, &len,
581 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000582 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
584 if( memcmp( *p, "\x06\x03\x55\x1D\x13", 5 ) != 0 )
585 {
586 *p += len;
587 continue;
588 }
589
590 *p += 5;
591
592 if( ( ret = asn1_get_bool( p, end, &is_critical ) ) != 0 &&
Paul Bakker40e46942009-01-03 21:51:57 +0000593 ( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) )
594 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000595
596 if( ( ret = asn1_get_tag( p, end, &len,
597 ASN1_OCTET_STRING ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000598 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000599
600 /*
601 * BasicConstraints ::= SEQUENCE {
602 * cA BOOLEAN DEFAULT FALSE,
603 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
604 */
605 end2 = *p + len;
606
607 if( ( ret = asn1_get_tag( p, end2, &len,
608 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000609 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000610
611 if( *p == end2 )
612 continue;
613
614 if( ( ret = asn1_get_bool( p, end2, &is_cacert ) ) != 0 )
615 {
Paul Bakker40e46942009-01-03 21:51:57 +0000616 if( ret == POLARSSL_ERR_ASN1_UNEXPECTED_TAG )
Paul Bakker5121ce52009-01-03 21:22:43 +0000617 ret = asn1_get_int( p, end2, &is_cacert );
618
619 if( ret != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000620 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000621
622 if( is_cacert != 0 )
623 is_cacert = 1;
624 }
625
626 if( *p == end2 )
627 continue;
628
629 if( ( ret = asn1_get_int( p, end2, max_pathlen ) ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000630 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000631
632 if( *p != end2 )
Paul Bakker40e46942009-01-03 21:51:57 +0000633 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
634 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000635
636 max_pathlen++;
637 }
638
639 if( *p != end )
Paul Bakker40e46942009-01-03 21:51:57 +0000640 return( POLARSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
641 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000642
643 *ca_istrue = is_critical & is_cacert;
644
645 return( 0 );
646}
647
648/*
649 * Parse one or more certificates and add them to the chained list
650 */
651int x509parse_crt( x509_cert *chain, unsigned char *buf, int buflen )
652{
653 int ret, len;
654 unsigned char *s1, *s2;
655 unsigned char *p, *end;
656 x509_cert *crt;
657
658 crt = chain;
659
660 while( crt->version != 0 )
661 crt = crt->next;
662
663 /*
664 * check if the certificate is encoded in base64
665 */
666 s1 = (unsigned char *) strstr( (char *) buf,
667 "-----BEGIN CERTIFICATE-----" );
668
669 if( s1 != NULL )
670 {
671 s2 = (unsigned char *) strstr( (char *) buf,
672 "-----END CERTIFICATE-----" );
673
674 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +0000675 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
677 s1 += 27;
678 if( *s1 == '\r' ) s1++;
679 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +0000680 else return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000681
682 /*
683 * get the DER data length and decode the buffer
684 */
685 len = 0;
686 ret = base64_decode( NULL, &len, s1, s2 - s1 );
687
Paul Bakker40e46942009-01-03 21:51:57 +0000688 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
689 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000690
691 if( ( p = (unsigned char *) malloc( len ) ) == NULL )
692 return( 1 );
693
694 if( ( ret = base64_decode( p, &len, s1, s2 - s1 ) ) != 0 )
695 {
696 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000697 return( POLARSSL_ERR_X509_CERT_INVALID_PEM | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000698 }
699
700 /*
701 * update the buffer size and offset
702 */
703 s2 += 25;
704 if( *s2 == '\r' ) s2++;
705 if( *s2 == '\n' ) s2++;
706 else
707 {
708 free( p );
Paul Bakker40e46942009-01-03 21:51:57 +0000709 return( POLARSSL_ERR_X509_CERT_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +0000710 }
711
712 buflen -= s2 - buf;
713 buf = s2;
714 }
715 else
716 {
717 /*
718 * nope, copy the raw DER data
719 */
720 p = (unsigned char *) malloc( len = buflen );
721
722 if( p == NULL )
723 return( 1 );
724
725 memcpy( p, buf, buflen );
726
727 buflen = 0;
728 }
729
730 crt->raw.p = p;
731 crt->raw.len = len;
732 end = p + len;
733
734 /*
735 * Certificate ::= SEQUENCE {
736 * tbsCertificate TBSCertificate,
737 * signatureAlgorithm AlgorithmIdentifier,
738 * signatureValue BIT STRING }
739 */
740 if( ( ret = asn1_get_tag( &p, end, &len,
741 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
742 {
743 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000744 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 }
746
747 if( len != (int) ( end - p ) )
748 {
749 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000750 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
751 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000752 }
753
754 /*
755 * TBSCertificate ::= SEQUENCE {
756 */
757 crt->tbs.p = p;
758
759 if( ( ret = asn1_get_tag( &p, end, &len,
760 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
761 {
762 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000763 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000764 }
765
766 end = p + len;
767 crt->tbs.len = end - crt->tbs.p;
768
769 /*
770 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
771 *
772 * CertificateSerialNumber ::= INTEGER
773 *
774 * signature AlgorithmIdentifier
775 */
776 if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 ||
777 ( ret = x509_get_serial( &p, end, &crt->serial ) ) != 0 ||
778 ( ret = x509_get_alg( &p, end, &crt->sig_oid1 ) ) != 0 )
779 {
780 x509_free( crt );
781 return( ret );
782 }
783
784 crt->version++;
785
786 if( crt->version > 3 )
787 {
788 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000789 return( POLARSSL_ERR_X509_CERT_UNKNOWN_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +0000790 }
791
792 if( crt->sig_oid1.len != 9 ||
793 memcmp( crt->sig_oid1.p, OID_PKCS1, 8 ) != 0 )
794 {
795 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000796 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000797 }
798
799 if( crt->sig_oid1.p[8] < 2 ||
Paul Bakker4593aea2009-02-09 22:32:35 +0000800 ( crt->sig_oid1.p[8] > 5 && crt->sig_oid1.p[8] < 11 ) ||
801 crt->sig_oid1.p[8] > 14 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000802 {
803 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000804 return( POLARSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +0000805 }
806
807 /*
808 * issuer Name
809 */
810 crt->issuer_raw.p = p;
811
812 if( ( ret = asn1_get_tag( &p, end, &len,
813 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
814 {
815 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000816 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000817 }
818
819 if( ( ret = x509_get_name( &p, p + len, &crt->issuer ) ) != 0 )
820 {
821 x509_free( crt );
822 return( ret );
823 }
824
825 crt->issuer_raw.len = p - crt->issuer_raw.p;
826
827 /*
828 * Validity ::= SEQUENCE {
829 * notBefore Time,
830 * notAfter Time }
831 *
832 */
833 if( ( ret = x509_get_dates( &p, end, &crt->valid_from,
834 &crt->valid_to ) ) != 0 )
835 {
836 x509_free( crt );
837 return( ret );
838 }
839
840 /*
841 * subject Name
842 */
843 crt->subject_raw.p = p;
844
845 if( ( ret = asn1_get_tag( &p, end, &len,
846 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
847 {
848 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000849 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000850 }
851
852 if( ( ret = x509_get_name( &p, p + len, &crt->subject ) ) != 0 )
853 {
854 x509_free( crt );
855 return( ret );
856 }
857
858 crt->subject_raw.len = p - crt->subject_raw.p;
859
860 /*
861 * SubjectPublicKeyInfo ::= SEQUENCE
862 * algorithm AlgorithmIdentifier,
863 * subjectPublicKey BIT STRING }
864 */
865 if( ( ret = asn1_get_tag( &p, end, &len,
866 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
867 {
868 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000869 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000870 }
871
872 if( ( ret = x509_get_pubkey( &p, p + len, &crt->pk_oid,
873 &crt->rsa.N, &crt->rsa.E ) ) != 0 )
874 {
875 x509_free( crt );
876 return( ret );
877 }
878
879 if( ( ret = rsa_check_pubkey( &crt->rsa ) ) != 0 )
880 {
881 x509_free( crt );
882 return( ret );
883 }
884
885 crt->rsa.len = mpi_size( &crt->rsa.N );
886
887 /*
888 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
889 * -- If present, version shall be v2 or v3
890 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
891 * -- If present, version shall be v2 or v3
892 * extensions [3] EXPLICIT Extensions OPTIONAL
893 * -- If present, version shall be v3
894 */
895 if( crt->version == 2 || crt->version == 3 )
896 {
897 ret = x509_get_uid( &p, end, &crt->issuer_id, 1 );
898 if( ret != 0 )
899 {
900 x509_free( crt );
901 return( ret );
902 }
903 }
904
905 if( crt->version == 2 || crt->version == 3 )
906 {
907 ret = x509_get_uid( &p, end, &crt->subject_id, 2 );
908 if( ret != 0 )
909 {
910 x509_free( crt );
911 return( ret );
912 }
913 }
914
915 if( crt->version == 3 )
916 {
917 ret = x509_get_ext( &p, end, &crt->v3_ext,
918 &crt->ca_istrue, &crt->max_pathlen );
919 if( ret != 0 )
920 {
921 x509_free( crt );
922 return( ret );
923 }
924 }
925
926 if( p != end )
927 {
928 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000929 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
930 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000931 }
932
933 end = crt->raw.p + crt->raw.len;
934
935 /*
936 * signatureAlgorithm AlgorithmIdentifier,
937 * signatureValue BIT STRING
938 */
939 if( ( ret = x509_get_alg( &p, end, &crt->sig_oid2 ) ) != 0 )
940 {
941 x509_free( crt );
942 return( ret );
943 }
944
945 if( memcmp( crt->sig_oid1.p, crt->sig_oid2.p, 9 ) != 0 )
946 {
947 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000948 return( POLARSSL_ERR_X509_CERT_SIG_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000949 }
950
951 if( ( ret = x509_get_sig( &p, end, &crt->sig ) ) != 0 )
952 {
953 x509_free( crt );
954 return( ret );
955 }
956
957 if( p != end )
958 {
959 x509_free( crt );
Paul Bakker40e46942009-01-03 21:51:57 +0000960 return( POLARSSL_ERR_X509_CERT_INVALID_FORMAT |
961 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +0000962 }
963
964 crt->next = (x509_cert *) malloc( sizeof( x509_cert ) );
965
966 if( crt->next == NULL )
967 {
968 x509_free( crt );
969 return( 1 );
970 }
971
972 crt = crt->next;
973 memset( crt, 0, sizeof( x509_cert ) );
974
975 if( buflen > 0 )
976 return( x509parse_crt( crt, buf, buflen ) );
977
978 return( 0 );
979}
980
981/*
982 * Load one or more certificates and add them to the chained list
983 */
984int x509parse_crtfile( x509_cert *chain, char *path )
985{
986 int ret;
987 FILE *f;
988 size_t n;
989 unsigned char *buf;
990
991 if( ( f = fopen( path, "rb" ) ) == NULL )
992 return( 1 );
993
994 fseek( f, 0, SEEK_END );
995 n = (size_t) ftell( f );
996 fseek( f, 0, SEEK_SET );
997
998 if( ( buf = (unsigned char *) malloc( n + 1 ) ) == NULL )
999 return( 1 );
1000
1001 if( fread( buf, 1, n, f ) != n )
1002 {
1003 fclose( f );
1004 free( buf );
1005 return( 1 );
1006 }
1007
1008 buf[n] = '\0';
1009
1010 ret = x509parse_crt( chain, buf, (int) n );
1011
1012 memset( buf, 0, n + 1 );
1013 free( buf );
1014 fclose( f );
1015
1016 return( ret );
1017}
1018
Paul Bakker40e46942009-01-03 21:51:57 +00001019#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001020/*
1021 * Read a 16-byte hex string and convert it to binary
1022 */
1023static int x509_get_iv( unsigned char *s, unsigned char iv[8] )
1024{
1025 int i, j, k;
1026
1027 memset( iv, 0, 8 );
1028
1029 for( i = 0; i < 16; i++, s++ )
1030 {
1031 if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
1032 if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
1033 if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
Paul Bakker40e46942009-01-03 21:51:57 +00001034 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001035
1036 k = ( ( i & 1 ) != 0 ) ? j : j << 4;
1037
1038 iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
1039 }
1040
1041 return( 0 );
1042}
1043
1044/*
1045 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
1046 */
1047static void x509_des3_decrypt( unsigned char des3_iv[8],
1048 unsigned char *buf, int buflen,
1049 unsigned char *pwd, int pwdlen )
1050{
1051 md5_context md5_ctx;
1052 des3_context des3_ctx;
1053 unsigned char md5sum[16];
1054 unsigned char des3_key[24];
1055
1056 /*
1057 * 3DES key[ 0..15] = MD5(pwd || IV)
1058 * key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
1059 */
1060 md5_starts( &md5_ctx );
1061 md5_update( &md5_ctx, pwd, pwdlen );
1062 md5_update( &md5_ctx, des3_iv, 8 );
1063 md5_finish( &md5_ctx, md5sum );
1064 memcpy( des3_key, md5sum, 16 );
1065
1066 md5_starts( &md5_ctx );
1067 md5_update( &md5_ctx, md5sum, 16 );
1068 md5_update( &md5_ctx, pwd, pwdlen );
1069 md5_update( &md5_ctx, des3_iv, 8 );
1070 md5_finish( &md5_ctx, md5sum );
1071 memcpy( des3_key + 16, md5sum, 8 );
1072
1073 des3_set3key_dec( &des3_ctx, des3_key );
1074 des3_crypt_cbc( &des3_ctx, DES_DECRYPT, buflen,
1075 des3_iv, buf, buf );
1076
1077 memset( &md5_ctx, 0, sizeof( md5_ctx ) );
1078 memset( &des3_ctx, 0, sizeof( des3_ctx ) );
1079 memset( md5sum, 0, 16 );
1080 memset( des3_key, 0, 24 );
1081}
1082#endif
1083
1084/*
1085 * Parse a private RSA key
1086 */
1087int x509parse_key( rsa_context *rsa, unsigned char *buf, int buflen,
1088 unsigned char *pwd, int pwdlen )
1089{
1090 int ret, len, enc;
1091 unsigned char *s1, *s2;
1092 unsigned char *p, *end;
1093 unsigned char des3_iv[8];
1094
1095 s1 = (unsigned char *) strstr( (char *) buf,
1096 "-----BEGIN RSA PRIVATE KEY-----" );
1097
1098 if( s1 != NULL )
1099 {
1100 s2 = (unsigned char *) strstr( (char *) buf,
1101 "-----END RSA PRIVATE KEY-----" );
1102
1103 if( s2 == NULL || s2 <= s1 )
Paul Bakker40e46942009-01-03 21:51:57 +00001104 return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001105
1106 s1 += 31;
1107 if( *s1 == '\r' ) s1++;
1108 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001109 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001110
1111 enc = 0;
1112
1113 if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
1114 {
Paul Bakker40e46942009-01-03 21:51:57 +00001115#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001116 enc++;
1117
1118 s1 += 22;
1119 if( *s1 == '\r' ) s1++;
1120 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001121 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001122
1123 if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001124 return( POLARSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG );
Paul Bakker5121ce52009-01-03 21:22:43 +00001125
1126 s1 += 23;
1127 if( x509_get_iv( s1, des3_iv ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001128 return( POLARSSL_ERR_X509_KEY_INVALID_ENC_IV );
Paul Bakker5121ce52009-01-03 21:22:43 +00001129
1130 s1 += 16;
1131 if( *s1 == '\r' ) s1++;
1132 if( *s1 == '\n' ) s1++;
Paul Bakker40e46942009-01-03 21:51:57 +00001133 else return( POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001134#else
Paul Bakker40e46942009-01-03 21:51:57 +00001135 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001136#endif
1137 }
1138
1139 len = 0;
1140 ret = base64_decode( NULL, &len, s1, s2 - s1 );
1141
Paul Bakker40e46942009-01-03 21:51:57 +00001142 if( ret == POLARSSL_ERR_BASE64_INVALID_CHARACTER )
1143 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001144
1145 if( ( buf = (unsigned char *) malloc( len ) ) == NULL )
1146 return( 1 );
1147
1148 if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
1149 {
1150 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001151 return( ret | POLARSSL_ERR_X509_KEY_INVALID_PEM );
Paul Bakker5121ce52009-01-03 21:22:43 +00001152 }
1153
1154 buflen = len;
1155
1156 if( enc != 0 )
1157 {
Paul Bakker40e46942009-01-03 21:51:57 +00001158#if defined(POLARSSL_DES_C)
Paul Bakker5121ce52009-01-03 21:22:43 +00001159 if( pwd == NULL )
1160 {
1161 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001162 return( POLARSSL_ERR_X509_KEY_PASSWORD_REQUIRED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001163 }
1164
1165 x509_des3_decrypt( des3_iv, buf, buflen, pwd, pwdlen );
1166
1167 if( buf[0] != 0x30 || buf[1] != 0x82 ||
1168 buf[4] != 0x02 || buf[5] != 0x01 )
1169 {
1170 free( buf );
Paul Bakker40e46942009-01-03 21:51:57 +00001171 return( POLARSSL_ERR_X509_KEY_PASSWORD_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001172 }
1173#else
Paul Bakker40e46942009-01-03 21:51:57 +00001174 return( POLARSSL_ERR_X509_FEATURE_UNAVAILABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001175#endif
1176 }
1177 }
1178
1179 memset( rsa, 0, sizeof( rsa_context ) );
1180
1181 p = buf;
1182 end = buf + buflen;
1183
1184 /*
1185 * RSAPrivateKey ::= SEQUENCE {
1186 * version Version,
1187 * modulus INTEGER, -- n
1188 * publicExponent INTEGER, -- e
1189 * privateExponent INTEGER, -- d
1190 * prime1 INTEGER, -- p
1191 * prime2 INTEGER, -- q
1192 * exponent1 INTEGER, -- d mod (p-1)
1193 * exponent2 INTEGER, -- d mod (q-1)
1194 * coefficient INTEGER, -- (inverse of q) mod p
1195 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1196 * }
1197 */
1198 if( ( ret = asn1_get_tag( &p, end, &len,
1199 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
1200 {
1201 if( s1 != NULL )
1202 free( buf );
1203
1204 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001205 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001206 }
1207
1208 end = p + len;
1209
1210 if( ( ret = asn1_get_int( &p, end, &rsa->ver ) ) != 0 )
1211 {
1212 if( s1 != NULL )
1213 free( buf );
1214
1215 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001216 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT | ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001217 }
1218
1219 if( rsa->ver != 0 )
1220 {
1221 if( s1 != NULL )
1222 free( buf );
1223
1224 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001225 return( ret | POLARSSL_ERR_X509_KEY_INVALID_VERSION );
Paul Bakker5121ce52009-01-03 21:22:43 +00001226 }
1227
1228 if( ( ret = asn1_get_mpi( &p, end, &rsa->N ) ) != 0 ||
1229 ( ret = asn1_get_mpi( &p, end, &rsa->E ) ) != 0 ||
1230 ( ret = asn1_get_mpi( &p, end, &rsa->D ) ) != 0 ||
1231 ( ret = asn1_get_mpi( &p, end, &rsa->P ) ) != 0 ||
1232 ( ret = asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 ||
1233 ( ret = asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 ||
1234 ( ret = asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 ||
1235 ( ret = asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
1236 {
1237 if( s1 != NULL )
1238 free( buf );
1239
1240 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001241 return( ret | POLARSSL_ERR_X509_KEY_INVALID_FORMAT );
Paul Bakker5121ce52009-01-03 21:22:43 +00001242 }
1243
1244 rsa->len = mpi_size( &rsa->N );
1245
1246 if( p != end )
1247 {
1248 if( s1 != NULL )
1249 free( buf );
1250
1251 rsa_free( rsa );
Paul Bakker40e46942009-01-03 21:51:57 +00001252 return( POLARSSL_ERR_X509_KEY_INVALID_FORMAT |
1253 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
Paul Bakker5121ce52009-01-03 21:22:43 +00001254 }
1255
1256 if( ( ret = rsa_check_privkey( rsa ) ) != 0 )
1257 {
1258 if( s1 != NULL )
1259 free( buf );
1260
1261 rsa_free( rsa );
1262 return( ret );
1263 }
1264
1265 if( s1 != NULL )
1266 free( buf );
1267
1268 return( 0 );
1269}
1270
1271/*
1272 * Load and parse a private RSA key
1273 */
1274int x509parse_keyfile( rsa_context *rsa, char *path, char *pwd )
1275{
1276 int ret;
1277 FILE *f;
1278 size_t n;
1279 unsigned char *buf;
1280
1281 if( ( f = fopen( path, "rb" ) ) == NULL )
1282 return( 1 );
1283
1284 fseek( f, 0, SEEK_END );
1285 n = (size_t) ftell( f );
1286 fseek( f, 0, SEEK_SET );
1287
1288 if( ( buf = (unsigned char *) malloc( n + 1 ) ) == NULL )
1289 return( 1 );
1290
1291 if( fread( buf, 1, n, f ) != n )
1292 {
1293 fclose( f );
1294 free( buf );
1295 return( 1 );
1296 }
1297
1298 buf[n] = '\0';
1299
1300 if( pwd == NULL )
1301 ret = x509parse_key( rsa, buf, (int) n, NULL, 0 );
1302 else
1303 ret = x509parse_key( rsa, buf, (int) n,
1304 (unsigned char *) pwd, strlen( pwd ) );
1305
1306 memset( buf, 0, n + 1 );
1307 free( buf );
1308 fclose( f );
1309
1310 return( ret );
1311}
1312
1313#if defined _MSC_VER && !defined snprintf
1314#define snprintf _snprintf
1315#endif
1316
1317/*
1318 * Store the name in printable form into buf; no more
1319 * than (end - buf) characters will be written
1320 */
1321int x509parse_dn_gets( char *buf, char *end, x509_name *dn )
1322{
1323 int i;
1324 unsigned char c;
1325 x509_name *name;
1326 char s[128], *p;
1327
1328 memset( s, 0, sizeof( s ) );
1329
1330 name = dn;
1331 p = buf;
1332
1333 while( name != NULL )
1334 {
1335 if( name != dn )
1336 p += snprintf( p, end - p, ", " );
1337
1338 if( memcmp( name->oid.p, OID_X520, 2 ) == 0 )
1339 {
1340 switch( name->oid.p[2] )
1341 {
1342 case X520_COMMON_NAME:
1343 p += snprintf( p, end - p, "CN=" ); break;
1344
1345 case X520_COUNTRY:
1346 p += snprintf( p, end - p, "C=" ); break;
1347
1348 case X520_LOCALITY:
1349 p += snprintf( p, end - p, "L=" ); break;
1350
1351 case X520_STATE:
1352 p += snprintf( p, end - p, "ST=" ); break;
1353
1354 case X520_ORGANIZATION:
1355 p += snprintf( p, end - p, "O=" ); break;
1356
1357 case X520_ORG_UNIT:
1358 p += snprintf( p, end - p, "OU=" ); break;
1359
1360 default:
1361 p += snprintf( p, end - p, "0x%02X=",
1362 name->oid.p[2] );
1363 break;
1364 }
1365 }
1366 else if( memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 )
1367 {
1368 switch( name->oid.p[8] )
1369 {
1370 case PKCS9_EMAIL:
1371 p += snprintf( p, end - p, "emailAddress=" ); break;
1372
1373 default:
1374 p += snprintf( p, end - p, "0x%02X=",
1375 name->oid.p[8] );
1376 break;
1377 }
1378 }
1379 else
1380 p += snprintf( p, end - p, "\?\?=" );
1381
1382 for( i = 0; i < name->val.len; i++ )
1383 {
1384 if( i >= (int) sizeof( s ) - 1 )
1385 break;
1386
1387 c = name->val.p[i];
1388 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
1389 s[i] = '?';
1390 else s[i] = c;
1391 }
1392 s[i] = '\0';
1393 p += snprintf( p, end - p, "%s", s );
1394 name = name->next;
1395 }
1396
1397 return( p - buf );
1398}
1399
1400/*
1401 * Return an informational string about the
1402 * certificate, or NULL if memory allocation failed
1403 */
1404char *x509parse_cert_info( char *prefix, x509_cert *crt )
1405{
1406 int i, n;
1407 char *p, *end;
Paul Bakker3681b112009-02-07 17:14:21 +00001408 static char buf[1024];
Paul Bakker5121ce52009-01-03 21:22:43 +00001409
1410 p = buf;
1411 end = buf + sizeof( buf ) - 1;
1412
1413 p += snprintf( p, end - p, "%scert. version : %d\n",
1414 prefix, crt->version );
1415 p += snprintf( p, end - p, "%sserial number : ",
1416 prefix );
1417
1418 n = ( crt->serial.len <= 32 )
1419 ? crt->serial.len : 32;
1420
1421 for( i = 0; i < n; i++ )
1422 p += snprintf( p, end - p, "%02X%s",
1423 crt->serial.p[i], ( i < n - 1 ) ? ":" : "" );
1424
1425 p += snprintf( p, end - p, "\n%sissuer name : ", prefix );
1426 p += x509parse_dn_gets( p, end, &crt->issuer );
1427
1428 p += snprintf( p, end - p, "\n%ssubject name : ", prefix );
1429 p += x509parse_dn_gets( p, end, &crt->subject );
1430
1431 p += snprintf( p, end - p, "\n%sissued on : " \
1432 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1433 crt->valid_from.year, crt->valid_from.mon,
1434 crt->valid_from.day, crt->valid_from.hour,
1435 crt->valid_from.min, crt->valid_from.sec );
1436
1437 p += snprintf( p, end - p, "\n%sexpires on : " \
1438 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1439 crt->valid_to.year, crt->valid_to.mon,
1440 crt->valid_to.day, crt->valid_to.hour,
1441 crt->valid_to.min, crt->valid_to.sec );
1442
1443 p += snprintf( p, end - p, "\n%ssigned using : RSA+", prefix );
1444
1445 switch( crt->sig_oid1.p[8] )
1446 {
Paul Bakker4593aea2009-02-09 22:32:35 +00001447 case SIG_RSA_MD2 : p += snprintf( p, end - p, "MD2" ); break;
1448 case SIG_RSA_MD4 : p += snprintf( p, end - p, "MD4" ); break;
1449 case SIG_RSA_MD5 : p += snprintf( p, end - p, "MD5" ); break;
1450 case SIG_RSA_SHA1 : p += snprintf( p, end - p, "SHA1" ); break;
1451 case SIG_RSA_SHA224 : p += snprintf( p, end - p, "SHA224" ); break;
1452 case SIG_RSA_SHA256 : p += snprintf( p, end - p, "SHA256" ); break;
1453 case SIG_RSA_SHA384 : p += snprintf( p, end - p, "SHA384" ); break;
1454 case SIG_RSA_SHA512 : p += snprintf( p, end - p, "SHA512" ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001455 default: p += snprintf( p, end - p, "???" ); break;
1456 }
1457
1458 p += snprintf( p, end - p, "\n%sRSA key size : %d bits\n", prefix,
1459 crt->rsa.N.n * (int) sizeof( unsigned long ) * 8 );
1460
1461 return( buf );
1462}
1463
1464/*
1465 * Return 0 if the certificate is still valid, or BADCERT_EXPIRED
1466 */
1467int x509parse_expired( x509_cert *crt )
1468{
1469 struct tm *lt;
1470 time_t tt;
1471
1472 tt = time( NULL );
1473 lt = localtime( &tt );
1474
1475 if( lt->tm_year > crt->valid_to.year - 1900 )
1476 return( BADCERT_EXPIRED );
1477
1478 if( lt->tm_year == crt->valid_to.year - 1900 &&
1479 lt->tm_mon > crt->valid_to.mon - 1 )
1480 return( BADCERT_EXPIRED );
1481
1482 if( lt->tm_year == crt->valid_to.year - 1900 &&
1483 lt->tm_mon == crt->valid_to.mon - 1 &&
1484 lt->tm_mday > crt->valid_to.day )
1485 return( BADCERT_EXPIRED );
1486
1487 return( 0 );
1488}
1489
1490static void x509_hash( unsigned char *in, int len, int alg,
1491 unsigned char *out )
1492{
1493 switch( alg )
1494 {
Paul Bakker40e46942009-01-03 21:51:57 +00001495#if defined(POLARSSL_MD2_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00001496 case SIG_RSA_MD2 : md2( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001497#endif
Paul Bakker40e46942009-01-03 21:51:57 +00001498#if defined(POLARSSL_MD4_C)
Paul Bakker4593aea2009-02-09 22:32:35 +00001499 case SIG_RSA_MD4 : md4( in, len, out ); break;
Paul Bakker5121ce52009-01-03 21:22:43 +00001500#endif
Paul Bakker4593aea2009-02-09 22:32:35 +00001501 case SIG_RSA_MD5 : md5( in, len, out ); break;
1502 case SIG_RSA_SHA1 : sha1( in, len, out ); break;
1503#if defined(POLARSSL_SHA2_C)
1504 case SIG_RSA_SHA224 : sha2( in, len, out, 1 ); break;
1505 case SIG_RSA_SHA256 : sha2( in, len, out, 0 ); break;
1506#endif
1507#if defined(POLARSSL_SHA2_C)
1508 case SIG_RSA_SHA384 : sha4( in, len, out, 1 ); break;
1509 case SIG_RSA_SHA512 : sha4( in, len, out, 0 ); break;
1510#endif
Paul Bakker5121ce52009-01-03 21:22:43 +00001511 default:
1512 memset( out, '\xFF', len );
1513 break;
1514 }
1515}
1516
1517/*
1518 * Verify the certificate validity
1519 */
1520int x509parse_verify( x509_cert *crt,
1521 x509_cert *trust_ca,
1522 char *cn, int *flags )
1523{
1524 int cn_len;
1525 int hash_id;
1526 int pathlen;
1527 x509_cert *cur;
1528 x509_name *name;
Paul Bakker4593aea2009-02-09 22:32:35 +00001529 unsigned char hash[64];
Paul Bakker5121ce52009-01-03 21:22:43 +00001530
1531 *flags = x509parse_expired( crt );
1532
1533 if( cn != NULL )
1534 {
1535 name = &crt->subject;
1536 cn_len = strlen( cn );
1537
1538 while( name != NULL )
1539 {
1540 if( memcmp( name->oid.p, OID_CN, 3 ) == 0 &&
1541 memcmp( name->val.p, cn, cn_len ) == 0 &&
1542 name->val.len == cn_len )
1543 break;
1544
1545 name = name->next;
1546 }
1547
1548 if( name == NULL )
1549 *flags |= BADCERT_CN_MISMATCH;
1550 }
1551
1552 *flags |= BADCERT_NOT_TRUSTED;
1553
1554 /*
1555 * Iterate upwards in the given cert chain,
1556 * ignoring any upper cert with CA != TRUE.
1557 */
1558 cur = crt->next;
1559
1560 pathlen = 1;
1561
1562 while( cur->version != 0 )
1563 {
1564 if( cur->ca_istrue == 0 ||
1565 crt->issuer_raw.len != cur->subject_raw.len ||
1566 memcmp( crt->issuer_raw.p, cur->subject_raw.p,
1567 crt->issuer_raw.len ) != 0 )
1568 {
1569 cur = cur->next;
1570 continue;
1571 }
1572
1573 hash_id = crt->sig_oid1.p[8];
1574
1575 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
1576
1577 if( rsa_pkcs1_verify( &cur->rsa, RSA_PUBLIC, hash_id,
1578 0, hash, crt->sig.p ) != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001579 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001580
1581 pathlen++;
1582
1583 crt = cur;
1584 cur = crt->next;
1585 }
1586
1587 /*
1588 * Atempt to validate topmost cert with our CA chain.
1589 */
1590 while( trust_ca->version != 0 )
1591 {
1592 if( crt->issuer_raw.len != trust_ca->subject_raw.len ||
1593 memcmp( crt->issuer_raw.p, trust_ca->subject_raw.p,
1594 crt->issuer_raw.len ) != 0 )
1595 {
1596 trust_ca = trust_ca->next;
1597 continue;
1598 }
1599
1600 if( trust_ca->max_pathlen > 0 &&
1601 trust_ca->max_pathlen < pathlen )
1602 break;
1603
1604 hash_id = crt->sig_oid1.p[8];
1605
1606 x509_hash( crt->tbs.p, crt->tbs.len, hash_id, hash );
1607
1608 if( rsa_pkcs1_verify( &trust_ca->rsa, RSA_PUBLIC, hash_id,
1609 0, hash, crt->sig.p ) == 0 )
1610 {
1611 /*
1612 * cert. is signed by a trusted CA
1613 */
1614 *flags &= ~BADCERT_NOT_TRUSTED;
1615 break;
1616 }
1617
1618 trust_ca = trust_ca->next;
1619 }
1620
1621 if( *flags != 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001622 return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED );
Paul Bakker5121ce52009-01-03 21:22:43 +00001623
1624 return( 0 );
1625}
1626
1627/*
1628 * Unallocate all certificate data
1629 */
1630void x509_free( x509_cert *crt )
1631{
1632 x509_cert *cert_cur = crt;
1633 x509_cert *cert_prv;
1634 x509_name *name_cur;
1635 x509_name *name_prv;
1636
1637 if( crt == NULL )
1638 return;
1639
1640 do
1641 {
1642 rsa_free( &cert_cur->rsa );
1643
1644 name_cur = cert_cur->issuer.next;
1645 while( name_cur != NULL )
1646 {
1647 name_prv = name_cur;
1648 name_cur = name_cur->next;
1649 memset( name_prv, 0, sizeof( x509_name ) );
1650 free( name_prv );
1651 }
1652
1653 name_cur = cert_cur->subject.next;
1654 while( name_cur != NULL )
1655 {
1656 name_prv = name_cur;
1657 name_cur = name_cur->next;
1658 memset( name_prv, 0, sizeof( x509_name ) );
1659 free( name_prv );
1660 }
1661
1662 if( cert_cur->raw.p != NULL )
1663 {
1664 memset( cert_cur->raw.p, 0, cert_cur->raw.len );
1665 free( cert_cur->raw.p );
1666 }
1667
1668 cert_cur = cert_cur->next;
1669 }
1670 while( cert_cur != NULL );
1671
1672 cert_cur = crt;
1673 do
1674 {
1675 cert_prv = cert_cur;
1676 cert_cur = cert_cur->next;
1677
1678 memset( cert_prv, 0, sizeof( x509_cert ) );
1679 if( cert_prv != crt )
1680 free( cert_prv );
1681 }
1682 while( cert_cur != NULL );
1683}
1684
Paul Bakker40e46942009-01-03 21:51:57 +00001685#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001686
Paul Bakker40e46942009-01-03 21:51:57 +00001687#include "polarssl/certs.h"
Paul Bakker5121ce52009-01-03 21:22:43 +00001688
1689/*
1690 * Checkup routine
1691 */
1692int x509_self_test( int verbose )
1693{
1694 int ret, i, j;
1695 x509_cert cacert;
1696 x509_cert clicert;
1697 rsa_context rsa;
1698
1699 if( verbose != 0 )
1700 printf( " X.509 certificate load: " );
1701
1702 memset( &clicert, 0, sizeof( x509_cert ) );
1703
1704 ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
1705 strlen( test_cli_crt ) );
1706 if( ret != 0 )
1707 {
1708 if( verbose != 0 )
1709 printf( "failed\n" );
1710
1711 return( ret );
1712 }
1713
1714 memset( &cacert, 0, sizeof( x509_cert ) );
1715
1716 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
1717 strlen( test_ca_crt ) );
1718 if( ret != 0 )
1719 {
1720 if( verbose != 0 )
1721 printf( "failed\n" );
1722
1723 return( ret );
1724 }
1725
1726 if( verbose != 0 )
1727 printf( "passed\n X.509 private key load: " );
1728
1729 i = strlen( test_ca_key );
1730 j = strlen( test_ca_pwd );
1731
1732 if( ( ret = x509parse_key( &rsa,
1733 (unsigned char *) test_ca_key, i,
1734 (unsigned char *) test_ca_pwd, j ) ) != 0 )
1735 {
1736 if( verbose != 0 )
1737 printf( "failed\n" );
1738
1739 return( ret );
1740 }
1741
1742 if( verbose != 0 )
1743 printf( "passed\n X.509 signature verify: ");
1744
1745 ret = x509parse_verify( &clicert, &cacert, "Joe User", &i );
1746 if( ret != 0 )
1747 {
1748 if( verbose != 0 )
1749 printf( "failed\n" );
1750
1751 return( ret );
1752 }
1753
1754 if( verbose != 0 )
1755 printf( "passed\n\n" );
1756
1757 x509_free( &cacert );
1758 x509_free( &clicert );
1759 rsa_free( &rsa );
1760
1761 return( 0 );
1762}
1763
1764#endif
1765
1766#endif