joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers loader.c Source File

loader.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  * Load certificates/keys into memory. These can be in many different formats.
00033  * PEM support and other formats can be processed here.
00034  *
00035  * The PEM private keys may be optionally encrypted with AES128 or AES256. 
00036  * The encrypted PEM keys were generated with something like:
00037  *
00038  * openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
00039  */
00040 
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <stdio.h>
00044 #include "os_port.h"
00045 #include "ssl.h"
00046 #include "config.h"
00047 
00048 static int do_obj(SSL_CTX *ssl_ctx, int obj_type, 
00049                     SSLObjLoader *ssl_obj, const char *password);
00050 #ifdef CONFIG_SSL_HAS_PEM
00051 static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type, 
00052                         SSLObjLoader *ssl_obj, const char *password);
00053 #endif
00054 
00055 /*
00056  * Load a file into memory that is in binary DER (or ascii PEM) format.
00057  */
00058 EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type, 
00059                             const char *filename, const char *password)
00060 {
00061 #ifndef CONFIG_SSL_SKELETON_MODE
00062     static const char * const begin = "-----BEGIN";
00063     int ret = SSL_OK;
00064     SSLObjLoader *ssl_obj = NULL;
00065 
00066     if (filename == NULL)
00067     {
00068         ret = SSL_ERROR_INVALID_KEY;
00069         goto error;
00070     }
00071 
00072     ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
00073     ssl_obj->len = get_file(filename, &ssl_obj->buf); 
00074     if (ssl_obj->len <= 0)
00075     {
00076         ret = SSL_ERROR_INVALID_KEY;
00077         goto error;
00078     }
00079 
00080     /* is the file a PEM file? */
00081     if (strstr((char *)ssl_obj->buf, begin) != NULL)
00082     {
00083 #ifdef CONFIG_SSL_HAS_PEM
00084         ret = ssl_obj_PEM_load(ssl_ctx, obj_type, ssl_obj, password);
00085 #else
00086         printf(unsupported_str);
00087         ret = SSL_ERROR_NOT_SUPPORTED;
00088 #endif
00089     }
00090     else
00091         ret = do_obj(ssl_ctx, obj_type, ssl_obj, password);
00092 
00093 error:
00094     ssl_obj_free(ssl_obj);
00095     return ret;
00096 #else
00097     printf(unsupported_str);
00098     return SSL_ERROR_NOT_SUPPORTED;
00099 #endif /* CONFIG_SSL_SKELETON_MODE */
00100 }
00101 
00102 /*
00103  * Transfer binary data into the object loader.
00104  */
00105 EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int mem_type, 
00106         const uint8_t *data, int len, const char *password)
00107 {
00108     int ret;
00109     SSLObjLoader ssl_obj;
00110     ssl_obj.buf = data;
00111     ssl_obj.len = len;
00112     ret = do_obj(ssl_ctx, mem_type, &ssl_obj, password);
00113     
00114     return ret;
00115 }
00116 
00117 /*
00118  * Actually work out what we are doing 
00119  */
00120 static int do_obj(SSL_CTX *ssl_ctx, int obj_type, 
00121                     SSLObjLoader *ssl_obj, const char *password)
00122 {
00123     int ret = SSL_OK;
00124 
00125     switch (obj_type)
00126     {
00127         case SSL_OBJ_RSA_KEY:
00128             ret = add_private_key(ssl_ctx, ssl_obj);
00129             break;
00130 
00131         case SSL_OBJ_X509_CERT:
00132             ret = add_cert(ssl_ctx, ssl_obj->buf, ssl_obj->len);
00133             break;
00134 
00135 #ifdef CONFIG_SSL_CERT_VERIFICATION
00136         case SSL_OBJ_X509_CACERT:
00137             add_cert_auth(ssl_ctx, ssl_obj->buf, ssl_obj->len);
00138             break;
00139 #endif
00140 
00141 #ifdef CONFIG_SSL_USE_PKCS12
00142         case SSL_OBJ_PKCS8:
00143             ret = pkcs8_decode(ssl_ctx, ssl_obj, password);
00144             break;
00145 
00146         case SSL_OBJ_PKCS12:
00147             ret = pkcs12_decode(ssl_ctx, ssl_obj, password);
00148             break;
00149 #endif
00150         default:
00151             printf(unsupported_str);
00152             ret = SSL_ERROR_NOT_SUPPORTED;
00153             break;
00154     }
00155 
00156     return ret;
00157 }
00158 
00159 /*
00160  * Clean up our mess.
00161  */
00162 void ssl_obj_free(SSLObjLoader *ssl_obj)
00163 {
00164     if (ssl_obj)
00165     {
00166         free(ssl_obj->buf);
00167         free(ssl_obj);
00168     }
00169 }
00170 
00171 /*
00172  * Support for PEM encoded keys/certificates.
00173  */
00174 #ifdef CONFIG_SSL_HAS_PEM
00175 
00176 #define NUM_PEM_TYPES               4
00177 #define IV_SIZE                     16
00178 #define IS_RSA_PRIVATE_KEY          0
00179 #define IS_ENCRYPTED_PRIVATE_KEY    1
00180 #define IS_PRIVATE_KEY              2
00181 #define IS_CERTIFICATE              3
00182 
00183 static const char * const begins[NUM_PEM_TYPES] =
00184 {
00185     "-----BEGIN RSA PRIVATE KEY-----",
00186     "-----BEGIN ENCRYPTED PRIVATE KEY-----",
00187     "-----BEGIN PRIVATE KEY-----",
00188     "-----BEGIN CERTIFICATE-----",
00189 };
00190 
00191 static const char * const ends[NUM_PEM_TYPES] =
00192 {
00193     "-----END RSA PRIVATE KEY-----",
00194     "-----END ENCRYPTED PRIVATE KEY-----",
00195     "-----END PRIVATE KEY-----",
00196     "-----END CERTIFICATE-----",
00197 };
00198 
00199 static const char * const aes_str[2] =
00200 {
00201     "DEK-Info: AES-128-CBC,",
00202     "DEK-Info: AES-256-CBC," 
00203 };
00204 
00205 /**
00206  * Take a base64 blob of data and decrypt it (using AES) into its 
00207  * proper ASN.1 form.
00208  */
00209 static int pem_decrypt(const char *where, const char *end,
00210                         const char *password, SSLObjLoader *ssl_obj)
00211 {
00212     int ret = -1;
00213     int is_aes_256 = 0;
00214     char *start = NULL;
00215     uint8_t iv[IV_SIZE];
00216     int i, pem_size;
00217     MD5_CTX md5_ctx;
00218     AES_CTX aes_ctx;
00219     uint8_t key[32];        /* AES256 size */
00220 
00221     if (password == NULL || strlen(password) == 0)
00222     {
00223 #ifdef CONFIG_SSL_FULL_MODE
00224         printf("Error: Need a password for this PEM file\n"); TTY_FLUSH();
00225 #endif
00226         goto error;
00227     }
00228 
00229     if ((start = strstr((const char *)where, aes_str[0])))         /* AES128? */
00230     {
00231         start += strlen(aes_str[0]);
00232     }
00233     else if ((start = strstr((const char *)where, aes_str[1])))    /* AES256? */
00234     {
00235         is_aes_256 = 1;
00236         start += strlen(aes_str[1]);
00237     }
00238     else 
00239     {
00240 #ifdef CONFIG_SSL_FULL_MODE
00241         printf("Error: Unsupported password cipher\n"); TTY_FLUSH();
00242 #endif
00243         goto error;
00244     }
00245 
00246     /* convert from hex to binary - assumes uppercase hex */
00247     for (i = 0; i < IV_SIZE; i++)
00248     {
00249         char c = *start++ - '0';
00250         iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4;
00251         c = *start++ - '0';
00252         iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c);
00253     }
00254 
00255     while (*start == '\r' || *start == '\n')
00256         start++;
00257 
00258     /* turn base64 into binary */
00259     pem_size = (int)(end-start);
00260     if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0)
00261         goto error;
00262 
00263     /* work out the key */
00264     MD5_Init(&md5_ctx);
00265     MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
00266     MD5_Update(&md5_ctx, iv, SALT_SIZE);
00267     MD5_Final(key, &md5_ctx);
00268 
00269     if (is_aes_256)
00270     {
00271         MD5_Init(&md5_ctx);
00272         MD5_Update(&md5_ctx, key, MD5_SIZE);
00273         MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
00274         MD5_Update(&md5_ctx, iv, SALT_SIZE);
00275         MD5_Final(&key[MD5_SIZE], &md5_ctx);
00276     }
00277 
00278     /* decrypt using the key/iv */
00279     AES_set_key(&aes_ctx, key, iv, is_aes_256 ? AES_MODE_256 : AES_MODE_128);
00280     AES_convert_key(&aes_ctx);
00281     AES_cbc_decrypt(&aes_ctx, ssl_obj->buf, ssl_obj->buf, ssl_obj->len);
00282     ret = 0;
00283 
00284 error:
00285     return ret; 
00286 }
00287 
00288 /**
00289  * Take a base64 blob of data and turn it into its proper ASN.1 form.
00290  */
00291 static int new_pem_obj(SSL_CTX *ssl_ctx, int is_cacert, char *where, 
00292                     int remain, const char *password)
00293 {
00294     int ret = SSL_ERROR_BAD_CERTIFICATE;
00295     SSLObjLoader *ssl_obj = NULL;
00296 
00297     while (remain > 0)
00298     {
00299         int i, pem_size, obj_type;
00300         char *start = NULL, *end = NULL;
00301 
00302         for (i = 0; i < NUM_PEM_TYPES; i++)
00303         {
00304             if ((start = strstr(where, begins[i])) &&
00305                     (end = strstr(where, ends[i])))
00306             {
00307                 remain -= (int)(end-where);
00308                 start += strlen(begins[i]);
00309                 pem_size = (int)(end-start);
00310 
00311                 ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
00312 
00313                 /* 4/3 bigger than what we need but so what */
00314                 ssl_obj->buf = (uint8_t *)calloc(1, pem_size);
00315                 ssl_obj->len = pem_size;
00316 
00317                 if (i == IS_RSA_PRIVATE_KEY && 
00318                             strstr(start, "Proc-Type:") && 
00319                             strstr(start, "4,ENCRYPTED"))
00320                 {
00321                     /* check for encrypted PEM file */
00322                     if (pem_decrypt(start, end, password, ssl_obj) < 0)
00323                     {
00324                         ret = SSL_ERROR_BAD_CERTIFICATE;
00325                         goto error;
00326                     }
00327                 }
00328                 else 
00329                 {
00330                     ssl_obj->len = pem_size;
00331                     if (base64_decode(start, pem_size, 
00332                                 ssl_obj->buf, &ssl_obj->len) != 0)
00333                     {
00334                         ret = SSL_ERROR_BAD_CERTIFICATE;
00335                         goto error;
00336                     }
00337                 }
00338 
00339                 switch (i)
00340                 {
00341                     case IS_RSA_PRIVATE_KEY:
00342                         obj_type = SSL_OBJ_RSA_KEY;
00343                         break;
00344 
00345                     case IS_ENCRYPTED_PRIVATE_KEY:
00346                     case IS_PRIVATE_KEY:
00347                         obj_type = SSL_OBJ_PKCS8;
00348                         break;
00349 
00350                     case IS_CERTIFICATE:
00351                         obj_type = is_cacert ?
00352                                         SSL_OBJ_X509_CACERT : SSL_OBJ_X509_CERT;
00353                         break;
00354 
00355                     default:
00356                         ret = SSL_ERROR_BAD_CERTIFICATE;
00357                         goto error;
00358                 }
00359 
00360                 /* In a format we can now understand - so process it */
00361                 if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password)))
00362                     goto error;
00363 
00364                 end += strlen(ends[i]);
00365                 remain -= strlen(ends[i]);
00366                 while (remain > 0 && (*end == '\r' || *end == '\n'))
00367                 {
00368                     end++;
00369                     remain--;
00370                 }
00371 
00372                 where = end;
00373                 break;
00374             }
00375         }
00376 
00377         ssl_obj_free(ssl_obj);
00378         ssl_obj = NULL;
00379         if (start == NULL)
00380            break;
00381     }
00382 error:
00383     ssl_obj_free(ssl_obj);
00384     return ret;
00385 }
00386 
00387 /*
00388  * Load a file into memory that is in ASCII PEM format.
00389  */
00390 static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type, 
00391                         SSLObjLoader *ssl_obj, const char *password)
00392 {
00393     char *start;
00394 
00395     /* add a null terminator */
00396     ssl_obj->len++;
00397     ssl_obj->buf = (uint8_t *)realloc(ssl_obj->buf, ssl_obj->len);
00398     ssl_obj->buf[ssl_obj->len-1] = 0;
00399     start = (char *)ssl_obj->buf;
00400     return new_pem_obj(ssl_ctx, obj_type == SSL_OBJ_X509_CACERT,
00401                                 start, ssl_obj->len, password);
00402 }
00403 #endif /* CONFIG_SSL_HAS_PEM */
00404 
00405 /**
00406  * Load the key/certificates in memory depending on compile-time and user
00407  * options. 
00408  */
00409 int load_key_certs(SSL_CTX *ssl_ctx)
00410 {
00411     int ret = SSL_OK;
00412     uint32_t options = ssl_ctx->options;
00413 #ifdef CONFIG_SSL_GENERATE_X509_CERT 
00414     uint8_t *cert_data = NULL;
00415     int cert_size;
00416     static const char *dn[] = 
00417     {
00418         CONFIG_SSL_X509_COMMON_NAME,
00419         CONFIG_SSL_X509_ORGANIZATION_NAME,
00420         CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME
00421     };
00422 #endif
00423 
00424     /* do the private key first */
00425     if (strlen(CONFIG_SSL_PRIVATE_KEY_LOCATION) > 0)
00426     {
00427         if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY, 
00428                                 CONFIG_SSL_PRIVATE_KEY_LOCATION,
00429                                 CONFIG_SSL_PRIVATE_KEY_PASSWORD)) < 0)
00430             goto error;
00431     }
00432     else if (!(options & SSL_NO_DEFAULT_KEY))
00433     {
00434 #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
00435 //        static const    /* saves a few more bytes */
00436 //#include "private_key.h"
00437 //       ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key,
00438   //              default_private_key_len, NULL); 
00439 #endif
00440     }
00441 
00442     /* now load the certificate */
00443 #ifdef CONFIG_SSL_GENERATE_X509_CERT 
00444     if ((cert_size = ssl_x509_create(ssl_ctx, 0, dn, &cert_data)) < 0)
00445     {
00446         ret = cert_size;
00447         goto error;
00448     }
00449 
00450     ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, cert_data, cert_size, NULL);
00451     free(cert_data);
00452 #else
00453     if (strlen(CONFIG_SSL_X509_CERT_LOCATION))
00454     {
00455         if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, 
00456                                 CONFIG_SSL_X509_CERT_LOCATION, NULL)) < 0)
00457             goto error;
00458     }
00459     else if (!(options & SSL_NO_DEFAULT_KEY))
00460     {
00461 #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
00462         static const    /* saves a few bytes and RAM */
00463 #include "cert.h"
00464         ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, 
00465                     default_certificate, default_certificate_len, NULL);
00466 #endif
00467     }
00468 #endif
00469 
00470 error:
00471 #ifdef CONFIG_SSL_FULL_MODE
00472     if (ret)
00473     {
00474         printf("Error: Certificate or key not loaded\n"); TTY_FLUSH();
00475     }
00476 #endif
00477 
00478     return ret;
00479 
00480 }