Annotation of embedaddon/axTLS/ssl/x509.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 2007, Cameron Rich
3: *
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions are met:
8: *
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.
17: *
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.
29: */
30:
31: /**
32: * @file x509.c
33: *
34: * Certificate processing.
35: */
36:
37: #include <stdio.h>
38: #include <stdlib.h>
39: #include <string.h>
40: #include <time.h>
41: #include "os_port.h"
42: #include "crypto_misc.h"
43:
44: #ifdef CONFIG_SSL_CERT_VERIFICATION
45: /**
46: * Retrieve the signature from a certificate.
47: */
48: static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
49: {
50: int offset = 0;
51: const uint8_t *ptr = NULL;
52:
53: if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 ||
54: asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
55: goto end_get_sig;
56:
57: if (asn1_sig[offset++] != ASN1_OCTET_STRING)
58: goto end_get_sig;
59: *len = get_asn1_length(asn1_sig, &offset);
60: ptr = &asn1_sig[offset]; /* all ok */
61:
62: end_get_sig:
63: return ptr;
64: }
65:
66: #endif
67:
68: /**
69: * Construct a new x509 object.
70: * @return 0 if ok. < 0 if there was a problem.
71: */
72: int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
73: {
74: int begin_tbs, end_tbs;
75: int ret = X509_NOT_OK, offset = 0, cert_size = 0;
76: X509_CTX *x509_ctx;
77: BI_CTX *bi_ctx;
78:
79: *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
80: x509_ctx = *ctx;
81:
82: /* get the certificate size */
83: asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE);
84:
85: if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
86: goto end_cert;
87:
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:
92: if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
93: goto end_cert;
94:
95: if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */
96: {
97: if (asn1_version(cert, &offset, x509_ctx))
98: goto end_cert;
99: }
100:
101: if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */
102: asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
103: goto end_cert;
104:
105: /* make sure the signature is ok */
106: if (asn1_signature_type(cert, &offset, x509_ctx))
107: {
108: ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
109: goto end_cert;
110: }
111:
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))
116: {
117: goto end_cert;
118: }
119:
120: bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
121:
122: #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
123: /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
124: if (x509_ctx->sig_type == SIG_TYPE_MD5)
125: {
126: MD5_CTX md5_ctx;
127: uint8_t md5_dgst[MD5_SIZE];
128: MD5_Init(&md5_ctx);
129: MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
130: MD5_Final(md5_dgst, &md5_ctx);
131: x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
132: }
133: else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
134: {
135: SHA1_CTX sha_ctx;
136: uint8_t sha_dgst[SHA1_SIZE];
137: SHA1_Init(&sha_ctx);
138: SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
139: SHA1_Final(sha_dgst, &sha_ctx);
140: x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
141: }
142: else if (x509_ctx->sig_type == SIG_TYPE_MD2)
143: {
144: MD2_CTX md2_ctx;
145: uint8_t md2_dgst[MD2_SIZE];
146: MD2_Init(&md2_ctx);
147: MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
148: MD2_Final(md2_dgst, &md2_ctx);
149: x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
150: }
151:
152: if (cert[offset] == ASN1_V3_DATA)
153: {
154: int suboffset;
155:
156: ++offset;
157: get_asn1_length(cert, &offset);
158:
159: if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0)
160: {
161: if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0)
162: {
163: int altlen;
164:
165: if ((altlen = asn1_next_obj(cert,
166: &suboffset, ASN1_SEQUENCE)) > 0)
167: {
168: int endalt = suboffset + altlen;
169: int totalnames = 0;
170:
171: while (suboffset < endalt)
172: {
173: int type = cert[suboffset++];
174: int dnslen = get_asn1_length(cert, &suboffset);
175:
176: if (type == ASN1_CONTEXT_DNSNAME)
177: {
178: x509_ctx->subject_alt_dnsnames = (char**)
179: realloc(x509_ctx->subject_alt_dnsnames,
180: (totalnames + 2) * sizeof(char*));
181: x509_ctx->subject_alt_dnsnames[totalnames] =
182: (char*)malloc(dnslen + 1);
183: x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL;
184: memcpy(x509_ctx->subject_alt_dnsnames[totalnames],
185: cert + suboffset, dnslen);
186: x509_ctx->subject_alt_dnsnames[
187: totalnames][dnslen] = 0;
188: ++totalnames;
189: }
190:
191: suboffset += dnslen;
192: }
193: }
194: }
195: }
196: }
197:
198: offset = end_tbs; /* skip the rest of v3 data */
199: if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
200: asn1_signature(cert, &offset, x509_ctx))
201: goto end_cert;
202: #endif
203: ret = X509_OK;
204: end_cert:
205: if (len)
206: {
207: *len = cert_size;
208: }
209:
210: if (ret)
211: {
212: #ifdef CONFIG_SSL_FULL_MODE
213: printf("Error: Invalid X509 ASN.1 file (%s)\n",
214: x509_display_error(ret));
215: #endif
216: x509_free(x509_ctx);
217: *ctx = NULL;
218: }
219:
220: return ret;
221: }
222:
223: /**
224: * Free an X.509 object's resources.
225: */
226: void x509_free(X509_CTX *x509_ctx)
227: {
228: X509_CTX *next;
229: int i;
230:
231: if (x509_ctx == NULL) /* if already null, then don't bother */
232: return;
233:
234: for (i = 0; i < X509_NUM_DN_TYPES; i++)
235: {
236: free(x509_ctx->ca_cert_dn[i]);
237: free(x509_ctx->cert_dn[i]);
238: }
239:
240: free(x509_ctx->signature);
241:
242: #ifdef CONFIG_SSL_CERT_VERIFICATION
243: if (x509_ctx->digest)
244: {
245: bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
246: }
247:
248: if (x509_ctx->subject_alt_dnsnames)
249: {
250: for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i)
251: free(x509_ctx->subject_alt_dnsnames[i]);
252:
253: free(x509_ctx->subject_alt_dnsnames);
254: }
255: #endif
256:
257: RSA_free(x509_ctx->rsa_ctx);
258: next = x509_ctx->next;
259: free(x509_ctx);
260: x509_free(next); /* clear the chain */
261: }
262:
263: #ifdef CONFIG_SSL_CERT_VERIFICATION
264: /**
265: * Take a signature and decrypt it.
266: */
267: static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
268: bigint *modulus, bigint *pub_exp)
269: {
270: int i, size;
271: bigint *decrypted_bi, *dat_bi;
272: bigint *bir = NULL;
273: uint8_t *block = (uint8_t *)alloca(sig_len);
274:
275: /* decrypt */
276: dat_bi = bi_import(ctx, sig, sig_len);
277: ctx->mod_offset = BIGINT_M_OFFSET;
278:
279: /* convert to a normal block */
280: decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
281:
282: bi_export(ctx, decrypted_bi, block, sig_len);
283: ctx->mod_offset = BIGINT_M_OFFSET;
284:
285: i = 10; /* start at the first possible non-padded byte */
286: while (block[i++] && i < sig_len);
287: size = sig_len - i;
288:
289: /* get only the bit we want */
290: if (size > 0)
291: {
292: int len;
293: const uint8_t *sig_ptr = get_signature(&block[i], &len);
294:
295: if (sig_ptr)
296: {
297: bir = bi_import(ctx, sig_ptr, len);
298: }
299: }
300:
301: /* save a few bytes of memory */
302: bi_clear_cache(ctx);
303: return bir;
304: }
305:
306: /**
307: * Do some basic checks on the certificate chain.
308: *
309: * Certificate verification consists of a number of checks:
310: * - The date of the certificate is after the start date.
311: * - The date of the certificate is before the finish date.
312: * - A root certificate exists in the certificate store.
313: * - That the certificate(s) are not self-signed.
314: * - The certificate chain is valid.
315: * - The signature of the certificate is valid.
316: */
317: int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
318: {
319: int ret = X509_OK, i = 0;
320: bigint *cert_sig;
321: X509_CTX *next_cert = NULL;
322: BI_CTX *ctx = NULL;
323: bigint *mod = NULL, *expn = NULL;
324: int match_ca_cert = 0;
325: struct timeval tv;
326: uint8_t is_self_signed = 0;
327:
328: if (cert == NULL)
329: {
330: ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
331: goto end_verify;
332: }
333:
334: /* a self-signed certificate that is not in the CA store - use this
335: to check the signature */
336: if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
337: {
338: is_self_signed = 1;
339: ctx = cert->rsa_ctx->bi_ctx;
340: mod = cert->rsa_ctx->m;
341: expn = cert->rsa_ctx->e;
342: }
343:
344: gettimeofday(&tv, NULL);
345:
346: /* check the not before date */
347: if (tv.tv_sec < cert->not_before)
348: {
349: ret = X509_VFY_ERROR_NOT_YET_VALID;
350: goto end_verify;
351: }
352:
353: /* check the not after date */
354: if (tv.tv_sec > cert->not_after)
355: {
356: ret = X509_VFY_ERROR_EXPIRED;
357: goto end_verify;
358: }
359:
360: next_cert = cert->next;
361:
362: /* last cert in the chain - look for a trusted cert */
363: if (next_cert == NULL)
364: {
365: if (ca_cert_ctx != NULL)
366: {
367: /* go thu the CA store */
368: while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
369: {
370: if (asn1_compare_dn(cert->ca_cert_dn,
371: ca_cert_ctx->cert[i]->cert_dn) == 0)
372: {
373: /* use this CA certificate for signature verification */
374: match_ca_cert = 1;
375: ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx;
376: mod = ca_cert_ctx->cert[i]->rsa_ctx->m;
377: expn = ca_cert_ctx->cert[i]->rsa_ctx->e;
378: break;
379: }
380:
381: i++;
382: }
383: }
384:
385: /* couldn't find a trusted cert (& let self-signed errors
386: be returned) */
387: if (!match_ca_cert && !is_self_signed)
388: {
389: ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
390: goto end_verify;
391: }
392: }
393: else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
394: {
395: /* check the chain */
396: ret = X509_VFY_ERROR_INVALID_CHAIN;
397: goto end_verify;
398: }
399: else /* use the next certificate in the chain for signature verify */
400: {
401: ctx = next_cert->rsa_ctx->bi_ctx;
402: mod = next_cert->rsa_ctx->m;
403: expn = next_cert->rsa_ctx->e;
404: }
405:
406: /* cert is self signed */
407: if (!match_ca_cert && is_self_signed)
408: {
409: ret = X509_VFY_ERROR_SELF_SIGNED;
410: goto end_verify;
411: }
412:
413: /* check the signature */
414: cert_sig = sig_verify(ctx, cert->signature, cert->sig_len,
415: bi_clone(ctx, mod), bi_clone(ctx, expn));
416:
417: if (cert_sig && cert->digest)
418: {
419: if (bi_compare(cert_sig, cert->digest) != 0)
420: ret = X509_VFY_ERROR_BAD_SIGNATURE;
421:
422:
423: bi_free(ctx, cert_sig);
424: }
425: else
426: {
427: ret = X509_VFY_ERROR_BAD_SIGNATURE;
428: }
429:
430: if (ret)
431: goto end_verify;
432:
433: /* go down the certificate chain using recursion. */
434: if (next_cert != NULL)
435: {
436: ret = x509_verify(ca_cert_ctx, next_cert);
437: }
438:
439: end_verify:
440: return ret;
441: }
442: #endif
443:
444: #if defined (CONFIG_SSL_FULL_MODE)
445: /**
446: * Used for diagnostics.
447: */
448: static const char *not_part_of_cert = "<Not Part Of Certificate>";
449: void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
450: {
451: if (cert == NULL)
452: return;
453:
454: printf("=== CERTIFICATE ISSUED TO ===\n");
455: printf("Common Name (CN):\t\t");
456: printf("%s\n", cert->cert_dn[X509_COMMON_NAME] ?
457: cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert);
458:
459: printf("Organization (O):\t\t");
460: printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ?
461: cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
462:
463: printf("Organizational Unit (OU):\t");
464: printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ?
465: cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
466:
467: printf("=== CERTIFICATE ISSUED BY ===\n");
468: printf("Common Name (CN):\t\t");
469: printf("%s\n", cert->ca_cert_dn[X509_COMMON_NAME] ?
470: cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert);
471:
472: printf("Organization (O):\t\t");
473: printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
474: cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
475:
476: printf("Organizational Unit (OU):\t");
477: printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ?
478: cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
479:
480: printf("Not Before:\t\t\t%s", ctime(&cert->not_before));
481: printf("Not After:\t\t\t%s", ctime(&cert->not_after));
482: printf("RSA bitsize:\t\t\t%d\n", cert->rsa_ctx->num_octets*8);
483: printf("Sig Type:\t\t\t");
484: switch (cert->sig_type)
485: {
486: case SIG_TYPE_MD5:
487: printf("MD5\n");
488: break;
489: case SIG_TYPE_SHA1:
490: printf("SHA1\n");
491: break;
492: case SIG_TYPE_MD2:
493: printf("MD2\n");
494: break;
495: default:
496: printf("Unrecognized: %d\n", cert->sig_type);
497: break;
498: }
499:
500: if (ca_cert_ctx)
501: {
502: printf("Verify:\t\t\t\t%s\n",
503: x509_display_error(x509_verify(ca_cert_ctx, cert)));
504: }
505:
506: #if 0
507: print_blob("Signature", cert->signature, cert->sig_len);
508: bi_print("Modulus", cert->rsa_ctx->m);
509: bi_print("Pub Exp", cert->rsa_ctx->e);
510: #endif
511:
512: if (ca_cert_ctx)
513: {
514: x509_print(cert->next, ca_cert_ctx);
515: }
516:
517: TTY_FLUSH();
518: }
519:
520: const char * x509_display_error(int error)
521: {
522: switch (error)
523: {
524: case X509_OK:
525: return "Certificate verify successful";
526:
527: case X509_NOT_OK:
528: return "X509 not ok";
529:
530: case X509_VFY_ERROR_NO_TRUSTED_CERT:
531: return "No trusted cert is available";
532:
533: case X509_VFY_ERROR_BAD_SIGNATURE:
534: return "Bad signature";
535:
536: case X509_VFY_ERROR_NOT_YET_VALID:
537: return "Cert is not yet valid";
538:
539: case X509_VFY_ERROR_EXPIRED:
540: return "Cert has expired";
541:
542: case X509_VFY_ERROR_SELF_SIGNED:
543: return "Cert is self-signed";
544:
545: case X509_VFY_ERROR_INVALID_CHAIN:
546: return "Chain is invalid (check order of certs)";
547:
548: case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
549: return "Unsupported digest";
550:
551: case X509_INVALID_PRIV_KEY:
552: return "Invalid private key";
553:
554: default:
555: return "Unknown";
556: }
557: }
558: #endif /* CONFIG_SSL_FULL_MODE */
559:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>