dhgdh

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by joey shelton

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers x509.c Source File

x509.c

00001 /*
00002  * Copyright (c) 2007, Cameron Rich
00003  * 
00004  * All rights reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without 
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * * Redistributions of source code must retain the above copyright notice, 
00010  *   this list of conditions and the following disclaimer.
00011  * * Redistributions in binary form must reproduce the above copyright notice, 
00012  *   this list of conditions and the following disclaimer in the documentation 
00013  *   and/or other materials provided with the distribution.
00014  * * Neither the name of the axTLS project nor the names of its contributors 
00015  *   may be used to endorse or promote products derived from this software 
00016  *   without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00021  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00022  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00025  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00026  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 /**
00032  * @file x509.c
00033  * 
00034  * Certificate processing.
00035  */
00036 
00037 #include <time.h>
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include "os_port.h"
00042 #include "crypto_misc.h "
00043 #include "sockets.h"
00044 #include "config.h"
00045 #ifdef CONFIG_SSL_CERT_VERIFICATION
00046 /**
00047  * Retrieve the signature from a certificate.
00048  */
00049 static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
00050 {
00051     int offset = 0;
00052     const uint8_t *ptr = NULL;
00053 
00054     if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 || 
00055             asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
00056         goto end_get_sig;
00057 
00058     if (asn1_sig[offset++] != ASN1_OCTET_STRING)
00059         goto end_get_sig;
00060     *len = get_asn1_length(asn1_sig, &offset);
00061     ptr = &asn1_sig[offset];          /* all ok */
00062 
00063 end_get_sig:
00064     return ptr;
00065 }
00066 
00067 #endif
00068 
00069 /**
00070  * Construct a new x509 object.
00071  * @return 0 if ok. < 0 if there was a problem.
00072  */
00073 int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
00074 {
00075 
00076     int begin_tbs, end_tbs;
00077     int ret = X509_NOT_OK, offset = 0, cert_size = 0;
00078     X509_CTX *x509_ctx;
00079     BI_CTX *bi_ctx;
00080     *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
00081     x509_ctx = *ctx;
00082     /* get the certificate size */
00083     asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); 
00084 
00085     if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
00086         goto end_cert;
00087 
00088     begin_tbs = offset;         /* start of the tbs */
00089     end_tbs = begin_tbs;        /* work out the end of the tbs */
00090     asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);
00091     if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
00092         goto end_cert;
00093     if (cert[offset] == ASN1_EXPLICIT_TAG)   /* optional version */
00094     {
00095         if (asn1_version(cert, &offset, x509_ctx))
00096             goto end_cert;
00097     }
00098     if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 
00099             asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
00100     {
00101         goto end_cert;
00102     }
00103     /* make sure the signature is ok */
00104     if (asn1_signature_type(cert, &offset, x509_ctx))
00105     {
00106         ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
00107         goto end_cert;
00108     }
00109     if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || 
00110             asn1_validity(cert, &offset, x509_ctx) ||
00111             asn1_name(cert, &offset, x509_ctx->cert_dn) ||
00112             asn1_public_key(cert, &offset, x509_ctx))
00113     {
00114         goto end_cert;
00115     }
00116     bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
00117 #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
00118     
00119     /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
00120     if (x509_ctx->sig_type == SIG_TYPE_MD5)
00121     {
00122         MD5_CTX md5_ctx;
00123         uint8_t md5_dgst[MD5_SIZE];
00124         MD5_Init(&md5_ctx);
00125         MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
00126         MD5_Final(md5_dgst, &md5_ctx);
00127         x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
00128     }
00129     else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
00130     {
00131         SHA1_CTX sha_ctx;
00132         uint8_t sha_dgst[SHA1_SIZE];
00133         SHA1_Init(&sha_ctx);
00134         SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
00135         SHA1_Final(sha_dgst, &sha_ctx);
00136         x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
00137     }
00138     else if (x509_ctx->sig_type == SIG_TYPE_MD2)
00139     {
00140         MD2_CTX md2_ctx;
00141         uint8_t md2_dgst[MD2_SIZE];
00142         MD2_Init(&md2_ctx);
00143         MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
00144         MD2_Final(md2_dgst, &md2_ctx);
00145         x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
00146     }
00147 
00148     if (cert[offset] == ASN1_V3_DATA)
00149     {
00150         int suboffset;
00151 
00152         ++offset;
00153         get_asn1_length(cert, &offset);
00154 
00155         if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0)
00156         {
00157             if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0)
00158             {
00159                 int altlen;
00160 
00161                 if ((altlen = asn1_next_obj(cert, 
00162                                             &suboffset, ASN1_SEQUENCE)) > 0)
00163                 {
00164                     int endalt = suboffset + altlen;
00165                     int totalnames = 0;
00166 
00167                     while (suboffset < endalt)
00168                     {
00169                         int type = cert[suboffset++];
00170                         int dnslen = get_asn1_length(cert, &suboffset);
00171 
00172                         if (type == ASN1_CONTEXT_DNSNAME)
00173                         {
00174                             x509_ctx->subject_alt_dnsnames = (char**)
00175                                     realloc(x509_ctx->subject_alt_dnsnames, 
00176                                        (totalnames + 2) * sizeof(char*));
00177                             x509_ctx->subject_alt_dnsnames[totalnames] = 
00178                                     (char*)malloc(dnslen + 1);
00179                             x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL;
00180                             memcpy(x509_ctx->subject_alt_dnsnames[totalnames], 
00181                                     cert + suboffset, dnslen);
00182                             x509_ctx->subject_alt_dnsnames[
00183                                     totalnames][dnslen] = 0;
00184                             ++totalnames;
00185                         }
00186 
00187                         suboffset += dnslen;
00188                     }
00189                 }
00190             }
00191         }
00192     }
00193 
00194     offset = end_tbs;   /* skip the rest of v3 data */
00195     if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || 
00196             asn1_signature(cert, &offset, x509_ctx))
00197         goto end_cert;
00198         
00199 #endif
00200     ret = X509_OK;
00201 end_cert:
00202     if (len)
00203     {
00204         *len = cert_size;
00205     }
00206 
00207     if (ret)
00208     {
00209 #ifdef CONFIG_SSL_FULL_MODE
00210         printf("Error: Invalid X509 ASN.1 file (%s)\n",
00211                         x509_display_error(ret));
00212 #endif
00213         x509_free(x509_ctx);
00214         *ctx = NULL;
00215     }
00216     return ret;
00217 }
00218 
00219 /**
00220  * Free an X.509 object's resources.
00221  */
00222 void x509_free(X509_CTX *x509_ctx)
00223 {
00224     X509_CTX *next;
00225     int i;
00226 
00227     if (x509_ctx == NULL)       /* if already null, then don't bother */
00228         return;
00229 
00230     for (i = 0; i < X509_NUM_DN_TYPES; i++)
00231     {
00232         free(x509_ctx->ca_cert_dn[i]);
00233         free(x509_ctx->cert_dn[i]);
00234     }
00235 
00236     free(x509_ctx->signature);
00237 
00238 #ifdef CONFIG_SSL_CERT_VERIFICATION 
00239     if (x509_ctx->digest)
00240     {
00241         bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest);
00242     }
00243 
00244     if (x509_ctx->subject_alt_dnsnames)
00245     {
00246         for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i)
00247             free(x509_ctx->subject_alt_dnsnames[i]);
00248 
00249         free(x509_ctx->subject_alt_dnsnames);
00250     }
00251 #endif
00252 
00253     RSA_free(x509_ctx->rsa_ctx);
00254     next = x509_ctx->next;
00255     free(x509_ctx);
00256     x509_free(next);        /* clear the chain */
00257 }
00258 
00259 #ifdef CONFIG_SSL_CERT_VERIFICATION
00260 /**
00261  * Take a signature and decrypt it.
00262  */
00263 static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
00264         bigint *modulus, bigint *pub_exp)
00265 {
00266     int i, size;
00267     bigint *decrypted_bi, *dat_bi;
00268     bigint *bir = NULL;
00269     uint8_t *block = (uint8_t *)alloca(sig_len);
00270 
00271     /* decrypt */
00272     dat_bi = bi_import(ctx, sig, sig_len);
00273     ctx->mod_offset = BIGINT_M_OFFSET;
00274 
00275     /* convert to a normal block */
00276     decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);
00277 
00278     bi_export(ctx, decrypted_bi, block, sig_len);
00279     ctx->mod_offset = BIGINT_M_OFFSET;
00280 
00281     i = 10; /* start at the first possible non-padded byte */
00282     while (block[i++] && i < sig_len);
00283     size = sig_len - i;
00284 
00285     /* get only the bit we want */
00286     if (size > 0)
00287     {
00288         int len;
00289         const uint8_t *sig_ptr = get_signature(&block[i], &len);
00290 
00291         if (sig_ptr)
00292         {
00293             bir = bi_import(ctx, sig_ptr, len);
00294         }
00295     }
00296 
00297     /* save a few bytes of memory */
00298     bi_clear_cache(ctx);
00299     return bir;
00300 }
00301 
00302 /**
00303  * Do some basic checks on the certificate chain.
00304  *
00305  * Certificate verification consists of a number of checks:
00306  * - The date of the certificate is after the start date.
00307  * - The date of the certificate is before the finish date.
00308  * - A root certificate exists in the certificate store.
00309  * - That the certificate(s) are not self-signed.
00310  * - The certificate chain is valid.
00311  * - The signature of the certificate is valid.
00312  */
00313 int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) 
00314 {
00315     int ret = X509_OK, i = 0;
00316     bigint *cert_sig;
00317     X509_CTX *next_cert = NULL;
00318     BI_CTX *ctx = NULL;
00319     bigint *mod = NULL, *expn = NULL;
00320     int match_ca_cert = 0;
00321     struct timeval tv;
00322     uint8_t is_self_signed = 0;
00323 
00324     if (cert == NULL)
00325     {
00326         ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
00327         goto end_verify;
00328     }
00329 
00330     /* a self-signed certificate that is not in the CA store - use this 
00331        to check the signature */
00332     if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
00333     {
00334         printf("self signed cert\r\n");
00335         is_self_signed = 1;
00336         ctx = cert->rsa_ctx->bi_ctx;
00337         mod = cert->rsa_ctx->m;
00338         expn = cert->rsa_ctx->e;
00339     }
00340 
00341     gettimeofday(&tv, NULL);
00342     
00343     /* check the not before date */
00344     if (tv.tv_sec < cert->not_before)
00345     {
00346         ret = X509_VFY_ERROR_NOT_YET_VALID;
00347         goto end_verify;
00348     }
00349 
00350     /* check the not after date */
00351     if (tv.tv_sec > cert->not_after)
00352     {
00353         ret = X509_VFY_ERROR_EXPIRED;
00354         goto end_verify;
00355     }
00356 
00357     next_cert = cert->next;
00358 
00359     /* last cert in the chain - look for a trusted cert */
00360     if (next_cert == NULL)
00361     {
00362        if (ca_cert_ctx != NULL) 
00363        {
00364             /* go thu the CA store */
00365             while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
00366             {
00367                 if (asn1_compare_dn(cert->ca_cert_dn,
00368                                             ca_cert_ctx->cert[i]->cert_dn) == 0)
00369                 {
00370                     /* use this CA certificate for signature verification */
00371                     match_ca_cert = 1;
00372                     ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx;
00373                     mod = ca_cert_ctx->cert[i]->rsa_ctx->m;
00374                     expn = ca_cert_ctx->cert[i]->rsa_ctx->e;
00375                     break;
00376                 }
00377 
00378                 i++;
00379             }
00380         }
00381 
00382         /* couldn't find a trusted cert (& let self-signed errors 
00383            be returned) */
00384         if (!match_ca_cert && !is_self_signed)
00385         {
00386             ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
00387             goto end_verify;
00388         }
00389     }
00390     else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
00391     {
00392         /* check the chain */
00393         ret = X509_VFY_ERROR_INVALID_CHAIN;
00394         goto end_verify;
00395     }
00396     else /* use the next certificate in the chain for signature verify */
00397     {
00398         ctx = next_cert->rsa_ctx->bi_ctx;
00399         mod = next_cert->rsa_ctx->m;
00400         expn = next_cert->rsa_ctx->e;
00401     }
00402 
00403     /* cert is self signed */
00404     if (!match_ca_cert && is_self_signed)
00405     {
00406         ret = X509_VFY_ERROR_SELF_SIGNED;
00407         goto end_verify;
00408     }
00409 
00410     /* check the signature */
00411     cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, 
00412                         bi_clone(ctx, mod), bi_clone(ctx, expn));
00413 
00414     if (cert_sig && cert->digest)
00415     {
00416         if (bi_compare(cert_sig, cert->digest) != 0)
00417             ret = X509_VFY_ERROR_BAD_SIGNATURE;
00418 
00419 
00420         bi_free(ctx, cert_sig);
00421     }
00422     else
00423     {
00424         ret = X509_VFY_ERROR_BAD_SIGNATURE;
00425     }
00426 
00427     if (ret)
00428         goto end_verify;
00429 
00430     /* go down the certificate chain using recursion. */
00431     if (next_cert != NULL)
00432     {
00433         ret = x509_verify(ca_cert_ctx, next_cert);
00434     }
00435 
00436 end_verify:
00437     return ret;
00438 }
00439 #endif
00440 
00441 #if defined (CONFIG_SSL_FULL_MODE)
00442 /**
00443  * Used for diagnostics.
00444  */
00445 static const char *not_part_of_cert = "<Not Part Of Certificate>";
00446 void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx) 
00447 {
00448     if (cert == NULL)
00449         return;
00450 
00451     printf("=== CERTIFICATE ISSUED TO ===\n");
00452     printf("Common Name (CN):\t\t");
00453     printf("%s\r\n", cert->cert_dn[X509_COMMON_NAME] ?
00454                     cert->cert_dn[X509_COMMON_NAME] : not_part_of_cert);
00455 
00456     printf("Organization (O):\t\t");
00457     printf("%s\r\n", cert->cert_dn[X509_ORGANIZATION] ?
00458         cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
00459 
00460     printf("Organizational Unit (OU):\t");
00461     printf("%s\r\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ?
00462         cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
00463 
00464     printf("=== CERTIFICATE ISSUED BY ===\r\n");
00465     printf("Common Name (CN):\t\t");
00466     printf("%s\r\n", cert->ca_cert_dn[X509_COMMON_NAME] ?
00467                     cert->ca_cert_dn[X509_COMMON_NAME] : not_part_of_cert);
00468 
00469     printf("Organization (O):\t\t");
00470     printf("%s\r\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
00471         cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
00472 
00473     printf("Organizational Unit (OU):\t");
00474     printf("%s\r\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ?
00475         cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
00476 
00477     printf("Not Before:\t\t\t%s\r\n", ctime(&cert->not_before));
00478     printf("Not After:\t\t\t%s\r\n", ctime(&cert->not_after));
00479     printf("RSA bitsize:\t\t\t%d\r\n", cert->rsa_ctx->num_octets*8);
00480     printf("Sig Type:\t\t\t");
00481     switch (cert->sig_type)
00482     {
00483         case SIG_TYPE_MD5:
00484             printf("MD5\r\n");
00485             break;
00486         case SIG_TYPE_SHA1:
00487             printf("SHA1\r\n");
00488             break;
00489         case SIG_TYPE_MD2:
00490             printf("MD2\r\n");
00491             break;
00492         default:
00493             printf("Unrecognized: %d\r\n", cert->sig_type);
00494             break;
00495     }
00496 
00497     if (ca_cert_ctx)
00498     {
00499         printf("Verify:\t\t\t\t%s\r\n",
00500                 x509_display_error(x509_verify(ca_cert_ctx, cert)));
00501     }
00502 
00503 #if 0
00504     print_blob("Signature", cert->signature, cert->sig_len);
00505     bi_print("Modulus", cert->rsa_ctx->m);
00506     bi_print("Pub Exp", cert->rsa_ctx->e);
00507 #endif
00508 
00509     if (ca_cert_ctx)
00510     {
00511         x509_print(cert->next, ca_cert_ctx);
00512     }
00513 
00514     TTY_FLUSH();
00515 }
00516 
00517 const char * x509_display_error(int error)
00518 {
00519     switch (error)
00520     {
00521         case X509_OK:
00522             return "Certificate verify successful";
00523 
00524         case X509_NOT_OK:
00525             return "X509 not ok";
00526 
00527         case X509_VFY_ERROR_NO_TRUSTED_CERT:
00528             return "No trusted cert is available";
00529 
00530         case X509_VFY_ERROR_BAD_SIGNATURE:
00531             return "Bad signature";
00532 
00533         case X509_VFY_ERROR_NOT_YET_VALID:
00534             return "Cert is not yet valid";
00535 
00536         case X509_VFY_ERROR_EXPIRED:
00537             return "Cert has expired";
00538 
00539         case X509_VFY_ERROR_SELF_SIGNED:
00540             return "Cert is self-signed";
00541 
00542         case X509_VFY_ERROR_INVALID_CHAIN:
00543             return "Chain is invalid (check order of certs)";
00544 
00545         case X509_VFY_ERROR_UNSUPPORTED_DIGEST:
00546             return "Unsupported digest";
00547 
00548         case X509_INVALID_PRIV_KEY:
00549             return "Invalid private key";
00550 
00551         default:
00552             return "Unknown";
00553     }
00554 }
00555 #endif      /* CONFIG_SSL_FULL_MODE */
00556