]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/net/https/axTLS/ssl/x509.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[tmk_keyboard.git] / tool / mbed / mbed-sdk / libraries / net / https / axTLS / ssl / x509.c
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 <time.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include "os_port.h"
42 #include "crypto_misc.h"
43 #include "sockets.h"
44 #include "config.h"
45 #ifdef CONFIG_SSL_CERT_VERIFICATION
46 /**
47 * Retrieve the signature from a certificate.
48 */
49 static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
50 {
51 int offset = 0;
52 const uint8_t *ptr = NULL;
53
54 if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 ||
55 asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
56 goto end_get_sig;
57
58 if (asn1_sig[offset++] != ASN1_OCTET_STRING)
59 goto end_get_sig;
60 *len = get_asn1_length(asn1_sig, &offset);
61 ptr = &asn1_sig[offset]; /* all ok */
62
63 end_get_sig:
64 return ptr;
65 }
66
67 #endif
68
69 /**
70 * Construct a new x509 object.
71 * @return 0 if ok. < 0 if there was a problem.
72 */
73 int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
74 {
75
76 int begin_tbs, end_tbs;
77 int ret = X509_NOT_OK, offset = 0, cert_size = 0;
78 X509_CTX *x509_ctx;
79 BI_CTX *bi_ctx;
80 *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
81 x509_ctx = *ctx;
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 if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
92 goto end_cert;
93 if (cert[offset] == ASN1_EXPLICIT_TAG) /* optional version */
94 {
95 if (asn1_version(cert, &offset, x509_ctx))
96 goto end_cert;
97 }
98 if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */
99 asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
100 {
101 goto end_cert;
102 }
103 /* make sure the signature is ok */
104 if (asn1_signature_type(cert, &offset, x509_ctx))
105 {
106 ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
107 goto end_cert;
108 }
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))
113 {
114 goto end_cert;
115 }
116 bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
117 #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
118
119 /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
120 if (x509_ctx->sig_type == SIG_TYPE_MD5)
121 {
122 MD5_CTX md5_ctx;
123 uint8_t md5_dgst[MD5_SIZE];
124 MD5_Init(&md5_ctx);
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);
128 }
129 else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
130 {
131 SHA1_CTX sha_ctx;
132 uint8_t sha_dgst[SHA1_SIZE];
133 SHA1_Init(&sha_ctx);
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);
137 }
138 else if (x509_ctx->sig_type == SIG_TYPE_MD2)
139 {
140 MD2_CTX md2_ctx;
141 uint8_t md2_dgst[MD2_SIZE];
142 MD2_Init(&md2_ctx);
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);
146 }
147
148 if (cert[offset] == ASN1_V3_DATA)
149 {
150 int suboffset;
151
152 ++offset;
153 get_asn1_length(cert, &offset);
154
155 if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0)
156 {
157 if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0)
158 {
159 int altlen;
160
161 if ((altlen = asn1_next_obj(cert,
162 &suboffset, ASN1_SEQUENCE)) > 0)
163 {
164 int endalt = suboffset + altlen;
165 int totalnames = 0;
166
167 while (suboffset < endalt)
168 {
169 int type = cert[suboffset++];
170 int dnslen = get_asn1_length(cert, &suboffset);
171
172 if (type == ASN1_CONTEXT_DNSNAME)
173 {
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;
184 ++totalnames;
185 }
186
187 suboffset += dnslen;
188 }
189 }
190 }
191 }
192 }
193
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))
197 goto end_cert;
198
199 #endif
200 ret = X509_OK;
201 end_cert:
202 if (len)
203 {
204 *len = cert_size;
205 }
206
207 if (ret)
208 {
209 #ifdef CONFIG_SSL_FULL_MODE
210 printf("Error: Invalid X509 ASN.1 file (%s)\n",
211 x509_display_error(ret));
212 #endif
213 x509_free(x509_ctx);
214 *ctx = NULL;
215 }
216 return ret;
217 }
218
219 /**
220 * Free an X.509 object's resources.
221 */
222 void x509_free(X509_CTX *x509_ctx)
223 {
224 X509_CTX *next;
225 int i;
226
227 if (x509_ctx == NULL) /* if already null, then don't bother */
228 return;
229
230 for (i = 0; i < X509_NUM_DN_TYPES; i++)
231 {
232 free(x509_ctx->ca_cert_dn[i]);
233 free(x509_ctx->cert_dn[i]);
234 }
235
236 free(x509_ctx->signature);
237
238 #ifdef CONFIG_SSL_CERT_VERIFICATION
239 if (x509_ctx->digest)
240 {
241 bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
242 }
243
244 if (x509_ctx->subject_alt_dnsnames)
245 {
246 for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i)
247 free(x509_ctx->subject_alt_dnsnames[i]);
248
249 free(x509_ctx->subject_alt_dnsnames);
250 }
251 #endif
252
253 RSA_free(x509_ctx->rsa_ctx);
254 next = x509_ctx->next;
255 free(x509_ctx);
256 x509_free(next); /* clear the chain */
257 }
258
259 #ifdef CONFIG_SSL_CERT_VERIFICATION
260 /**
261 * Take a signature and decrypt it.
262 */
263 static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
264 bigint *modulus, bigint *pub_exp)
265 {
266 int i, size;
267 bigint *decrypted_bi, *dat_bi;
268 bigint *bir = NULL;
269 uint8_t *block = (uint8_t *)alloca(sig_len);
270
271 /* decrypt */
272 dat_bi = bi_import(ctx, sig, sig_len);
273 ctx->mod_offset = BIGINT_M_OFFSET;
274
275 /* convert to a normal block */
276 decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
277
278 bi_export(ctx, decrypted_bi, block, sig_len);
279 ctx->mod_offset = BIGINT_M_OFFSET;
280
281 i = 10; /* start at the first possible non-padded byte */
282 while (block[i++] && i < sig_len);
283 size = sig_len - i;
284
285 /* get only the bit we want */
286 if (size > 0)
287 {
288 int len;
289 const uint8_t *sig_ptr = get_signature(&block[i], &len);
290
291 if (sig_ptr)
292 {
293 bir = bi_import(ctx, sig_ptr, len);
294 }
295 }
296
297 /* save a few bytes of memory */
298 bi_clear_cache(ctx);
299 return bir;
300 }
301
302 /**
303 * Do some basic checks on the certificate chain.
304 *
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.
312 */
313 int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
314 {
315 int ret = X509_OK, i = 0;
316 bigint *cert_sig;
317 X509_CTX *next_cert = NULL;
318 BI_CTX *ctx = NULL;
319 bigint *mod = NULL, *expn = NULL;
320 int match_ca_cert = 0;
321 struct timeval tv;
322 uint8_t is_self_signed = 0;
323
324 if (cert == NULL)
325 {
326 ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
327 goto end_verify;
328 }
329
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)
333 {
334 printf("self signed cert\r\n");
335 is_self_signed = 1;
336 ctx = cert->rsa_ctx->bi_ctx;
337 mod = cert->rsa_ctx->m;
338 expn = cert->rsa_ctx->e;
339 }
340
341 gettimeofday(&tv, NULL);
342
343 /* check the not before date */
344 if (tv.tv_sec < cert->not_before)
345 {
346 ret = X509_VFY_ERROR_NOT_YET_VALID;
347 goto end_verify;
348 }
349
350 /* check the not after date */
351 if (tv.tv_sec > cert->not_after)
352 {
353 ret = X509_VFY_ERROR_EXPIRED;
354 goto end_verify;
355 }
356
357 next_cert = cert->next;
358
359 /* last cert in the chain - look for a trusted cert */
360 if (next_cert == NULL)
361 {
362 if (ca_cert_ctx != NULL)
363 {
364 /* go thu the CA store */
365 while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
366 {
367 if (asn1_compare_dn(cert->ca_cert_dn,
368 ca_cert_ctx->cert[i]->cert_dn) == 0)
369 {
370 /* use this CA certificate for signature verification */
371 match_ca_cert = 1;
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;
375 break;
376 }
377
378 i++;
379 }
380 }
381
382 /* couldn't find a trusted cert (& let self-signed errors
383 be returned) */
384 if (!match_ca_cert && !is_self_signed)
385 {
386 ret = X509_VFY_ERROR_NO_TRUSTED_CERT;
387 goto end_verify;
388 }
389 }
390 else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
391 {
392 /* check the chain */
393 ret = X509_VFY_ERROR_INVALID_CHAIN;
394 goto end_verify;
395 }
396 else /* use the next certificate in the chain for signature verify */
397 {
398 ctx = next_cert->rsa_ctx->bi_ctx;
399 mod = next_cert->rsa_ctx->m;
400 expn = next_cert->rsa_ctx->e;
401 }
402
403 /* cert is self signed */
404 if (!match_ca_cert && is_self_signed)
405 {
406 ret = X509_VFY_ERROR_SELF_SIGNED;
407 goto end_verify;
408 }
409
410 /* check the signature */
411 cert_sig = sig_verify(ctx, cert->signature, cert->sig_len,
412 bi_clone(ctx, mod), bi_clone(ctx, expn));
413
414 if (cert_sig && cert->digest)
415 {
416 if (bi_compare(cert_sig, cert->digest) != 0)
417 ret = X509_VFY_ERROR_BAD_SIGNATURE;
418
419
420 bi_free(ctx, cert_sig);
421 }
422 else
423 {
424 ret = X509_VFY_ERROR_BAD_SIGNATURE;
425 }
426
427 if (ret)
428 goto end_verify;
429
430 /* go down the certificate chain using recursion. */
431 if (next_cert != NULL)
432 {
433 ret = x509_verify(ca_cert_ctx, next_cert);
434 }
435
436 end_verify:
437 return ret;
438 }
439 #endif
440
441 #if defined (CONFIG_SSL_FULL_MODE)
442 /**
443 * Used for diagnostics.
444 */
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)
447 {
448 if (cert == NULL)
449 return;
450
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);
455
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);
459
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);
463
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);
468
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);
472
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);
476
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)
482 {
483 case SIG_TYPE_MD5:
484 printf("MD5\r\n");
485 break;
486 case SIG_TYPE_SHA1:
487 printf("SHA1\r\n");
488 break;
489 case SIG_TYPE_MD2:
490 printf("MD2\r\n");
491 break;
492 default:
493 printf("Unrecognized: %d\r\n", cert->sig_type);
494 break;
495 }
496
497 if (ca_cert_ctx)
498 {
499 printf("Verify:\t\t\t\t%s\r\n",
500 x509_display_error(x509_verify(ca_cert_ctx, cert)));
501 }
502
503 #if 0
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);
507 #endif
508
509 if (ca_cert_ctx)
510 {
511 x509_print(cert->next, ca_cert_ctx);
512 }
513
514 TTY_FLUSH();
515 }
516
517 const char * x509_display_error(int error)
518 {
519 switch (error)
520 {
521 case X509_OK:
522 return "Certificate verify successful";
523
524 case X509_NOT_OK:
525 return "X509 not ok";
526
527 case X509_VFY_ERROR_NO_TRUSTED_CERT:
528 return "No trusted cert is available";
529
530 case X509_VFY_ERROR_BAD_SIGNATURE:
531 return "Bad signature";
532
533 case X509_VFY_ERROR_NOT_YET_VALID:
534 return "Cert is not yet valid";
535
536 case X509_VFY_ERROR_EXPIRED:
537 return "Cert has expired";
538
539 case X509_VFY_ERROR_SELF_SIGNED:
540 return "Cert is self-signed";
541
542 case X509_VFY_ERROR_INVALID_CHAIN:
543 return "Chain is invalid (check order of certs)";
544
545 case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
546 return "Unsupported digest";
547
548 case X509_INVALID_PRIV_KEY:
549 return "Invalid private key";
550
551 default:
552 return "Unknown";
553 }
554 }
555 #endif /* CONFIG_SSL_FULL_MODE */
556
Imprint / Impressum