2 * Copyright (c) 2007, Cameron Rich
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of the axTLS project nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Certificate processing.
42 #include "crypto_misc.h"
45 #ifdef CONFIG_SSL_CERT_VERIFICATION
47 * Retrieve the signature from a certificate.
49 static const uint8_t *get_signature(const uint8_t *asn1_sig
, int *len
)
52 const uint8_t *ptr
= NULL
;
54 if (asn1_next_obj(asn1_sig
, &offset
, ASN1_SEQUENCE
) < 0 ||
55 asn1_skip_obj(asn1_sig
, &offset
, ASN1_SEQUENCE
))
58 if (asn1_sig
[offset
++] != ASN1_OCTET_STRING
)
60 *len
= get_asn1_length(asn1_sig
, &offset
);
61 ptr
= &asn1_sig
[offset
]; /* all ok */
70 * Construct a new x509 object.
71 * @return 0 if ok. < 0 if there was a problem.
73 int x509_new(const uint8_t *cert
, int *len
, X509_CTX
**ctx
)
76 int begin_tbs
, end_tbs
;
77 int ret
= X509_NOT_OK
, offset
= 0, cert_size
= 0;
80 *ctx
= (X509_CTX
*)calloc(1, sizeof(X509_CTX
));
82 /* get the certificate size */
83 asn1_skip_obj(cert
, &cert_size
, ASN1_SEQUENCE
);
85 if (asn1_next_obj(cert
, &offset
, ASN1_SEQUENCE
) < 0)
88 begin_tbs
= offset
; /* start of the tbs */
89 end_tbs
= begin_tbs
; /* work out the end of the tbs */
90 asn1_skip_obj(cert
, &end_tbs
, ASN1_SEQUENCE
);
91 if (asn1_next_obj(cert
, &offset
, ASN1_SEQUENCE
) < 0)
93 if (cert
[offset
] == ASN1_EXPLICIT_TAG
) /* optional version */
95 if (asn1_version(cert
, &offset
, x509_ctx
))
98 if (asn1_skip_obj(cert
, &offset
, ASN1_INTEGER
) || /* serial number */
99 asn1_next_obj(cert
, &offset
, ASN1_SEQUENCE
) < 0)
103 /* make sure the signature is ok */
104 if (asn1_signature_type(cert
, &offset
, x509_ctx
))
106 ret
= X509_VFY_ERROR_UNSUPPORTED_DIGEST
;
109 if (asn1_name(cert
, &offset
, x509_ctx
->ca_cert_dn
) ||
110 asn1_validity(cert
, &offset
, x509_ctx
) ||
111 asn1_name(cert
, &offset
, x509_ctx
->cert_dn
) ||
112 asn1_public_key(cert
, &offset
, x509_ctx
))
116 bi_ctx
= x509_ctx
->rsa_ctx
->bi_ctx
;
117 #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
119 /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
120 if (x509_ctx
->sig_type
== SIG_TYPE_MD5
)
123 uint8_t md5_dgst
[MD5_SIZE
];
125 MD5_Update(&md5_ctx
, &cert
[begin_tbs
], end_tbs
-begin_tbs
);
126 MD5_Final(md5_dgst
, &md5_ctx
);
127 x509_ctx
->digest
= bi_import(bi_ctx
, md5_dgst
, MD5_SIZE
);
129 else if (x509_ctx
->sig_type
== SIG_TYPE_SHA1
)
132 uint8_t sha_dgst
[SHA1_SIZE
];
134 SHA1_Update(&sha_ctx
, &cert
[begin_tbs
], end_tbs
-begin_tbs
);
135 SHA1_Final(sha_dgst
, &sha_ctx
);
136 x509_ctx
->digest
= bi_import(bi_ctx
, sha_dgst
, SHA1_SIZE
);
138 else if (x509_ctx
->sig_type
== SIG_TYPE_MD2
)
141 uint8_t md2_dgst
[MD2_SIZE
];
143 MD2_Update(&md2_ctx
, &cert
[begin_tbs
], end_tbs
-begin_tbs
);
144 MD2_Final(md2_dgst
, &md2_ctx
);
145 x509_ctx
->digest
= bi_import(bi_ctx
, md2_dgst
, MD2_SIZE
);
148 if (cert
[offset
] == ASN1_V3_DATA
)
153 get_asn1_length(cert
, &offset
);
155 if ((suboffset
= asn1_find_subjectaltname(cert
, offset
)) > 0)
157 if (asn1_next_obj(cert
, &suboffset
, ASN1_OCTET_STRING
) > 0)
161 if ((altlen
= asn1_next_obj(cert
,
162 &suboffset
, ASN1_SEQUENCE
)) > 0)
164 int endalt
= suboffset
+ altlen
;
167 while (suboffset
< endalt
)
169 int type
= cert
[suboffset
++];
170 int dnslen
= get_asn1_length(cert
, &suboffset
);
172 if (type
== ASN1_CONTEXT_DNSNAME
)
174 x509_ctx
->subject_alt_dnsnames
= (char**)
175 realloc(x509_ctx
->subject_alt_dnsnames
,
176 (totalnames
+ 2) * sizeof(char*));
177 x509_ctx
->subject_alt_dnsnames
[totalnames
] =
178 (char*)malloc(dnslen
+ 1);
179 x509_ctx
->subject_alt_dnsnames
[totalnames
+1] = NULL
;
180 memcpy(x509_ctx
->subject_alt_dnsnames
[totalnames
],
181 cert
+ suboffset
, dnslen
);
182 x509_ctx
->subject_alt_dnsnames
[
183 totalnames
][dnslen
] = 0;
194 offset
= end_tbs
; /* skip the rest of v3 data */
195 if (asn1_skip_obj(cert
, &offset
, ASN1_SEQUENCE
) ||
196 asn1_signature(cert
, &offset
, x509_ctx
))
209 #ifdef CONFIG_SSL_FULL_MODE
210 printf("Error: Invalid X509 ASN.1 file (%s)\n",
211 x509_display_error(ret
));
220 * Free an X.509 object's resources.
222 void x509_free(X509_CTX
*x509_ctx
)
227 if (x509_ctx
== NULL
) /* if already null, then don't bother */
230 for (i
= 0; i
< X509_NUM_DN_TYPES
; i
++)
232 free(x509_ctx
->ca_cert_dn
[i
]);
233 free(x509_ctx
->cert_dn
[i
]);
236 free(x509_ctx
->signature
);
238 #ifdef CONFIG_SSL_CERT_VERIFICATION
239 if (x509_ctx
->digest
)
241 bi_free(x509_ctx
->rsa_ctx
->bi_ctx
, x509_ctx
->digest
);
244 if (x509_ctx
->subject_alt_dnsnames
)
246 for (i
= 0; x509_ctx
->subject_alt_dnsnames
[i
]; ++i
)
247 free(x509_ctx
->subject_alt_dnsnames
[i
]);
249 free(x509_ctx
->subject_alt_dnsnames
);
253 RSA_free(x509_ctx
->rsa_ctx
);
254 next
= x509_ctx
->next
;
256 x509_free(next
); /* clear the chain */
259 #ifdef CONFIG_SSL_CERT_VERIFICATION
261 * Take a signature and decrypt it.
263 static bigint
*sig_verify(BI_CTX
*ctx
, const uint8_t *sig
, int sig_len
,
264 bigint
*modulus
, bigint
*pub_exp
)
267 bigint
*decrypted_bi
, *dat_bi
;
269 uint8_t *block
= (uint8_t *)alloca(sig_len
);
272 dat_bi
= bi_import(ctx
, sig
, sig_len
);
273 ctx
->mod_offset
= BIGINT_M_OFFSET
;
275 /* convert to a normal block */
276 decrypted_bi
= bi_mod_power2(ctx
, dat_bi
, modulus
, pub_exp
);
278 bi_export(ctx
, decrypted_bi
, block
, sig_len
);
279 ctx
->mod_offset
= BIGINT_M_OFFSET
;
281 i
= 10; /* start at the first possible non-padded byte */
282 while (block
[i
++] && i
< sig_len
);
285 /* get only the bit we want */
289 const uint8_t *sig_ptr
= get_signature(&block
[i
], &len
);
293 bir
= bi_import(ctx
, sig_ptr
, len
);
297 /* save a few bytes of memory */
303 * Do some basic checks on the certificate chain.
305 * Certificate verification consists of a number of checks:
306 * - The date of the certificate is after the start date.
307 * - The date of the certificate is before the finish date.
308 * - A root certificate exists in the certificate store.
309 * - That the certificate(s) are not self-signed.
310 * - The certificate chain is valid.
311 * - The signature of the certificate is valid.
313 int x509_verify(const CA_CERT_CTX
*ca_cert_ctx
, const X509_CTX
*cert
)
315 int ret
= X509_OK
, i
= 0;
317 X509_CTX
*next_cert
= NULL
;
319 bigint
*mod
= NULL
, *expn
= NULL
;
320 int match_ca_cert
= 0;
322 uint8_t is_self_signed
= 0;
326 ret
= X509_VFY_ERROR_NO_TRUSTED_CERT
;
330 /* a self-signed certificate that is not in the CA store - use this
331 to check the signature */
332 if (asn1_compare_dn(cert
->ca_cert_dn
, cert
->cert_dn
) == 0)
334 printf("self signed cert\r\n");
336 ctx
= cert
->rsa_ctx
->bi_ctx
;
337 mod
= cert
->rsa_ctx
->m
;
338 expn
= cert
->rsa_ctx
->e
;
341 gettimeofday(&tv
, NULL
);
343 /* check the not before date */
344 if (tv
.tv_sec
< cert
->not_before
)
346 ret
= X509_VFY_ERROR_NOT_YET_VALID
;
350 /* check the not after date */
351 if (tv
.tv_sec
> cert
->not_after
)
353 ret
= X509_VFY_ERROR_EXPIRED
;
357 next_cert
= cert
->next
;
359 /* last cert in the chain - look for a trusted cert */
360 if (next_cert
== NULL
)
362 if (ca_cert_ctx
!= NULL
)
364 /* go thu the CA store */
365 while (i
< CONFIG_X509_MAX_CA_CERTS
&& ca_cert_ctx
->cert
[i
])
367 if (asn1_compare_dn(cert
->ca_cert_dn
,
368 ca_cert_ctx
->cert
[i
]->cert_dn
) == 0)
370 /* use this CA certificate for signature verification */
372 ctx
= ca_cert_ctx
->cert
[i
]->rsa_ctx
->bi_ctx
;
373 mod
= ca_cert_ctx
->cert
[i
]->rsa_ctx
->m
;
374 expn
= ca_cert_ctx
->cert
[i
]->rsa_ctx
->e
;
382 /* couldn't find a trusted cert (& let self-signed errors
384 if (!match_ca_cert
&& !is_self_signed
)
386 ret
= X509_VFY_ERROR_NO_TRUSTED_CERT
;
390 else if (asn1_compare_dn(cert
->ca_cert_dn
, next_cert
->cert_dn
) != 0)
392 /* check the chain */
393 ret
= X509_VFY_ERROR_INVALID_CHAIN
;
396 else /* use the next certificate in the chain for signature verify */
398 ctx
= next_cert
->rsa_ctx
->bi_ctx
;
399 mod
= next_cert
->rsa_ctx
->m
;
400 expn
= next_cert
->rsa_ctx
->e
;
403 /* cert is self signed */
404 if (!match_ca_cert
&& is_self_signed
)
406 ret
= X509_VFY_ERROR_SELF_SIGNED
;
410 /* check the signature */
411 cert_sig
= sig_verify(ctx
, cert
->signature
, cert
->sig_len
,
412 bi_clone(ctx
, mod
), bi_clone(ctx
, expn
));
414 if (cert_sig
&& cert
->digest
)
416 if (bi_compare(cert_sig
, cert
->digest
) != 0)
417 ret
= X509_VFY_ERROR_BAD_SIGNATURE
;
420 bi_free(ctx
, cert_sig
);
424 ret
= X509_VFY_ERROR_BAD_SIGNATURE
;
430 /* go down the certificate chain using recursion. */
431 if (next_cert
!= NULL
)
433 ret
= x509_verify(ca_cert_ctx
, next_cert
);
441 #if defined (CONFIG_SSL_FULL_MODE)
443 * Used for diagnostics.
445 static const char *not_part_of_cert
= "<Not Part Of Certificate>";
446 void x509_print(const X509_CTX
*cert
, CA_CERT_CTX
*ca_cert_ctx
)
451 printf("=== CERTIFICATE ISSUED TO ===\n");
452 printf("Common Name (CN):\t\t");
453 printf("%s\r\n", cert
->cert_dn
[X509_COMMON_NAME
] ?
454 cert
->cert_dn
[X509_COMMON_NAME
] : not_part_of_cert
);
456 printf("Organization (O):\t\t");
457 printf("%s\r\n", cert
->cert_dn
[X509_ORGANIZATION
] ?
458 cert
->cert_dn
[X509_ORGANIZATION
] : not_part_of_cert
);
460 printf("Organizational Unit (OU):\t");
461 printf("%s\r\n", cert
->cert_dn
[X509_ORGANIZATIONAL_UNIT
] ?
462 cert
->cert_dn
[X509_ORGANIZATIONAL_UNIT
] : not_part_of_cert
);
464 printf("=== CERTIFICATE ISSUED BY ===\r\n");
465 printf("Common Name (CN):\t\t");
466 printf("%s\r\n", cert
->ca_cert_dn
[X509_COMMON_NAME
] ?
467 cert
->ca_cert_dn
[X509_COMMON_NAME
] : not_part_of_cert
);
469 printf("Organization (O):\t\t");
470 printf("%s\r\n", cert
->ca_cert_dn
[X509_ORGANIZATION
] ?
471 cert
->ca_cert_dn
[X509_ORGANIZATION
] : not_part_of_cert
);
473 printf("Organizational Unit (OU):\t");
474 printf("%s\r\n", cert
->ca_cert_dn
[X509_ORGANIZATIONAL_UNIT
] ?
475 cert
->ca_cert_dn
[X509_ORGANIZATIONAL_UNIT
] : not_part_of_cert
);
477 printf("Not Before:\t\t\t%s\r\n", ctime(&cert
->not_before
));
478 printf("Not After:\t\t\t%s\r\n", ctime(&cert
->not_after
));
479 printf("RSA bitsize:\t\t\t%d\r\n", cert
->rsa_ctx
->num_octets
*8);
480 printf("Sig Type:\t\t\t");
481 switch (cert
->sig_type
)
493 printf("Unrecognized: %d\r\n", cert
->sig_type
);
499 printf("Verify:\t\t\t\t%s\r\n",
500 x509_display_error(x509_verify(ca_cert_ctx
, cert
)));
504 print_blob("Signature", cert
->signature
, cert
->sig_len
);
505 bi_print("Modulus", cert
->rsa_ctx
->m
);
506 bi_print("Pub Exp", cert
->rsa_ctx
->e
);
511 x509_print(cert
->next
, ca_cert_ctx
);
517 const char * x509_display_error(int error
)
522 return "Certificate verify successful";
525 return "X509 not ok";
527 case X509_VFY_ERROR_NO_TRUSTED_CERT
:
528 return "No trusted cert is available";
530 case X509_VFY_ERROR_BAD_SIGNATURE
:
531 return "Bad signature";
533 case X509_VFY_ERROR_NOT_YET_VALID
:
534 return "Cert is not yet valid";
536 case X509_VFY_ERROR_EXPIRED
:
537 return "Cert has expired";
539 case X509_VFY_ERROR_SELF_SIGNED
:
540 return "Cert is self-signed";
542 case X509_VFY_ERROR_INVALID_CHAIN
:
543 return "Chain is invalid (check order of certs)";
545 case X509_VFY_ERROR_UNSUPPORTED_DIGEST
:
546 return "Unsupported digest";
548 case X509_INVALID_PRIV_KEY
:
549 return "Invalid private key";
555 #endif /* CONFIG_SSL_FULL_MODE */