camellia: fix camellia_self_test failure on compilers where char is unsigned by default
[tropicssl.git] / library / x509parse.c
blobf14d6efa5e7d6da96e43aba7d892e9b471bf8687
1 /*
2 * X.509 certificate and private key decoding
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * The ITU-T X.509 standard defines a certificat format for PKI.
38 * http://www.ietf.org/rfc/rfc2459.txt
39 * http://www.ietf.org/rfc/rfc3279.txt
41 * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
43 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
44 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
47 #include "tropicssl/config.h"
49 #if defined(TROPICSSL_X509_PARSE_C)
51 #include "tropicssl/x509.h"
52 #include "tropicssl/base64.h"
53 #include "tropicssl/des.h"
54 #include "tropicssl/md2.h"
55 #include "tropicssl/md4.h"
56 #include "tropicssl/md5.h"
57 #include "tropicssl/sha1.h"
59 #include <string.h>
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <time.h>
65 * ASN.1 DER decoding routines
67 static int asn1_get_len(unsigned char **p, const unsigned char *end, int *len)
69 if ((end - *p) < 1)
70 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA);
72 if ((**p & 0x80) == 0)
73 *len = *(*p)++;
74 else {
75 switch (**p & 0x7F) {
76 case 1:
77 if ((end - *p) < 2)
78 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA);
80 *len = (*p)[1];
81 (*p) += 2;
82 break;
84 case 2:
85 if ((end - *p) < 3)
86 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA);
88 *len = ((*p)[1] << 8) | (*p)[2];
89 (*p) += 3;
90 break;
92 default:
93 return (TROPICSSL_ERR_ASN1_INVALID_LENGTH);
94 break;
98 if (*len > (int)(end - *p))
99 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA);
101 return (0);
104 static int asn1_get_tag(unsigned char **p,
105 const unsigned char *end, int *len, int tag)
107 if ((end - *p) < 1)
108 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA);
110 if (**p != tag)
111 return (TROPICSSL_ERR_ASN1_UNEXPECTED_TAG);
113 (*p)++;
115 return (asn1_get_len(p, end, len));
118 static int asn1_get_bool(unsigned char **p, const unsigned char *end, int *val)
120 int ret, len;
122 if ((ret = asn1_get_tag(p, end, &len, ASN1_BOOLEAN)) != 0)
123 return (ret);
125 if (len != 1)
126 return (TROPICSSL_ERR_ASN1_INVALID_LENGTH);
128 *val = (**p != 0) ? 1 : 0;
129 (*p)++;
131 return (0);
134 static int asn1_get_int(unsigned char **p, const unsigned char *end, int *val)
136 int ret, len;
138 if ((ret = asn1_get_tag(p, end, &len, ASN1_INTEGER)) != 0)
139 return (ret);
141 if (len > (int)sizeof(int) || (**p & 0x80) != 0)
142 return (TROPICSSL_ERR_ASN1_INVALID_LENGTH);
144 *val = 0;
146 while (len-- > 0) {
147 *val = (*val << 8) | **p;
148 (*p)++;
151 return (0);
154 static int asn1_get_mpi(unsigned char **p, const unsigned char *end, mpi * X)
156 int ret, len;
158 if ((ret = asn1_get_tag(p, end, &len, ASN1_INTEGER)) != 0)
159 return (ret);
161 ret = mpi_read_binary(X, *p, len);
163 *p += len;
165 return (ret);
169 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
171 static int x509_get_version(unsigned char **p, const unsigned char *end, int *ver)
173 int ret, len;
175 if ((ret = asn1_get_tag(p, end, &len,
176 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0))
177 != 0) {
178 if (ret == TROPICSSL_ERR_ASN1_UNEXPECTED_TAG)
179 return (*ver = 0);
181 return (ret);
184 end = *p + len;
186 if ((ret = asn1_get_int(p, end, ver)) != 0)
187 return (TROPICSSL_ERR_X509_CERT_INVALID_VERSION | ret);
189 if (*p != end)
190 return (TROPICSSL_ERR_X509_CERT_INVALID_VERSION |
191 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
193 return (0);
197 * CertificateSerialNumber ::= INTEGER
199 static int x509_get_serial(unsigned char **p,
200 const unsigned char *end, x509_buf * serial)
202 int ret;
204 if ((end - *p) < 1)
205 return (TROPICSSL_ERR_X509_CERT_INVALID_SERIAL |
206 TROPICSSL_ERR_ASN1_OUT_OF_DATA);
208 if (**p != (ASN1_CONTEXT_SPECIFIC | ASN1_PRIMITIVE | 2) &&
209 **p != ASN1_INTEGER)
210 return (TROPICSSL_ERR_X509_CERT_INVALID_SERIAL |
211 TROPICSSL_ERR_ASN1_UNEXPECTED_TAG);
213 serial->tag = *(*p)++;
215 if ((ret = asn1_get_len(p, end, &serial->len)) != 0)
216 return (TROPICSSL_ERR_X509_CERT_INVALID_SERIAL | ret);
218 serial->p = *p;
219 *p += serial->len;
221 return (0);
225 * AlgorithmIdentifier ::= SEQUENCE {
226 * algorithm OBJECT IDENTIFIER,
227 * parameters ANY DEFINED BY algorithm OPTIONAL }
229 static int x509_get_alg(unsigned char **p, const unsigned char *end, x509_buf * alg)
231 int ret, len;
233 if ((ret = asn1_get_tag(p, end, &len,
234 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
235 return (TROPICSSL_ERR_X509_CERT_INVALID_ALG | ret);
237 end = *p + len;
238 alg->tag = **p;
240 if ((ret = asn1_get_tag(p, end, &alg->len, ASN1_OID)) != 0)
241 return (TROPICSSL_ERR_X509_CERT_INVALID_ALG | ret);
243 alg->p = *p;
244 *p += alg->len;
246 if (*p == end)
247 return (0);
250 * assume the algorithm parameters must be NULL
252 if ((ret = asn1_get_tag(p, end, &len, ASN1_NULL)) != 0)
253 return (TROPICSSL_ERR_X509_CERT_INVALID_ALG | ret);
255 if (*p != end)
256 return (TROPICSSL_ERR_X509_CERT_INVALID_ALG |
257 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
259 return (0);
263 * RelativeDistinguishedName ::=
264 * SET OF AttributeTypeAndValue
266 * AttributeTypeAndValue ::= SEQUENCE {
267 * type AttributeType,
268 * value AttributeValue }
270 * AttributeType ::= OBJECT IDENTIFIER
272 * AttributeValue ::= ANY DEFINED BY AttributeType
274 static int x509_get_name(unsigned char **p, const unsigned char *end, x509_name * cur)
276 int ret, len;
277 const unsigned char *end2;
278 x509_buf *oid;
279 x509_buf *val;
281 if ((ret = asn1_get_tag(p, end, &len,
282 ASN1_CONSTRUCTED | ASN1_SET)) != 0)
283 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME | ret);
285 end2 = end;
286 end = *p + len;
288 if ((ret = asn1_get_tag(p, end, &len,
289 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
290 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME | ret);
292 if (*p + len != end)
293 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME |
294 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
296 oid = &cur->oid;
297 oid->tag = **p;
299 if ((ret = asn1_get_tag(p, end, &oid->len, ASN1_OID)) != 0)
300 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME | ret);
302 oid->p = *p;
303 *p += oid->len;
305 if ((end - *p) < 1)
306 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME |
307 TROPICSSL_ERR_ASN1_OUT_OF_DATA);
309 if (**p != ASN1_BMP_STRING && **p != ASN1_UTF8_STRING &&
310 **p != ASN1_T61_STRING && **p != ASN1_PRINTABLE_STRING &&
311 **p != ASN1_IA5_STRING && **p != ASN1_UNIVERSAL_STRING)
312 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME |
313 TROPICSSL_ERR_ASN1_UNEXPECTED_TAG);
315 val = &cur->val;
316 val->tag = *(*p)++;
318 if ((ret = asn1_get_len(p, end, &val->len)) != 0)
319 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME | ret);
321 val->p = *p;
322 *p += val->len;
324 cur->next = NULL;
326 if (*p != end)
327 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME |
328 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
331 * recurse until end of SEQUENCE is reached
333 if (*p == end2)
334 return (0);
336 cur->next = (x509_name *) malloc(sizeof(x509_name));
338 if (cur->next == NULL)
339 return (1);
341 return (x509_get_name(p, end2, cur->next));
345 * Validity ::= SEQUENCE {
346 * notBefore Time,
347 * notAfter Time }
349 * Time ::= CHOICE {
350 * utcTime UTCTime,
351 * generalTime GeneralizedTime }
353 static int x509_get_dates(unsigned char **p,
354 const unsigned char *end, x509_time * from, x509_time * to)
356 int ret, len;
357 char date[64];
359 if ((ret = asn1_get_tag(p, end, &len,
360 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
361 return (TROPICSSL_ERR_X509_CERT_INVALID_DATE | ret);
363 end = *p + len;
366 * TODO: also handle GeneralizedTime
368 if ((ret = asn1_get_tag(p, end, &len, ASN1_UTC_TIME)) != 0)
369 return (TROPICSSL_ERR_X509_CERT_INVALID_DATE | ret);
371 memset(date, 0, sizeof(date));
372 memcpy(date, *p, (len < (int)sizeof(date) - 1) ?
373 len : (int)sizeof(date) - 1);
375 if (sscanf(date, "%2d%2d%2d%2d%2d%2d",
376 &from->year, &from->mon, &from->day,
377 &from->hour, &from->min, &from->sec) < 5)
378 return (TROPICSSL_ERR_X509_CERT_INVALID_DATE);
380 from->year += 100 * (from->year < 90);
381 from->year += 1900;
383 *p += len;
385 if ((ret = asn1_get_tag(p, end, &len, ASN1_UTC_TIME)) != 0)
386 return (TROPICSSL_ERR_X509_CERT_INVALID_DATE | ret);
388 memset(date, 0, sizeof(date));
389 memcpy(date, *p, (len < (int)sizeof(date) - 1) ?
390 len : (int)sizeof(date) - 1);
392 if (sscanf(date, "%2d%2d%2d%2d%2d%2d",
393 &to->year, &to->mon, &to->day,
394 &to->hour, &to->min, &to->sec) < 5)
395 return (TROPICSSL_ERR_X509_CERT_INVALID_DATE);
397 to->year += 100 * (to->year < 90);
398 to->year += 1900;
400 *p += len;
402 if (*p != end)
403 return (TROPICSSL_ERR_X509_CERT_INVALID_DATE |
404 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
406 return (0);
410 * SubjectPublicKeyInfo ::= SEQUENCE {
411 * algorithm AlgorithmIdentifier,
412 * subjectPublicKey BIT STRING }
414 static int x509_get_pubkey(unsigned char **p,
415 const unsigned char *end,
416 x509_buf * pk_alg_oid, mpi * N, mpi * E)
418 int ret, len;
419 const unsigned char *end2;
421 if ((ret = x509_get_alg(p, end, pk_alg_oid)) != 0)
422 return (ret);
425 * only RSA public keys handled at this time
427 if (pk_alg_oid->len != 9 ||
428 memcmp(pk_alg_oid->p, OID_PKCS1_RSA, 9) != 0)
429 return (TROPICSSL_ERR_X509_CERT_UNKNOWN_PK_ALG);
431 if ((ret = asn1_get_tag(p, end, &len, ASN1_BIT_STRING)) != 0)
432 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY | ret);
434 if ((end - *p) < 1)
435 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY |
436 TROPICSSL_ERR_ASN1_OUT_OF_DATA);
438 end2 = *p + len;
440 if (*(*p)++ != 0)
441 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY);
444 * RSAPublicKey ::= SEQUENCE {
445 * modulus INTEGER, -- n
446 * publicExponent INTEGER -- e
449 if ((ret = asn1_get_tag(p, end2, &len,
450 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
451 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY | ret);
453 if (*p + len != end2)
454 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY |
455 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
457 if ((ret = asn1_get_mpi(p, end2, N)) != 0 ||
458 (ret = asn1_get_mpi(p, end2, E)) != 0)
459 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY | ret);
461 if (*p != end)
462 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY |
463 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
465 return (0);
468 static int x509_get_sig(unsigned char **p, const unsigned char *end, x509_buf * sig)
470 int ret, len;
472 sig->tag = **p;
474 if ((ret = asn1_get_tag(p, end, &len, ASN1_BIT_STRING)) != 0)
475 return (TROPICSSL_ERR_X509_CERT_INVALID_SIGNATURE | ret);
477 if (--len < 1 || *(*p)++ != 0)
478 return (TROPICSSL_ERR_X509_CERT_INVALID_SIGNATURE);
480 sig->len = len;
481 sig->p = *p;
483 *p += len;
485 return (0);
489 * X.509 v2/v3 unique identifier (not parsed)
491 static int x509_get_uid(unsigned char **p,
492 const unsigned char *end, x509_buf * uid, int n)
494 int ret;
496 if (*p == end)
497 return (0);
499 uid->tag = **p;
501 if ((ret = asn1_get_tag(p, end, &uid->len,
502 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | n))
503 != 0) {
504 if (ret == TROPICSSL_ERR_ASN1_UNEXPECTED_TAG)
505 return (0);
507 return (ret);
510 uid->p = *p;
511 *p += uid->len;
513 return (0);
517 * X.509 v3 extensions (only BasicConstraints are parsed)
519 static int x509_get_ext(unsigned char **p,
520 const unsigned char *end,
521 x509_buf * ext, int *ca_istrue, int *max_pathlen)
523 int ret, len;
524 int is_critical = 1;
525 int is_cacert = 0;
526 unsigned char *end2;
528 if (*p == end)
529 return (0);
531 ext->tag = **p;
533 if ((ret = asn1_get_tag(p, end, &ext->len,
534 ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3))
535 != 0) {
536 if (ret == TROPICSSL_ERR_ASN1_UNEXPECTED_TAG)
537 return (0);
539 return (ret);
542 ext->p = *p;
543 end = *p + ext->len;
546 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
548 * Extension ::= SEQUENCE {
549 * extnID OBJECT IDENTIFIER,
550 * critical BOOLEAN DEFAULT FALSE,
551 * extnValue OCTET STRING }
553 if ((ret = asn1_get_tag(p, end, &len,
554 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
555 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS | ret);
557 if (end != *p + len)
558 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
559 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
561 while (*p < end) {
562 if ((ret = asn1_get_tag(p, end, &len,
563 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
564 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
565 ret);
567 if (memcmp(*p, "\x06\x03\x55\x1D\x13", 5) != 0) {
568 *p += len;
569 continue;
572 *p += 5;
574 if ((ret = asn1_get_bool(p, end, &is_critical)) != 0 &&
575 (ret != TROPICSSL_ERR_ASN1_UNEXPECTED_TAG))
576 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
577 ret);
579 if ((ret = asn1_get_tag(p, end, &len, ASN1_OCTET_STRING)) != 0)
580 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
581 ret);
584 * BasicConstraints ::= SEQUENCE {
585 * cA BOOLEAN DEFAULT FALSE,
586 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
588 end2 = *p + len;
590 if ((ret = asn1_get_tag(p, end2, &len,
591 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
592 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
593 ret);
595 if (*p == end2)
596 continue;
598 if ((ret = asn1_get_bool(p, end2, &is_cacert)) != 0) {
599 if (ret == TROPICSSL_ERR_ASN1_UNEXPECTED_TAG)
600 ret = asn1_get_int(p, end2, &is_cacert);
602 if (ret != 0)
603 return
604 (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
605 | ret);
607 if (is_cacert != 0)
608 is_cacert = 1;
611 if (*p == end2)
612 continue;
614 if ((ret = asn1_get_int(p, end2, max_pathlen)) != 0)
615 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
616 ret);
618 if (*p != end2)
619 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
620 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
622 max_pathlen++;
625 if (*p != end)
626 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS |
627 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
629 *ca_istrue = is_critical & is_cacert;
631 return (0);
635 * Parse one or more certificates and add them to the chained list
637 static int _x509parse_crt_1(x509_cert * chain, unsigned char *buf, int buflen)
639 int ret, len;
640 unsigned char *s1, *s2;
641 unsigned char *p;
642 const unsigned char *end;
643 x509_cert *crt;
645 crt = chain;
647 while (crt->version != 0)
648 crt = crt->next;
651 * check if the certificate is encoded in base64
653 s1 = (unsigned char *)strstr((char *)buf,
654 "-----BEGIN CERTIFICATE-----");
656 if (s1 != NULL) {
657 s2 = (unsigned char *)strstr((char *)buf,
658 "-----END CERTIFICATE-----");
660 if (s2 == NULL || s2 <= s1)
661 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM);
663 s1 += 27;
664 if (*s1 == '\r')
665 s1++;
666 if (*s1 == '\n')
667 s1++;
668 else
669 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM);
672 * get the DER data length and decode the buffer
674 len = 0;
675 ret = base64_decode(NULL, &len, s1, s2 - s1);
677 if (ret == TROPICSSL_ERR_BASE64_INVALID_CHARACTER)
678 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM | ret);
680 if ((p = (unsigned char *)malloc(len)) == NULL)
681 return (1);
683 if ((ret = base64_decode(p, &len, s1, s2 - s1)) != 0) {
684 free(p);
685 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM | ret);
689 * update the buffer size and offset
691 s2 += 25;
692 if (*s2 == '\r')
693 s2++;
694 if (*s2 == '\n')
695 s2++;
696 else {
697 free(p);
698 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM);
701 buflen -= s2 - buf;
702 buf = s2;
703 } else {
705 * nope, copy the raw DER data
707 p = (unsigned char *)malloc(len = buflen);
709 if (p == NULL)
710 return (1);
712 memcpy(p, buf, buflen);
714 buflen = 0;
717 crt->raw.p = p;
718 crt->raw.len = len;
719 end = p + len;
722 * Certificate ::= SEQUENCE {
723 * tbsCertificate TBSCertificate,
724 * signatureAlgorithm AlgorithmIdentifier,
725 * signatureValue BIT STRING }
727 if ((ret = asn1_get_tag(&p, end, &len,
728 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) {
729 x509_free(crt);
730 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT);
733 if (len != (int)(end - p)) {
734 x509_free(crt);
735 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT |
736 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
740 * TBSCertificate ::= SEQUENCE {
742 crt->tbs.p = p;
744 if ((ret = asn1_get_tag(&p, end, &len,
745 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) {
746 x509_free(crt);
747 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT | ret);
750 end = p + len;
751 crt->tbs.len = end - crt->tbs.p;
754 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
756 * CertificateSerialNumber ::= INTEGER
758 * signature AlgorithmIdentifier
760 if ((ret = x509_get_version(&p, end, &crt->version)) != 0 ||
761 (ret = x509_get_serial(&p, end, &crt->serial)) != 0 ||
762 (ret = x509_get_alg(&p, end, &crt->sig_oid1)) != 0) {
763 x509_free(crt);
764 return (ret);
767 crt->version++;
769 if (crt->version > 3) {
770 x509_free(crt);
771 return (TROPICSSL_ERR_X509_CERT_UNKNOWN_VERSION);
774 if (crt->sig_oid1.len != 9 ||
775 memcmp(crt->sig_oid1.p, OID_PKCS1, 8) != 0) {
776 x509_free(crt);
777 return (TROPICSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG);
780 if (crt->sig_oid1.p[8] < 2 || crt->sig_oid1.p[8] > 5) {
781 x509_free(crt);
782 return (TROPICSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG);
786 * issuer Name
788 crt->issuer_raw.p = p;
790 if ((ret = asn1_get_tag(&p, end, &len,
791 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) {
792 x509_free(crt);
793 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT | ret);
796 if ((ret = x509_get_name(&p, p + len, &crt->issuer)) != 0) {
797 x509_free(crt);
798 return (ret);
801 crt->issuer_raw.len = p - crt->issuer_raw.p;
804 * Validity ::= SEQUENCE {
805 * notBefore Time,
806 * notAfter Time }
809 if ((ret = x509_get_dates(&p, end, &crt->valid_from,
810 &crt->valid_to)) != 0) {
811 x509_free(crt);
812 return (ret);
816 * subject Name
818 crt->subject_raw.p = p;
820 if ((ret = asn1_get_tag(&p, end, &len,
821 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) {
822 x509_free(crt);
823 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT | ret);
826 if ((ret = x509_get_name(&p, p + len, &crt->subject)) != 0) {
827 x509_free(crt);
828 return (ret);
831 crt->subject_raw.len = p - crt->subject_raw.p;
834 * SubjectPublicKeyInfo ::= SEQUENCE
835 * algorithm AlgorithmIdentifier,
836 * subjectPublicKey BIT STRING }
838 if ((ret = asn1_get_tag(&p, end, &len,
839 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) {
840 x509_free(crt);
841 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT | ret);
844 if ((ret = x509_get_pubkey(&p, p + len, &crt->pk_oid,
845 &crt->rsa.N, &crt->rsa.E)) != 0) {
846 x509_free(crt);
847 return (ret);
850 if ((ret = rsa_check_pubkey(&crt->rsa)) != 0) {
851 x509_free(crt);
852 return (ret);
855 crt->rsa.len = mpi_size(&crt->rsa.N);
858 * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
859 * -- If present, version shall be v2 or v3
860 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
861 * -- If present, version shall be v2 or v3
862 * extensions [3] EXPLICIT Extensions OPTIONAL
863 * -- If present, version shall be v3
865 if (crt->version == 2 || crt->version == 3) {
866 ret = x509_get_uid(&p, end, &crt->issuer_id, 1);
867 if (ret != 0) {
868 x509_free(crt);
869 return (ret);
873 if (crt->version == 2 || crt->version == 3) {
874 ret = x509_get_uid(&p, end, &crt->subject_id, 2);
875 if (ret != 0) {
876 x509_free(crt);
877 return (ret);
881 if (crt->version == 3) {
882 ret = x509_get_ext(&p, end, &crt->v3_ext,
883 &crt->ca_istrue, &crt->max_pathlen);
884 if (ret != 0) {
885 x509_free(crt);
886 return (ret);
890 if (p != end) {
891 x509_free(crt);
892 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT |
893 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
896 end = crt->raw.p + crt->raw.len;
899 * signatureAlgorithm AlgorithmIdentifier,
900 * signatureValue BIT STRING
902 if ((ret = x509_get_alg(&p, end, &crt->sig_oid2)) != 0) {
903 x509_free(crt);
904 return (ret);
907 if (memcmp(crt->sig_oid1.p, crt->sig_oid2.p, 9) != 0) {
908 x509_free(crt);
909 return (TROPICSSL_ERR_X509_CERT_SIG_MISMATCH);
912 if ((ret = x509_get_sig(&p, end, &crt->sig)) != 0) {
913 x509_free(crt);
914 return (ret);
917 if (p != end) {
918 x509_free(crt);
919 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT |
920 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
923 crt->next = (x509_cert *) malloc(sizeof(x509_cert));
925 if (crt->next == NULL) {
926 x509_free(crt);
927 return (1);
930 crt = crt->next;
931 memset(crt, 0, sizeof(x509_cert));
933 if (buflen > 0)
934 return (x509parse_crt(crt, buf, buflen));
936 return (0);
940 * Parse one or more certificates and add them to the chained list
942 int x509parse_crt(x509_cert * chain, const unsigned char *buf, int buflen)
944 int ret;
945 unsigned char *buf1 = malloc(buflen);
946 if (buf1 == NULL) {
947 return (1);
949 memcpy(buf1, buf, buflen);
950 ret = _x509parse_crt_1(chain, buf1, buflen);
951 free(buf1);
952 return ret;
955 * Load one or more certificates and add them to the chained list
957 int x509parse_crtfile(x509_cert * chain, const char *path)
959 int ret;
960 FILE *f;
961 size_t n;
962 unsigned char *buf;
964 if ((f = fopen(path, "rb")) == NULL)
965 return (1);
967 fseek(f, 0, SEEK_END);
968 n = (size_t) ftell(f);
969 fseek(f, 0, SEEK_SET);
971 if ((buf = (unsigned char *)malloc(n + 1)) == NULL)
972 return (1);
974 if (fread(buf, 1, n, f) != n) {
975 fclose(f);
976 free(buf);
977 return (1);
980 buf[n] = '\0';
982 ret = x509parse_crt(chain, buf, (int)n);
984 memset(buf, 0, n + 1);
985 free(buf);
986 fclose(f);
988 return (ret);
991 #if defined(TROPICSSL_DES_C)
993 * Read a 16-byte hex string and convert it to binary
995 static int x509_get_iv(const unsigned char *s, unsigned char iv[8])
997 int i, j, k;
999 memset(iv, 0, 8);
1001 for (i = 0; i < 16; i++, s++) {
1002 if (*s >= '0' && *s <= '9')
1003 j = *s - '0';
1004 else if (*s >= 'A' && *s <= 'F')
1005 j = *s - '7';
1006 else if (*s >= 'a' && *s <= 'f')
1007 j = *s - 'W';
1008 else
1009 return (TROPICSSL_ERR_X509_KEY_INVALID_ENC_IV);
1011 k = ((i & 1) != 0) ? j : j << 4;
1013 iv[i >> 1] = (unsigned char)(iv[i >> 1] | k);
1016 return (0);
1020 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
1022 static void x509_des3_decrypt(unsigned char des3_iv[8],
1023 unsigned char *buf, int buflen,
1024 const unsigned char *pwd, int pwdlen)
1026 md5_context md5_ctx;
1027 des3_context des3_ctx;
1028 unsigned char md5sum[16];
1029 unsigned char des3_key[24];
1032 * 3DES key[ 0..15] = MD5(pwd || IV)
1033 * key[16..23] = MD5(pwd || IV || 3DES key[ 0..15])
1035 md5_starts(&md5_ctx);
1036 md5_update(&md5_ctx, pwd, pwdlen);
1037 md5_update(&md5_ctx, des3_iv, 8);
1038 md5_finish(&md5_ctx, md5sum);
1039 memcpy(des3_key, md5sum, 16);
1041 md5_starts(&md5_ctx);
1042 md5_update(&md5_ctx, md5sum, 16);
1043 md5_update(&md5_ctx, pwd, pwdlen);
1044 md5_update(&md5_ctx, des3_iv, 8);
1045 md5_finish(&md5_ctx, md5sum);
1046 memcpy(des3_key + 16, md5sum, 8);
1048 des3_set3key_dec(&des3_ctx, des3_key);
1049 des3_crypt_cbc(&des3_ctx, DES_DECRYPT, buflen, des3_iv, buf, buf);
1051 memset(&md5_ctx, 0, sizeof(md5_ctx));
1052 memset(&des3_ctx, 0, sizeof(des3_ctx));
1053 memset(md5sum, 0, 16);
1054 memset(des3_key, 0, 24);
1056 #endif
1059 * Parse a private RSA key
1061 static int _x509parse_key_1(rsa_context * rsa, unsigned char *buf, int buflen,
1062 const unsigned char *pwd, int pwdlen)
1064 int ret, len, enc;
1065 unsigned char *s1, *s2;
1066 unsigned char *p, *end;
1067 unsigned char des3_iv[8];
1069 s1 = (unsigned char *)strstr((char *)buf,
1070 "-----BEGIN RSA PRIVATE KEY-----");
1072 if (s1 != NULL) {
1073 s2 = (unsigned char *)strstr((char *)buf,
1074 "-----END RSA PRIVATE KEY-----");
1076 if (s2 == NULL || s2 <= s1)
1077 return (TROPICSSL_ERR_X509_KEY_INVALID_PEM);
1079 s1 += 31;
1080 if (*s1 == '\r')
1081 s1++;
1082 if (*s1 == '\n')
1083 s1++;
1084 else
1085 return (TROPICSSL_ERR_X509_KEY_INVALID_PEM);
1087 enc = 0;
1089 if (memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) {
1090 #if defined(TROPICSSL_DES_C)
1091 enc++;
1093 s1 += 22;
1094 if (*s1 == '\r')
1095 s1++;
1096 if (*s1 == '\n')
1097 s1++;
1098 else
1099 return (TROPICSSL_ERR_X509_KEY_INVALID_PEM);
1101 if (memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) != 0)
1102 return (TROPICSSL_ERR_X509_KEY_UNKNOWN_ENC_ALG);
1104 s1 += 23;
1105 if (x509_get_iv(s1, des3_iv) != 0)
1106 return (TROPICSSL_ERR_X509_KEY_INVALID_ENC_IV);
1108 s1 += 16;
1109 if (*s1 == '\r')
1110 s1++;
1111 if (*s1 == '\n')
1112 s1++;
1113 else
1114 return (TROPICSSL_ERR_X509_KEY_INVALID_PEM);
1115 #else
1116 return (TROPICSSL_ERR_X509_FEATURE_UNAVAILABLE);
1117 #endif
1120 len = 0;
1121 ret = base64_decode(NULL, &len, s1, s2 - s1);
1123 if (ret == TROPICSSL_ERR_BASE64_INVALID_CHARACTER)
1124 return (ret | TROPICSSL_ERR_X509_KEY_INVALID_PEM);
1126 if ((buf = (unsigned char *)malloc(len)) == NULL)
1127 return (1);
1129 if ((ret = base64_decode(buf, &len, s1, s2 - s1)) != 0) {
1130 free(buf);
1131 return (ret | TROPICSSL_ERR_X509_KEY_INVALID_PEM);
1134 buflen = len;
1136 if (enc != 0) {
1137 #if defined(TROPICSSL_DES_C)
1138 if (pwd == NULL) {
1139 free(buf);
1140 return
1141 (TROPICSSL_ERR_X509_KEY_PASSWORD_REQUIRED);
1144 x509_des3_decrypt(des3_iv, buf, buflen, pwd, pwdlen);
1146 if (buf[0] != 0x30 || buf[1] != 0x82 ||
1147 buf[4] != 0x02 || buf[5] != 0x01) {
1148 free(buf);
1149 return
1150 (TROPICSSL_ERR_X509_KEY_PASSWORD_MISMATCH);
1152 #else
1153 return (TROPICSSL_ERR_X509_FEATURE_UNAVAILABLE);
1154 #endif
1158 memset(rsa, 0, sizeof(rsa_context));
1160 p = buf;
1161 end = buf + buflen;
1164 * RSAPrivateKey ::= SEQUENCE {
1165 * version Version,
1166 * modulus INTEGER, -- n
1167 * publicExponent INTEGER, -- e
1168 * privateExponent INTEGER, -- d
1169 * prime1 INTEGER, -- p
1170 * prime2 INTEGER, -- q
1171 * exponent1 INTEGER, -- d mod (p-1)
1172 * exponent2 INTEGER, -- d mod (q-1)
1173 * coefficient INTEGER, -- (inverse of q) mod p
1174 * otherPrimeInfos OtherPrimeInfos OPTIONAL
1177 if ((ret = asn1_get_tag(&p, end, &len,
1178 ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0) {
1179 if (s1 != NULL)
1180 free(buf);
1182 rsa_free(rsa);
1183 return (TROPICSSL_ERR_X509_KEY_INVALID_FORMAT | ret);
1186 end = p + len;
1188 if ((ret = asn1_get_int(&p, end, &rsa->ver)) != 0) {
1189 if (s1 != NULL)
1190 free(buf);
1192 rsa_free(rsa);
1193 return (TROPICSSL_ERR_X509_KEY_INVALID_FORMAT | ret);
1196 if (rsa->ver != 0) {
1197 if (s1 != NULL)
1198 free(buf);
1200 rsa_free(rsa);
1201 return (ret | TROPICSSL_ERR_X509_KEY_INVALID_VERSION);
1204 if ((ret = asn1_get_mpi(&p, end, &rsa->N)) != 0 ||
1205 (ret = asn1_get_mpi(&p, end, &rsa->E)) != 0 ||
1206 (ret = asn1_get_mpi(&p, end, &rsa->D)) != 0 ||
1207 (ret = asn1_get_mpi(&p, end, &rsa->P)) != 0 ||
1208 (ret = asn1_get_mpi(&p, end, &rsa->Q)) != 0 ||
1209 (ret = asn1_get_mpi(&p, end, &rsa->DP)) != 0 ||
1210 (ret = asn1_get_mpi(&p, end, &rsa->DQ)) != 0 ||
1211 (ret = asn1_get_mpi(&p, end, &rsa->QP)) != 0) {
1212 if (s1 != NULL)
1213 free(buf);
1215 rsa_free(rsa);
1216 return (ret | TROPICSSL_ERR_X509_KEY_INVALID_FORMAT);
1219 rsa->len = mpi_size(&rsa->N);
1221 if (p != end) {
1222 if (s1 != NULL)
1223 free(buf);
1225 rsa_free(rsa);
1226 return (TROPICSSL_ERR_X509_KEY_INVALID_FORMAT |
1227 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH);
1230 if ((ret = rsa_check_privkey(rsa)) != 0) {
1231 if (s1 != NULL)
1232 free(buf);
1234 rsa_free(rsa);
1235 return (ret);
1238 if (s1 != NULL)
1239 free(buf);
1241 return (0);
1245 * Parse a private RSA key
1247 int x509parse_key(rsa_context * rsa,
1248 const unsigned char *key, int keylen,
1249 const unsigned char *pwd, int pwdlen)
1251 int ret;
1252 unsigned char *buf1;
1253 buf1 = malloc(keylen);
1254 if (buf1 == NULL) {
1255 return (1);
1257 memcpy(buf1, key, keylen);
1258 ret = _x509parse_key_1(rsa, buf1, keylen, pwd, pwdlen);
1259 free(buf1);
1260 return ret;
1264 * Load and parse a private RSA key
1266 int x509parse_keyfile(rsa_context * rsa, const char *path, const char *pwd)
1268 int ret;
1269 FILE *f;
1270 size_t n;
1271 unsigned char *buf;
1273 if ((f = fopen(path, "rb")) == NULL)
1274 return (1);
1276 fseek(f, 0, SEEK_END);
1277 n = (size_t) ftell(f);
1278 fseek(f, 0, SEEK_SET);
1280 if ((buf = (unsigned char *)malloc(n + 1)) == NULL)
1281 return (1);
1283 if (fread(buf, 1, n, f) != n) {
1284 fclose(f);
1285 free(buf);
1286 return (1);
1289 buf[n] = '\0';
1291 if (pwd == NULL)
1292 ret = x509parse_key(rsa, buf, (int)n, NULL, 0);
1293 else
1294 ret = x509parse_key(rsa, buf, (int)n,
1295 (const unsigned char *)pwd, strlen(pwd));
1297 memset(buf, 0, n + 1);
1298 free(buf);
1299 fclose(f);
1301 return (ret);
1304 #if defined _MSC_VER && !defined snprintf
1305 #define snprintf _snprintf
1306 #endif
1309 * Store the name in printable form into buf; no more
1310 * than (end - buf) characters will be written
1312 int x509parse_dn_gets(char *buf, const char *end, const x509_name * dn)
1314 int i;
1315 unsigned char c;
1316 const x509_name *name;
1317 char s[128], *p;
1319 memset(s, 0, sizeof(s));
1321 name = dn;
1322 p = buf;
1324 while (name != NULL) {
1325 if (name != dn)
1326 p += snprintf(p, end - p, ", ");
1328 if (memcmp(name->oid.p, OID_X520, 2) == 0) {
1329 switch (name->oid.p[2]) {
1330 case X520_COMMON_NAME:
1331 p += snprintf(p, end - p, "CN=");
1332 break;
1334 case X520_COUNTRY:
1335 p += snprintf(p, end - p, "C=");
1336 break;
1338 case X520_LOCALITY:
1339 p += snprintf(p, end - p, "L=");
1340 break;
1342 case X520_STATE:
1343 p += snprintf(p, end - p, "ST=");
1344 break;
1346 case X520_ORGANIZATION:
1347 p += snprintf(p, end - p, "O=");
1348 break;
1350 case X520_ORG_UNIT:
1351 p += snprintf(p, end - p, "OU=");
1352 break;
1354 default:
1355 p += snprintf(p, end - p, "0x%02X=",
1356 name->oid.p[2]);
1357 break;
1359 } else if (memcmp(name->oid.p, OID_PKCS9, 8) == 0) {
1360 switch (name->oid.p[8]) {
1361 case PKCS9_EMAIL:
1362 p += snprintf(p, end - p, "emailAddress=");
1363 break;
1365 default:
1366 p += snprintf(p, end - p, "0x%02X=",
1367 name->oid.p[8]);
1368 break;
1370 } else
1371 p += snprintf(p, end - p, "\?\?=");
1373 for (i = 0; i < name->val.len; i++) {
1374 if (i >= (int)sizeof(s) - 1)
1375 break;
1377 c = name->val.p[i];
1378 if (c < 32 || c == 127 || (c > 128 && c < 160))
1379 s[i] = '?';
1380 else
1381 s[i] = c;
1383 s[i] = '\0';
1384 p += snprintf(p, end - p, "%s", s);
1385 name = name->next;
1388 return (p - buf);
1392 * Return an informational string about the
1393 * certificate, or NULL if memory allocation failed
1395 char *x509parse_cert_info(char *buf, size_t buf_size,
1396 const char *prefix, const x509_cert * crt)
1398 int i, n;
1399 char *p;
1400 const char *end;
1402 p = buf;
1403 end = buf + buf_size - 1;
1405 p += snprintf(p, end - p, "%scert. version : %d\n",
1406 prefix, crt->version);
1407 p += snprintf(p, end - p, "%sserial number : ", prefix);
1409 n = (crt->serial.len <= 32)
1410 ? crt->serial.len : 32;
1412 for (i = 0; i < n; i++)
1413 p += snprintf(p, end - p, "%02X%s",
1414 crt->serial.p[i], (i < n - 1) ? ":" : "");
1416 p += snprintf(p, end - p, "\n%sissuer name : ", prefix);
1417 p += x509parse_dn_gets(p, end, &crt->issuer);
1419 p += snprintf(p, end - p, "\n%ssubject name : ", prefix);
1420 p += x509parse_dn_gets(p, end, &crt->subject);
1422 p += snprintf(p, end - p, "\n%sissued on : "
1423 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1424 crt->valid_from.year, crt->valid_from.mon,
1425 crt->valid_from.day, crt->valid_from.hour,
1426 crt->valid_from.min, crt->valid_from.sec);
1428 p += snprintf(p, end - p, "\n%sexpires on : "
1429 "%04d-%02d-%02d %02d:%02d:%02d", prefix,
1430 crt->valid_to.year, crt->valid_to.mon,
1431 crt->valid_to.day, crt->valid_to.hour,
1432 crt->valid_to.min, crt->valid_to.sec);
1434 p += snprintf(p, end - p, "\n%ssigned using : RSA+", prefix);
1436 switch (crt->sig_oid1.p[8]) {
1437 case RSA_MD2:
1438 p += snprintf(p, end - p, "MD2");
1439 break;
1440 case RSA_MD4:
1441 p += snprintf(p, end - p, "MD4");
1442 break;
1443 case RSA_MD5:
1444 p += snprintf(p, end - p, "MD5");
1445 break;
1446 case RSA_SHA1:
1447 p += snprintf(p, end - p, "SHA1");
1448 break;
1449 default:
1450 p += snprintf(p, end - p, "???");
1451 break;
1454 p += snprintf(p, end - p, "\n%sRSA key size : %d bits\n", prefix,
1455 crt->rsa.N.n * (int)sizeof(unsigned long) * 8);
1457 return (buf);
1461 * Return 0 if the certificate is still valid, or BADCERT_EXPIRED
1463 int x509parse_expired(const x509_cert * crt)
1465 struct tm *lt;
1466 time_t tt;
1468 tt = time(NULL);
1469 lt = localtime(&tt);
1471 if (lt->tm_year > crt->valid_to.year - 1900)
1472 return (BADCERT_EXPIRED);
1474 if (lt->tm_year == crt->valid_to.year - 1900 &&
1475 lt->tm_mon > crt->valid_to.mon - 1)
1476 return (BADCERT_EXPIRED);
1478 if (lt->tm_year == crt->valid_to.year - 1900 &&
1479 lt->tm_mon == crt->valid_to.mon - 1 &&
1480 lt->tm_mday > crt->valid_to.day)
1481 return (BADCERT_EXPIRED);
1483 return (0);
1486 static void x509_hash(const unsigned char *in, int len, int alg, unsigned char *out)
1488 switch (alg) {
1489 #if defined(TROPICSSL_MD2_C)
1490 case RSA_MD2:
1491 md2(in, len, out);
1492 break;
1493 #endif
1494 #if defined(TROPICSSL_MD4_C)
1495 case RSA_MD4:
1496 md4(in, len, out);
1497 break;
1498 #endif
1499 case RSA_MD5:
1500 md5(in, len, out);
1501 break;
1502 case RSA_SHA1:
1503 sha1(in, len, out);
1504 break;
1505 default:
1506 memset(out, '\xFF', len);
1507 break;
1512 * Verify the certificate validity
1514 int x509parse_verify(x509_cert * crt,
1515 x509_cert * trust_ca, const char *cn, int *flags)
1517 int cn_len;
1518 int hash_id;
1519 int pathlen;
1520 x509_cert *cur;
1521 x509_name *name;
1522 unsigned char hash[20];
1524 *flags = x509parse_expired(crt);
1526 if (cn != NULL) {
1527 name = &crt->subject;
1528 cn_len = strlen(cn);
1530 while (name != NULL) {
1531 if (memcmp(name->oid.p, OID_CN, 3) == 0 &&
1532 memcmp(name->val.p, cn, cn_len) == 0 &&
1533 name->val.len == cn_len)
1534 break;
1536 name = name->next;
1539 if (name == NULL)
1540 *flags |= BADCERT_CN_MISMATCH;
1543 *flags |= BADCERT_NOT_TRUSTED;
1546 * Iterate upwards in the given cert chain,
1547 * ignoring any upper cert with CA != TRUE.
1549 cur = crt->next;
1551 pathlen = 1;
1553 while (cur->version != 0) {
1554 if (cur->ca_istrue == 0 ||
1555 crt->issuer_raw.len != cur->subject_raw.len ||
1556 memcmp(crt->issuer_raw.p, cur->subject_raw.p,
1557 crt->issuer_raw.len) != 0) {
1558 cur = cur->next;
1559 continue;
1562 hash_id = crt->sig_oid1.p[8];
1564 x509_hash(crt->tbs.p, crt->tbs.len, hash_id, hash);
1566 if (rsa_pkcs1_verify(&cur->rsa, RSA_PUBLIC, hash_id,
1567 0, hash, crt->sig.p) != 0)
1568 return (TROPICSSL_ERR_X509_CERT_VERIFY_FAILED);
1570 pathlen++;
1572 crt = cur;
1573 cur = crt->next;
1577 * Atempt to validate topmost cert with our CA chain.
1579 while (trust_ca->version != 0) {
1580 if (crt->issuer_raw.len != trust_ca->subject_raw.len ||
1581 memcmp(crt->issuer_raw.p, trust_ca->subject_raw.p,
1582 crt->issuer_raw.len) != 0) {
1583 trust_ca = trust_ca->next;
1584 continue;
1587 if (trust_ca->max_pathlen > 0 &&
1588 trust_ca->max_pathlen < pathlen)
1589 break;
1591 hash_id = crt->sig_oid1.p[8];
1593 x509_hash(crt->tbs.p, crt->tbs.len, hash_id, hash);
1595 if (rsa_pkcs1_verify(&trust_ca->rsa, RSA_PUBLIC, hash_id,
1596 0, hash, crt->sig.p) == 0) {
1598 * cert. is signed by a trusted CA
1600 *flags &= ~BADCERT_NOT_TRUSTED;
1601 break;
1604 trust_ca = trust_ca->next;
1607 if (*flags != 0)
1608 return (TROPICSSL_ERR_X509_CERT_VERIFY_FAILED);
1610 return (0);
1614 * Unallocate all certificate data
1616 void x509_free(x509_cert * crt)
1618 x509_cert *cert_cur = crt;
1619 x509_cert *cert_prv;
1620 x509_name *name_cur;
1621 x509_name *name_prv;
1623 if (crt == NULL)
1624 return;
1626 do {
1627 rsa_free(&cert_cur->rsa);
1629 name_cur = cert_cur->issuer.next;
1630 while (name_cur != NULL) {
1631 name_prv = name_cur;
1632 name_cur = name_cur->next;
1633 memset(name_prv, 0, sizeof(x509_name));
1634 free(name_prv);
1637 name_cur = cert_cur->subject.next;
1638 while (name_cur != NULL) {
1639 name_prv = name_cur;
1640 name_cur = name_cur->next;
1641 memset(name_prv, 0, sizeof(x509_name));
1642 free(name_prv);
1645 if (cert_cur->raw.p != NULL) {
1646 memset(cert_cur->raw.p, 0, cert_cur->raw.len);
1647 free(cert_cur->raw.p);
1650 cert_cur = cert_cur->next;
1651 } while (cert_cur != NULL);
1653 cert_cur = crt;
1654 do {
1655 cert_prv = cert_cur;
1656 cert_cur = cert_cur->next;
1658 memset(cert_prv, 0, sizeof(x509_cert));
1659 if (cert_prv != crt)
1660 free(cert_prv);
1661 } while (cert_cur != NULL);
1664 #if defined(TROPICSSL_SELF_TEST)
1666 #include "tropicssl/certs.h"
1669 * Checkup routine
1671 int x509_self_test(int verbose)
1673 int ret, i, j;
1674 x509_cert cacert;
1675 x509_cert clicert;
1676 rsa_context rsa;
1678 if (verbose != 0)
1679 printf(" X.509 certificate load: ");
1681 memset(&clicert, 0, sizeof(x509_cert));
1683 ret = x509parse_crt(&clicert, (const unsigned char *)test_cli_crt,
1684 strlen(test_cli_crt));
1685 if (ret != 0) {
1686 if (verbose != 0)
1687 printf("failed\n");
1689 return (ret);
1692 memset(&cacert, 0, sizeof(x509_cert));
1694 ret = x509parse_crt(&cacert, (const unsigned char *)test_ca_crt,
1695 strlen(test_ca_crt));
1696 if (ret != 0) {
1697 if (verbose != 0)
1698 printf("failed\n");
1700 return (ret);
1703 if (verbose != 0)
1704 printf("passed\n X.509 private key load: ");
1706 i = strlen(test_ca_key);
1707 j = strlen(test_ca_pwd);
1709 if ((ret = x509parse_key(&rsa,
1710 (const unsigned char *)test_ca_key, i,
1711 (const unsigned char *)test_ca_pwd, j)) != 0) {
1712 if (verbose != 0)
1713 printf("failed\n");
1715 return (ret);
1718 if (verbose != 0)
1719 printf("passed\n X.509 signature verify: ");
1721 ret = x509parse_verify(&clicert, &cacert, "Joe User", &i);
1722 if (ret != 0) {
1723 if (verbose != 0)
1724 printf("failed\n");
1726 return (ret);
1729 if (verbose != 0)
1730 printf("passed\n\n");
1732 x509_free(&cacert);
1733 x509_free(&clicert);
1734 rsa_free(&rsa);
1736 return (0);
1739 #endif
1741 #endif