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"
44 #ifdef CONFIG_SSL_CERT_VERIFICATION
46 * Retrieve the signature from a certificate.
48 static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
51 const uint8_t *ptr = NULL;
53 if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 ||
54 asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
57 if (asn1_sig[offset++] != ASN1_OCTET_STRING)
59 *len = get_asn1_length(asn1_sig, &offset);
60 ptr = &asn1_sig[offset]; /* all ok */
69 * Construct a new x509 object.
70 * @return 0 if ok. < 0 if there was a problem.
72 int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
74 int begin_tbs, end_tbs;
75 int ret = X509_NOT_OK, offset = 0, cert_size = 0;
79 *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);
92 if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
95 if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */
97 if (asn1_version(cert, &offset, x509_ctx))
101 if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */
102 asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
105 /* make sure the signature is ok */
106 if (asn1_signature_type(cert, &offset, x509_ctx))
108 ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
112 if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) ||
113 asn1_validity(cert, &offset, x509_ctx) ||
114 asn1_name(cert, &offset, x509_ctx->cert_dn) ||
115 asn1_public_key(cert, &offset, x509_ctx))
118 bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
120 #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
121 /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
122 if (x509_ctx->sig_type == SIG_TYPE_MD5)
125 uint8_t md5_dgst[MD5_SIZE];
127 MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
128 MD5_Final(md5_dgst, &md5_ctx);
129 x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
131 else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
134 uint8_t sha_dgst[SHA1_SIZE];
136 SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
137 SHA1_Final(sha_dgst, &sha_ctx);
138 x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
140 else if (x509_ctx->sig_type == SIG_TYPE_MD2)
143 uint8_t md2_dgst[MD2_SIZE];
145 MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
146 MD2_Final(md2_dgst, &md2_ctx);
147 x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
150 offset = end_tbs; /* skip the v3 data */
151 if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
152 asn1_signature(cert, &offset, x509_ctx))
164 #ifdef CONFIG_SSL_FULL_MODE
167 printf("Error: Invalid X509 ASN.1 file\n");
175 * Free an X.509 object's resources.
177 void x509_free(X509_CTX *x509_ctx)
182 if (x509_ctx == NULL) /* if already null, then don't bother */
185 for (i = 0; i < X509_NUM_DN_TYPES; i++)
187 free(x509_ctx->ca_cert_dn[i]);
188 free(x509_ctx->cert_dn[i]);
191 free(x509_ctx->signature);
193 #ifdef CONFIG_SSL_CERT_VERIFICATION
194 if (x509_ctx->digest)
196 bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
200 RSA_free(x509_ctx->rsa_ctx);
202 next = x509_ctx->next;
204 x509_free(next); /* clear the chain */
207 #ifdef CONFIG_SSL_CERT_VERIFICATION
209 * Take a signature and decrypt it.
211 static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
212 bigint *modulus, bigint *pub_exp)
215 bigint *decrypted_bi, *dat_bi;
217 uint8_t *block = (uint8_t *)alloca(sig_len);
220 dat_bi = bi_import(ctx, sig, sig_len);
221 ctx->mod_offset = BIGINT_M_OFFSET;
223 /* convert to a normal block */
224 decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
226 bi_export(ctx, decrypted_bi, block, sig_len);
227 ctx->mod_offset = BIGINT_M_OFFSET;
229 i = 10; /* start at the first possible non-padded byte */
230 while (block[i++] && i < sig_len);
233 /* get only the bit we want */
237 const uint8_t *sig_ptr = get_signature(&block[i], &len);
241 bir = bi_import(ctx, sig_ptr, len);
245 /* save a few bytes of memory */
251 * Do some basic checks on the certificate chain.
253 * Certificate verification consists of a number of checks:
254 * - The date of the certificate is after the start date.
255 * - The date of the certificate is before the finish date.
256 * - A root certificate exists in the certificate store.
257 * - That the certificate(s) are not self-signed.
258 * - The certificate chain is valid.
259 * - The signature of the certificate is valid.
261 int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
263 int ret = X509_OK, i = 0;
265 X509_CTX *next_cert = NULL;
267 bigint *mod = NULL, *expn = NULL;
268 int match_ca_cert = 0;
270 uint8_t is_self_signed = 0;
274 ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
278 /* a self-signed certificate that is not in the CA store - use this
279 to check the signature */
280 if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
283 ctx = cert->rsa_ctx->bi_ctx;
284 mod = cert->rsa_ctx->m;
285 expn = cert->rsa_ctx->e;
288 gettimeofday(&tv, NULL);
290 /* check the not before date */
291 if (tv.tv_sec < cert->not_before)
293 ret = X509_VFY_ERROR_NOT_YET_VALID;
297 /* check the not after date */
298 if (tv.tv_sec > cert->not_after)
300 ret = X509_VFY_ERROR_EXPIRED;
304 next_cert = cert->next;
306 /* last cert in the chain - look for a trusted cert */
307 if (next_cert == NULL)
309 if (ca_cert_ctx != NULL)
311 /* go thu the CA store */
312 while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
314 if (asn1_compare_dn(cert->ca_cert_dn,
315 ca_cert_ctx->cert[i]->cert_dn) == 0)
317 /* use this CA certificate for signature verification */
319 ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx;
320 mod = ca_cert_ctx->cert[i]->rsa_ctx->m;
321 expn = ca_cert_ctx->cert[i]->rsa_ctx->e;
329 /* couldn't find a trusted cert (& let self-signed errors be returned) */
330 if (!match_ca_cert && !is_self_signed)
332 ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
336 else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
338 /* check the chain */
339 ret = X509_VFY_ERROR_INVALID_CHAIN;
342 else /* use the next certificate in the chain for signature verify */
344 ctx = next_cert->rsa_ctx->bi_ctx;
345 mod = next_cert->rsa_ctx->m;
346 expn = next_cert->rsa_ctx->e;
349 /* cert is self signed */
350 if (!match_ca_cert && is_self_signed)
352 ret = X509_VFY_ERROR_SELF_SIGNED;
356 /* check the signature */
357 cert_sig = sig_verify(ctx, cert->signature, cert->sig_len,
358 bi_clone(ctx, mod), bi_clone(ctx, expn));
360 if (cert_sig && cert->digest)
362 if (bi_compare(cert_sig, cert->digest) != 0)
363 ret = X509_VFY_ERROR_BAD_SIGNATURE;
366 bi_free(ctx, cert_sig);
370 ret = X509_VFY_ERROR_BAD_SIGNATURE;
376 /* go down the certificate chain using recursion. */
377 if (next_cert != NULL)
379 ret = x509_verify(ca_cert_ctx, next_cert);
387 #if defined (CONFIG_SSL_FULL_MODE)
389 * Used for diagnostics.
391 static const char *not_part_of_cert = "<Not Part Of Certificate>";
392 void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
397 printf("=== CERTIFICATE ISSUED TO ===\n");
398 printf("Common Name (CN):\t\t");
399 printf("%s\n", cert->cert_dn[X509_COMMON_NAME] ?
400 cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert);
402 printf("Organization (O):\t\t");
403 printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ?
404 cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
406 printf("Organizational Unit (OU):\t");
407 printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ?
408 cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
410 printf("=== CERTIFICATE ISSUED BY ===\n");
411 printf("Common Name (CN):\t\t");
412 printf("%s\n", cert->ca_cert_dn[X509_COMMON_NAME] ?
413 cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert);
415 printf("Organization (O):\t\t");
416 printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
417 cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
419 printf("Organizational Unit (OU):\t");
420 printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ?
421 cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
423 printf("Not Before:\t\t\t%s", ctime(&cert->not_before));
424 printf("Not After:\t\t\t%s", ctime(&cert->not_after));
425 printf("RSA bitsize:\t\t\t%d\n", cert->rsa_ctx->num_octets*8);
426 printf("Sig Type:\t\t\t");
427 switch (cert->sig_type)
439 printf("Unrecognized: %d\n", cert->sig_type);
445 printf("Verify:\t\t\t\t%s\n",
446 x509_display_error(x509_verify(ca_cert_ctx, cert)));
450 print_blob("Signature", cert->signature, cert->sig_len);
451 bi_print("Modulus", cert->rsa_ctx->m);
452 bi_print("Pub Exp", cert->rsa_ctx->e);
457 x509_print(cert->next, ca_cert_ctx);
463 const char * x509_display_error(int error)
468 return "Certificate verify successful";
471 return "X509 not ok";
473 case X509_VFY_ERROR_NO_TRUSTED_CERT:
474 return "No trusted cert is available";
476 case X509_VFY_ERROR_BAD_SIGNATURE:
477 return "Bad signature";
479 case X509_VFY_ERROR_NOT_YET_VALID:
480 return "Cert is not yet valid";
482 case X509_VFY_ERROR_EXPIRED:
483 return "Cert has expired";
485 case X509_VFY_ERROR_SELF_SIGNED:
486 return "Cert is self-signed";
488 case X509_VFY_ERROR_INVALID_CHAIN:
489 return "Chain is invalid (check order of certs)";
491 case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
492 return "Unsupported digest";
494 case X509_INVALID_PRIV_KEY:
495 return "Invalid private key";
501 #endif /* CONFIG_SSL_FULL_MODE */