comparison deps/Platinum/ThirdParty/Neptune/ThirdParty/axTLS/ssl/x509.c @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3425707ddbf6
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 goto end_cert;
117
118 bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
119
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)
123 {
124 MD5_CTX md5_ctx;
125 uint8_t md5_dgst[MD5_SIZE];
126 MD5_Init(&md5_ctx);
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);
130 }
131 else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
132 {
133 SHA1_CTX sha_ctx;
134 uint8_t sha_dgst[SHA1_SIZE];
135 SHA1_Init(&sha_ctx);
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);
139 }
140 else if (x509_ctx->sig_type == SIG_TYPE_MD2)
141 {
142 MD2_CTX md2_ctx;
143 uint8_t md2_dgst[MD2_SIZE];
144 MD2_Init(&md2_ctx);
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);
148 }
149
150 offset = end_tbs; /* skip the v3 data */
151 if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
152 asn1_signature(cert, &offset, x509_ctx))
153 goto end_cert;
154 #endif
155
156 /* GBG: compute the fingerprints */
157 {
158 MD5_CTX md5_ctx;
159 MD5_Init(&md5_ctx);
160 MD5_Update(&md5_ctx, cert, cert_size);
161 MD5_Final(x509_ctx->fingerprint.md5, &md5_ctx);
162 }
163 {
164 SHA1_CTX sha1_ctx;
165 SHA1_Init(&sha1_ctx);
166 SHA1_Update(&sha1_ctx, cert, cert_size);
167 SHA1_Final(x509_ctx->fingerprint.sha1, &sha1_ctx);
168 }
169 /* /GBG: compute the fingerprints */
170
171 if (len)
172 {
173 *len = cert_size;
174 }
175
176 ret = X509_OK;
177 end_cert:
178
179 #ifdef CONFIG_SSL_FULL_MODE
180 if (ret)
181 {
182 printf("Error: Invalid X509 ASN.1 file\n");
183 }
184 #endif
185
186 return ret;
187 }
188
189 /**
190 * Free an X.509 object's resources.
191 */
192 void x509_free(X509_CTX *x509_ctx)
193 {
194 X509_CTX *next;
195 int i;
196
197 if (x509_ctx == NULL) /* if already null, then don't bother */
198 return;
199
200 for (i = 0; i < X509_NUM_DN_TYPES; i++)
201 {
202 free(x509_ctx->ca_cert_dn[i]);
203 free(x509_ctx->cert_dn[i]);
204 }
205
206 free(x509_ctx->signature);
207
208 #ifdef CONFIG_SSL_CERT_VERIFICATION
209 if (x509_ctx->digest)
210 {
211 bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
212 }
213 #endif
214
215 RSA_free(x509_ctx->rsa_ctx);
216
217 next = x509_ctx->next;
218 free(x509_ctx);
219 x509_free(next); /* clear the chain */
220 }
221
222 #ifdef CONFIG_SSL_CERT_VERIFICATION
223 /**
224 * Take a signature and decrypt it.
225 */
226 static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
227 bigint *modulus, bigint *pub_exp)
228 {
229 int i, size;
230 bigint *decrypted_bi, *dat_bi;
231 bigint *bir = NULL;
232 uint8_t *block = (uint8_t *)alloca(sig_len);
233
234 /* decrypt */
235 dat_bi = bi_import(ctx, sig, sig_len);
236 ctx->mod_offset = BIGINT_M_OFFSET;
237
238 /* convert to a normal block */
239 decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
240
241 bi_export(ctx, decrypted_bi, block, sig_len);
242 ctx->mod_offset = BIGINT_M_OFFSET;
243
244 i = 10; /* start at the first possible non-padded byte */
245 while (block[i++] && i < sig_len);
246 size = sig_len - i;
247
248 /* get only the bit we want */
249 if (size > 0)
250 {
251 int len;
252 const uint8_t *sig_ptr = get_signature(&block[i], &len);
253
254 if (sig_ptr)
255 {
256 bir = bi_import(ctx, sig_ptr, len);
257 }
258 }
259
260 /* save a few bytes of memory */
261 bi_clear_cache(ctx);
262 return bir;
263 }
264
265 /**
266 * Do some basic checks on the certificate chain.
267 *
268 * Certificate verification consists of a number of checks:
269 * - A root certificate exists in the certificate store.
270 * - The date of the certificate is after the start date.
271 * - The date of the certificate is before the finish date.
272 * - The certificate chain is valid.
273 * - That the certificate(s) are not self-signed.
274 * - The signature of the certificate is valid.
275 */
276 int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
277 {
278 int ret = X509_OK, i = 0;
279 bigint *cert_sig;
280 X509_CTX *next_cert = NULL;
281 BI_CTX *ctx;
282 bigint *mod = NULL, *expn = NULL;
283 struct timeval tv;
284 int match_ca_cert = 0;
285 uint8_t is_self_signed = 0;
286
287 if (cert == NULL || ca_cert_ctx == NULL)
288 {
289 ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
290 goto end_verify;
291 }
292
293 /* last cert in the chain - look for a trusted cert */
294 if (cert->next == NULL && ca_cert_ctx)
295 {
296 while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
297 {
298 if (asn1_compare_dn(cert->ca_cert_dn,
299 ca_cert_ctx->cert[i]->cert_dn) == 0)
300 {
301 match_ca_cert = 1;
302 next_cert = ca_cert_ctx->cert[i];
303 break;
304 }
305
306 i++;
307 }
308
309 /* trusted cert not found */
310 if (match_ca_cert == 0)
311 {
312 ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
313 goto end_verify;
314 }
315 }
316 else
317 {
318 next_cert = cert->next;
319 }
320
321 gettimeofday(&tv, NULL);
322
323 /* check the not before date */
324 if (tv.tv_sec < cert->not_before)
325 {
326 ret = X509_VFY_ERROR_NOT_YET_VALID;
327 goto end_verify;
328 }
329
330 /* check the not after date */
331 if (tv.tv_sec > cert->not_after)
332 {
333 ret = X509_VFY_ERROR_EXPIRED;
334 goto end_verify;
335 }
336
337 ctx = cert->rsa_ctx->bi_ctx;
338
339 /* check for self-signing */
340 if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
341 {
342 is_self_signed = 1;
343 mod = cert->rsa_ctx->m;
344 expn = cert->rsa_ctx->e;
345 }
346 else if (next_cert != NULL)
347 {
348 mod = next_cert->rsa_ctx->m;
349 expn = next_cert->rsa_ctx->e;
350
351 /* check the chain integrity */
352 if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
353 {
354 ret = X509_VFY_ERROR_INVALID_CHAIN;
355 goto end_verify;
356 }
357 }
358
359 /* check the signature */
360 if (mod != NULL)
361 {
362 cert_sig = sig_verify(ctx, cert->signature, cert->sig_len,
363 bi_clone(ctx, mod), bi_clone(ctx, expn));
364
365 if (cert_sig && cert->digest)
366 {
367 if (bi_compare(cert_sig, cert->digest))
368 {
369 ret = X509_VFY_ERROR_BAD_SIGNATURE;
370 }
371
372 bi_free(ctx, cert_sig);
373
374 if (ret)
375 goto end_verify;
376 }
377 else
378 {
379 ret = X509_VFY_ERROR_BAD_SIGNATURE;
380 goto end_verify;
381 }
382 }
383
384 if (is_self_signed)
385 {
386 ret = X509_VFY_ERROR_SELF_SIGNED;
387 goto end_verify;
388 }
389
390 /* go down the certificate chain using recursion. */
391 if (ret == 0 && cert->next)
392 {
393 ret = x509_verify(ca_cert_ctx, next_cert);
394 }
395
396 end_verify:
397 return ret;
398 }
399 #endif
400
401 #if defined (CONFIG_SSL_FULL_MODE)
402 /**
403 * Used for diagnostics.
404 */
405 static const char *not_part_of_cert = "<Not Part Of Certificate>";
406 void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
407 {
408 if (cert == NULL)
409 return;
410
411 printf("=== CERTIFICATE ISSUED TO ===\n");
412 printf("Common Name (CN):\t\t");
413 printf("%s\n", cert->cert_dn[X509_COMMON_NAME] ?
414 cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert);
415
416 printf("Organization (O):\t\t");
417 printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ?
418 cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
419
420 printf("Organizational Unit (OU):\t");
421 printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ?
422 cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
423
424 printf("=== CERTIFICATE ISSUED BY ===\n");
425 printf("Common Name (CN):\t\t");
426 printf("%s\n", cert->ca_cert_dn[X509_COMMON_NAME] ?
427 cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert);
428
429 printf("Organization (O):\t\t");
430 printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
431 cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
432
433 printf("Organizational Unit (OU):\t");
434 printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ?
435 cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
436
437 printf("Not Before:\t\t\t%s", ctime(&cert->not_before));
438 printf("Not After:\t\t\t%s", ctime(&cert->not_after));
439 printf("RSA bitsize:\t\t\t%d\n", cert->rsa_ctx->num_octets*8);
440 printf("Sig Type:\t\t\t");
441 switch (cert->sig_type)
442 {
443 case SIG_TYPE_MD5:
444 printf("MD5\n");
445 break;
446 case SIG_TYPE_SHA1:
447 printf("SHA1\n");
448 break;
449 case SIG_TYPE_MD2:
450 printf("MD2\n");
451 break;
452 default:
453 printf("Unrecognized: %d\n", cert->sig_type);
454 break;
455 }
456
457 if (ca_cert_ctx)
458 {
459 printf("Verify:\t\t\t%s\n",
460 x509_display_error(x509_verify(ca_cert_ctx, cert)));
461 }
462
463 #if 0
464 print_blob("Signature", cert->signature, cert->sig_len);
465 bi_print("Modulus", cert->rsa_ctx->m);
466 bi_print("Pub Exp", cert->rsa_ctx->e);
467 #endif
468
469 if (ca_cert_ctx)
470 {
471 x509_print(cert->next, ca_cert_ctx);
472 }
473
474 TTY_FLUSH();
475 }
476
477 const char * x509_display_error(int error)
478 {
479 switch (error)
480 {
481 case X509_NOT_OK:
482 return "X509 not ok";
483
484 case X509_VFY_ERROR_NO_TRUSTED_CERT:
485 return "No trusted cert is available";
486
487 case X509_VFY_ERROR_BAD_SIGNATURE:
488 return "Bad signature";
489
490 case X509_VFY_ERROR_NOT_YET_VALID:
491 return "Cert is not yet valid";
492
493 case X509_VFY_ERROR_EXPIRED:
494 return "Cert has expired";
495
496 case X509_VFY_ERROR_SELF_SIGNED:
497 return "Cert is self-signed";
498
499 case X509_VFY_ERROR_INVALID_CHAIN:
500 return "Chain is invalid (check order of certs)";
501
502 case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
503 return "Unsupported digest";
504
505 case X509_INVALID_PRIV_KEY:
506 return "Invalid private key";
507
508 default:
509 return "Unknown";
510 }
511 }
512 #endif /* CONFIG_SSL_FULL_MODE */
513