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>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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"
65 * ASN.1 DER decoding routines
67 static int asn1_get_len(unsigned char **p
, const unsigned char *end
, int *len
)
70 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA
);
72 if ((**p
& 0x80) == 0)
78 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA
);
86 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA
);
88 *len
= ((*p
)[1] << 8) | (*p
)[2];
93 return (TROPICSSL_ERR_ASN1_INVALID_LENGTH
);
98 if (*len
> (int)(end
- *p
))
99 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA
);
104 static int asn1_get_tag(unsigned char **p
,
105 const unsigned char *end
, int *len
, int tag
)
108 return (TROPICSSL_ERR_ASN1_OUT_OF_DATA
);
111 return (TROPICSSL_ERR_ASN1_UNEXPECTED_TAG
);
115 return (asn1_get_len(p
, end
, len
));
118 static int asn1_get_bool(unsigned char **p
, const unsigned char *end
, int *val
)
122 if ((ret
= asn1_get_tag(p
, end
, &len
, ASN1_BOOLEAN
)) != 0)
126 return (TROPICSSL_ERR_ASN1_INVALID_LENGTH
);
128 *val
= (**p
!= 0) ? 1 : 0;
134 static int asn1_get_int(unsigned char **p
, const unsigned char *end
, int *val
)
138 if ((ret
= asn1_get_tag(p
, end
, &len
, ASN1_INTEGER
)) != 0)
141 if (len
> (int)sizeof(int) || (**p
& 0x80) != 0)
142 return (TROPICSSL_ERR_ASN1_INVALID_LENGTH
);
147 *val
= (*val
<< 8) | **p
;
154 static int asn1_get_mpi(unsigned char **p
, const unsigned char *end
, mpi
* X
)
158 if ((ret
= asn1_get_tag(p
, end
, &len
, ASN1_INTEGER
)) != 0)
161 ret
= mpi_read_binary(X
, *p
, len
);
169 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
171 static int x509_get_version(unsigned char **p
, const unsigned char *end
, int *ver
)
175 if ((ret
= asn1_get_tag(p
, end
, &len
,
176 ASN1_CONTEXT_SPECIFIC
| ASN1_CONSTRUCTED
| 0))
178 if (ret
== TROPICSSL_ERR_ASN1_UNEXPECTED_TAG
)
186 if ((ret
= asn1_get_int(p
, end
, ver
)) != 0)
187 return (TROPICSSL_ERR_X509_CERT_INVALID_VERSION
| ret
);
190 return (TROPICSSL_ERR_X509_CERT_INVALID_VERSION
|
191 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
197 * CertificateSerialNumber ::= INTEGER
199 static int x509_get_serial(unsigned char **p
,
200 const unsigned char *end
, x509_buf
* serial
)
205 return (TROPICSSL_ERR_X509_CERT_INVALID_SERIAL
|
206 TROPICSSL_ERR_ASN1_OUT_OF_DATA
);
208 if (**p
!= (ASN1_CONTEXT_SPECIFIC
| ASN1_PRIMITIVE
| 2) &&
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
);
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
)
233 if ((ret
= asn1_get_tag(p
, end
, &len
,
234 ASN1_CONSTRUCTED
| ASN1_SEQUENCE
)) != 0)
235 return (TROPICSSL_ERR_X509_CERT_INVALID_ALG
| ret
);
240 if ((ret
= asn1_get_tag(p
, end
, &alg
->len
, ASN1_OID
)) != 0)
241 return (TROPICSSL_ERR_X509_CERT_INVALID_ALG
| ret
);
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
);
256 return (TROPICSSL_ERR_X509_CERT_INVALID_ALG
|
257 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
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
)
277 const unsigned char *end2
;
281 if ((ret
= asn1_get_tag(p
, end
, &len
,
282 ASN1_CONSTRUCTED
| ASN1_SET
)) != 0)
283 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME
| ret
);
288 if ((ret
= asn1_get_tag(p
, end
, &len
,
289 ASN1_CONSTRUCTED
| ASN1_SEQUENCE
)) != 0)
290 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME
| ret
);
293 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME
|
294 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
299 if ((ret
= asn1_get_tag(p
, end
, &oid
->len
, ASN1_OID
)) != 0)
300 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME
| ret
);
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
);
318 if ((ret
= asn1_get_len(p
, end
, &val
->len
)) != 0)
319 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME
| ret
);
327 return (TROPICSSL_ERR_X509_CERT_INVALID_NAME
|
328 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
331 * recurse until end of SEQUENCE is reached
336 cur
->next
= (x509_name
*) malloc(sizeof(x509_name
));
338 if (cur
->next
== NULL
)
341 return (x509_get_name(p
, end2
, cur
->next
));
345 * Validity ::= SEQUENCE {
351 * generalTime GeneralizedTime }
353 static int x509_get_dates(unsigned char **p
,
354 const unsigned char *end
, x509_time
* from
, x509_time
* to
)
359 if ((ret
= asn1_get_tag(p
, end
, &len
,
360 ASN1_CONSTRUCTED
| ASN1_SEQUENCE
)) != 0)
361 return (TROPICSSL_ERR_X509_CERT_INVALID_DATE
| ret
);
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);
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);
403 return (TROPICSSL_ERR_X509_CERT_INVALID_DATE
|
404 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
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
)
419 const unsigned char *end2
;
421 if ((ret
= x509_get_alg(p
, end
, pk_alg_oid
)) != 0)
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
);
435 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY
|
436 TROPICSSL_ERR_ASN1_OUT_OF_DATA
);
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
);
462 return (TROPICSSL_ERR_X509_CERT_INVALID_PUBKEY
|
463 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
468 static int x509_get_sig(unsigned char **p
, const unsigned char *end
, x509_buf
* sig
)
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
);
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
)
501 if ((ret
= asn1_get_tag(p
, end
, &uid
->len
,
502 ASN1_CONTEXT_SPECIFIC
| ASN1_CONSTRUCTED
| n
))
504 if (ret
== TROPICSSL_ERR_ASN1_UNEXPECTED_TAG
)
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
)
533 if ((ret
= asn1_get_tag(p
, end
, &ext
->len
,
534 ASN1_CONTEXT_SPECIFIC
| ASN1_CONSTRUCTED
| 3))
536 if (ret
== TROPICSSL_ERR_ASN1_UNEXPECTED_TAG
)
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
);
558 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
|
559 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
562 if ((ret
= asn1_get_tag(p
, end
, &len
,
563 ASN1_CONSTRUCTED
| ASN1_SEQUENCE
)) != 0)
564 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
|
567 if (memcmp(*p
, "\x06\x03\x55\x1D\x13", 5) != 0) {
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
|
579 if ((ret
= asn1_get_tag(p
, end
, &len
, ASN1_OCTET_STRING
)) != 0)
580 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
|
584 * BasicConstraints ::= SEQUENCE {
585 * cA BOOLEAN DEFAULT FALSE,
586 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
590 if ((ret
= asn1_get_tag(p
, end2
, &len
,
591 ASN1_CONSTRUCTED
| ASN1_SEQUENCE
)) != 0)
592 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
|
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
);
604 (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
614 if ((ret
= asn1_get_int(p
, end2
, max_pathlen
)) != 0)
615 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
|
619 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
|
620 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
626 return (TROPICSSL_ERR_X509_CERT_INVALID_EXTENSIONS
|
627 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
629 *ca_istrue
= is_critical
& is_cacert
;
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
)
640 unsigned char *s1
, *s2
;
642 const unsigned char *end
;
647 while (crt
->version
!= 0)
651 * check if the certificate is encoded in base64
653 s1
= (unsigned char *)strstr((char *)buf
,
654 "-----BEGIN CERTIFICATE-----");
657 s2
= (unsigned char *)strstr((char *)buf
,
658 "-----END CERTIFICATE-----");
660 if (s2
== NULL
|| s2
<= s1
)
661 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM
);
669 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM
);
672 * get the DER data length and decode the buffer
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
)
683 if ((ret
= base64_decode(p
, &len
, s1
, s2
- s1
)) != 0) {
685 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM
| ret
);
689 * update the buffer size and offset
698 return (TROPICSSL_ERR_X509_CERT_INVALID_PEM
);
705 * nope, copy the raw DER data
707 p
= (unsigned char *)malloc(len
= buflen
);
712 memcpy(p
, buf
, buflen
);
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) {
730 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT
);
733 if (len
!= (int)(end
- p
)) {
735 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT
|
736 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
740 * TBSCertificate ::= SEQUENCE {
744 if ((ret
= asn1_get_tag(&p
, end
, &len
,
745 ASN1_CONSTRUCTED
| ASN1_SEQUENCE
)) != 0) {
747 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT
| ret
);
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) {
769 if (crt
->version
> 3) {
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) {
777 return (TROPICSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG
);
780 if (crt
->sig_oid1
.p
[8] < 2 || crt
->sig_oid1
.p
[8] > 5) {
782 return (TROPICSSL_ERR_X509_CERT_UNKNOWN_SIG_ALG
);
788 crt
->issuer_raw
.p
= p
;
790 if ((ret
= asn1_get_tag(&p
, end
, &len
,
791 ASN1_CONSTRUCTED
| ASN1_SEQUENCE
)) != 0) {
793 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT
| ret
);
796 if ((ret
= x509_get_name(&p
, p
+ len
, &crt
->issuer
)) != 0) {
801 crt
->issuer_raw
.len
= p
- crt
->issuer_raw
.p
;
804 * Validity ::= SEQUENCE {
809 if ((ret
= x509_get_dates(&p
, end
, &crt
->valid_from
,
810 &crt
->valid_to
)) != 0) {
818 crt
->subject_raw
.p
= p
;
820 if ((ret
= asn1_get_tag(&p
, end
, &len
,
821 ASN1_CONSTRUCTED
| ASN1_SEQUENCE
)) != 0) {
823 return (TROPICSSL_ERR_X509_CERT_INVALID_FORMAT
| ret
);
826 if ((ret
= x509_get_name(&p
, p
+ len
, &crt
->subject
)) != 0) {
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) {
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) {
850 if ((ret
= rsa_check_pubkey(&crt
->rsa
)) != 0) {
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);
873 if (crt
->version
== 2 || crt
->version
== 3) {
874 ret
= x509_get_uid(&p
, end
, &crt
->subject_id
, 2);
881 if (crt
->version
== 3) {
882 ret
= x509_get_ext(&p
, end
, &crt
->v3_ext
,
883 &crt
->ca_istrue
, &crt
->max_pathlen
);
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) {
907 if (memcmp(crt
->sig_oid1
.p
, crt
->sig_oid2
.p
, 9) != 0) {
909 return (TROPICSSL_ERR_X509_CERT_SIG_MISMATCH
);
912 if ((ret
= x509_get_sig(&p
, end
, &crt
->sig
)) != 0) {
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
) {
931 memset(crt
, 0, sizeof(x509_cert
));
934 return (x509parse_crt(crt
, buf
, buflen
));
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
)
945 unsigned char *buf1
= malloc(buflen
);
949 memcpy(buf1
, buf
, buflen
);
950 ret
= _x509parse_crt_1(chain
, buf1
, buflen
);
955 * Load one or more certificates and add them to the chained list
957 int x509parse_crtfile(x509_cert
* chain
, const char *path
)
964 if ((f
= fopen(path
, "rb")) == NULL
)
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
)
974 if (fread(buf
, 1, n
, f
) != n
) {
982 ret
= x509parse_crt(chain
, buf
, (int)n
);
984 memset(buf
, 0, n
+ 1);
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])
1001 for (i
= 0; i
< 16; i
++, s
++) {
1002 if (*s
>= '0' && *s
<= '9')
1004 else if (*s
>= 'A' && *s
<= 'F')
1006 else if (*s
>= 'a' && *s
<= 'f')
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
);
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);
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
)
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-----");
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
);
1085 return (TROPICSSL_ERR_X509_KEY_INVALID_PEM
);
1089 if (memcmp(s1
, "Proc-Type: 4,ENCRYPTED", 22) == 0) {
1090 #if defined(TROPICSSL_DES_C)
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
);
1105 if (x509_get_iv(s1
, des3_iv
) != 0)
1106 return (TROPICSSL_ERR_X509_KEY_INVALID_ENC_IV
);
1114 return (TROPICSSL_ERR_X509_KEY_INVALID_PEM
);
1116 return (TROPICSSL_ERR_X509_FEATURE_UNAVAILABLE
);
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
)
1129 if ((ret
= base64_decode(buf
, &len
, s1
, s2
- s1
)) != 0) {
1131 return (ret
| TROPICSSL_ERR_X509_KEY_INVALID_PEM
);
1137 #if defined(TROPICSSL_DES_C)
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) {
1150 (TROPICSSL_ERR_X509_KEY_PASSWORD_MISMATCH
);
1153 return (TROPICSSL_ERR_X509_FEATURE_UNAVAILABLE
);
1158 memset(rsa
, 0, sizeof(rsa_context
));
1164 * RSAPrivateKey ::= SEQUENCE {
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) {
1183 return (TROPICSSL_ERR_X509_KEY_INVALID_FORMAT
| ret
);
1188 if ((ret
= asn1_get_int(&p
, end
, &rsa
->ver
)) != 0) {
1193 return (TROPICSSL_ERR_X509_KEY_INVALID_FORMAT
| ret
);
1196 if (rsa
->ver
!= 0) {
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) {
1216 return (ret
| TROPICSSL_ERR_X509_KEY_INVALID_FORMAT
);
1219 rsa
->len
= mpi_size(&rsa
->N
);
1226 return (TROPICSSL_ERR_X509_KEY_INVALID_FORMAT
|
1227 TROPICSSL_ERR_ASN1_LENGTH_MISMATCH
);
1230 if ((ret
= rsa_check_privkey(rsa
)) != 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
)
1252 unsigned char *buf1
;
1253 buf1
= malloc(keylen
);
1257 memcpy(buf1
, key
, keylen
);
1258 ret
= _x509parse_key_1(rsa
, buf1
, keylen
, pwd
, pwdlen
);
1264 * Load and parse a private RSA key
1266 int x509parse_keyfile(rsa_context
* rsa
, const char *path
, const char *pwd
)
1273 if ((f
= fopen(path
, "rb")) == NULL
)
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
)
1283 if (fread(buf
, 1, n
, f
) != n
) {
1292 ret
= x509parse_key(rsa
, buf
, (int)n
, NULL
, 0);
1294 ret
= x509parse_key(rsa
, buf
, (int)n
,
1295 (const unsigned char *)pwd
, strlen(pwd
));
1297 memset(buf
, 0, n
+ 1);
1304 #if defined _MSC_VER && !defined snprintf
1305 #define snprintf _snprintf
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
)
1316 const x509_name
*name
;
1319 memset(s
, 0, sizeof(s
));
1324 while (name
!= NULL
) {
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=");
1335 p
+= snprintf(p
, end
- p
, "C=");
1339 p
+= snprintf(p
, end
- p
, "L=");
1343 p
+= snprintf(p
, end
- p
, "ST=");
1346 case X520_ORGANIZATION
:
1347 p
+= snprintf(p
, end
- p
, "O=");
1351 p
+= snprintf(p
, end
- p
, "OU=");
1355 p
+= snprintf(p
, end
- p
, "0x%02X=",
1359 } else if (memcmp(name
->oid
.p
, OID_PKCS9
, 8) == 0) {
1360 switch (name
->oid
.p
[8]) {
1362 p
+= snprintf(p
, end
- p
, "emailAddress=");
1366 p
+= snprintf(p
, end
- p
, "0x%02X=",
1371 p
+= snprintf(p
, end
- p
, "\?\?=");
1373 for (i
= 0; i
< name
->val
.len
; i
++) {
1374 if (i
>= (int)sizeof(s
) - 1)
1378 if (c
< 32 || c
== 127 || (c
> 128 && c
< 160))
1384 p
+= snprintf(p
, end
- p
, "%s", s
);
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
)
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]) {
1438 p
+= snprintf(p
, end
- p
, "MD2");
1441 p
+= snprintf(p
, end
- p
, "MD4");
1444 p
+= snprintf(p
, end
- p
, "MD5");
1447 p
+= snprintf(p
, end
- p
, "SHA1");
1450 p
+= snprintf(p
, end
- p
, "???");
1454 p
+= snprintf(p
, end
- p
, "\n%sRSA key size : %d bits\n", prefix
,
1455 crt
->rsa
.N
.n
* (int)sizeof(unsigned long) * 8);
1461 * Return 0 if the certificate is still valid, or BADCERT_EXPIRED
1463 int x509parse_expired(const x509_cert
* crt
)
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
);
1486 static void x509_hash(const unsigned char *in
, int len
, int alg
, unsigned char *out
)
1489 #if defined(TROPICSSL_MD2_C)
1494 #if defined(TROPICSSL_MD4_C)
1506 memset(out
, '\xFF', len
);
1512 * Verify the certificate validity
1514 int x509parse_verify(x509_cert
* crt
,
1515 x509_cert
* trust_ca
, const char *cn
, int *flags
)
1522 unsigned char hash
[20];
1524 *flags
= x509parse_expired(crt
);
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
)
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.
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) {
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
);
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
;
1587 if (trust_ca
->max_pathlen
> 0 &&
1588 trust_ca
->max_pathlen
< pathlen
)
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
;
1604 trust_ca
= trust_ca
->next
;
1608 return (TROPICSSL_ERR_X509_CERT_VERIFY_FAILED
);
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
;
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
));
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
));
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
);
1655 cert_prv
= cert_cur
;
1656 cert_cur
= cert_cur
->next
;
1658 memset(cert_prv
, 0, sizeof(x509_cert
));
1659 if (cert_prv
!= crt
)
1661 } while (cert_cur
!= NULL
);
1664 #if defined(TROPICSSL_SELF_TEST)
1666 #include "tropicssl/certs.h"
1671 int x509_self_test(int verbose
)
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
));
1692 memset(&cacert
, 0, sizeof(x509_cert
));
1694 ret
= x509parse_crt(&cacert
, (const unsigned char *)test_ca_crt
,
1695 strlen(test_ca_crt
));
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) {
1719 printf("passed\n X.509 signature verify: ");
1721 ret
= x509parse_verify(&clicert
, &cacert
, "Joe User", &i
);
1730 printf("passed\n\n");
1733 x509_free(&clicert
);