]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/net/https/axTLS/ssl/x509.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.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