Annotation of embedaddon/axTLS/ssl/loader.c, revision 1.1.1.1

1.1       misho       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:  * Load certificates/keys into memory. These can be in many different formats.
                     33:  * PEM support and other formats can be processed here.
                     34:  *
                     35:  * The PEM private keys may be optionally encrypted with AES128 or AES256. 
                     36:  * The encrypted PEM keys were generated with something like:
                     37:  *
                     38:  * openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
                     39:  */
                     40: 
                     41: #include <stdlib.h>
                     42: #include <string.h>
                     43: #include <stdio.h>
                     44: #include "os_port.h"
                     45: #include "ssl.h"
                     46: 
                     47: static int do_obj(SSL_CTX *ssl_ctx, int obj_type, 
                     48:                     SSLObjLoader *ssl_obj, const char *password);
                     49: #ifdef CONFIG_SSL_HAS_PEM
                     50: static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type, 
                     51:                         SSLObjLoader *ssl_obj, const char *password);
                     52: #endif
                     53: 
                     54: /*
                     55:  * Load a file into memory that is in binary DER (or ascii PEM) format.
                     56:  */
                     57: EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type, 
                     58:                             const char *filename, const char *password)
                     59: {
                     60: #ifndef CONFIG_SSL_SKELETON_MODE
                     61:     static const char * const begin = "-----BEGIN";
                     62:     int ret = SSL_OK;
                     63:     SSLObjLoader *ssl_obj = NULL;
                     64: 
                     65:     if (filename == NULL)
                     66:     {
                     67:         ret = SSL_ERROR_INVALID_KEY;
                     68:         goto error;
                     69:     }
                     70: 
                     71:     ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
                     72:     ssl_obj->len = get_file(filename, &ssl_obj->buf); 
                     73:     if (ssl_obj->len <= 0)
                     74:     {
                     75:         ret = SSL_ERROR_INVALID_KEY;
                     76:         goto error;
                     77:     }
                     78: 
                     79:     /* is the file a PEM file? */
                     80:     if (strstr((char *)ssl_obj->buf, begin) != NULL)
                     81:     {
                     82: #ifdef CONFIG_SSL_HAS_PEM
                     83:         ret = ssl_obj_PEM_load(ssl_ctx, obj_type, ssl_obj, password);
                     84: #else
                     85:         printf(unsupported_str);
                     86:         ret = SSL_ERROR_NOT_SUPPORTED;
                     87: #endif
                     88:     }
                     89:     else
                     90:         ret = do_obj(ssl_ctx, obj_type, ssl_obj, password);
                     91: 
                     92: error:
                     93:     ssl_obj_free(ssl_obj);
                     94:     return ret;
                     95: #else
                     96:     printf(unsupported_str);
                     97:     return SSL_ERROR_NOT_SUPPORTED;
                     98: #endif /* CONFIG_SSL_SKELETON_MODE */
                     99: }
                    100: 
                    101: /*
                    102:  * Transfer binary data into the object loader.
                    103:  */
                    104: EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int mem_type, 
                    105:         const uint8_t *data, int len, const char *password)
                    106: {
                    107:     int ret;
                    108:     SSLObjLoader *ssl_obj;
                    109: 
                    110:     ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
                    111:     ssl_obj->buf = (uint8_t *)malloc(len);
                    112:     memcpy(ssl_obj->buf, data, len);
                    113:     ssl_obj->len = len;
                    114:     ret = do_obj(ssl_ctx, mem_type, ssl_obj, password);
                    115:     ssl_obj_free(ssl_obj);
                    116:     return ret;
                    117: }
                    118: 
                    119: /*
                    120:  * Actually work out what we are doing 
                    121:  */
                    122: static int do_obj(SSL_CTX *ssl_ctx, int obj_type, 
                    123:                     SSLObjLoader *ssl_obj, const char *password)
                    124: {
                    125:     int ret = SSL_OK;
                    126: 
                    127:     switch (obj_type)
                    128:     {
                    129:         case SSL_OBJ_RSA_KEY:
                    130:             ret = add_private_key(ssl_ctx, ssl_obj);
                    131:             break;
                    132: 
                    133:         case SSL_OBJ_X509_CERT:
                    134:             ret = add_cert(ssl_ctx, ssl_obj->buf, ssl_obj->len);
                    135:             break;
                    136: 
                    137: #ifdef CONFIG_SSL_CERT_VERIFICATION
                    138:         case SSL_OBJ_X509_CACERT:
                    139:             add_cert_auth(ssl_ctx, ssl_obj->buf, ssl_obj->len);
                    140:             break;
                    141: #endif
                    142: 
                    143: #ifdef CONFIG_SSL_USE_PKCS12
                    144:         case SSL_OBJ_PKCS8:
                    145:             ret = pkcs8_decode(ssl_ctx, ssl_obj, password);
                    146:             break;
                    147: 
                    148:         case SSL_OBJ_PKCS12:
                    149:             ret = pkcs12_decode(ssl_ctx, ssl_obj, password);
                    150:             break;
                    151: #endif
                    152:         default:
                    153:             printf(unsupported_str);
                    154:             ret = SSL_ERROR_NOT_SUPPORTED;
                    155:             break;
                    156:     }
                    157: 
                    158:     return ret;
                    159: }
                    160: 
                    161: /*
                    162:  * Clean up our mess.
                    163:  */
                    164: void ssl_obj_free(SSLObjLoader *ssl_obj)
                    165: {
                    166:     if (ssl_obj)
                    167:     {
                    168:         free(ssl_obj->buf);
                    169:         free(ssl_obj);
                    170:     }
                    171: }
                    172: 
                    173: /*
                    174:  * Support for PEM encoded keys/certificates.
                    175:  */
                    176: #ifdef CONFIG_SSL_HAS_PEM
                    177: 
                    178: #define NUM_PEM_TYPES               4
                    179: #define IV_SIZE                     16
                    180: #define IS_RSA_PRIVATE_KEY          0
                    181: #define IS_ENCRYPTED_PRIVATE_KEY    1
                    182: #define IS_PRIVATE_KEY              2
                    183: #define IS_CERTIFICATE              3
                    184: 
                    185: static const char * const begins[NUM_PEM_TYPES] =
                    186: {
                    187:     "-----BEGIN RSA PRIVATE KEY-----",
                    188:     "-----BEGIN ENCRYPTED PRIVATE KEY-----",
                    189:     "-----BEGIN PRIVATE KEY-----",
                    190:     "-----BEGIN CERTIFICATE-----",
                    191: };
                    192: 
                    193: static const char * const ends[NUM_PEM_TYPES] =
                    194: {
                    195:     "-----END RSA PRIVATE KEY-----",
                    196:     "-----END ENCRYPTED PRIVATE KEY-----",
                    197:     "-----END PRIVATE KEY-----",
                    198:     "-----END CERTIFICATE-----",
                    199: };
                    200: 
                    201: static const char * const aes_str[2] =
                    202: {
                    203:     "DEK-Info: AES-128-CBC,",
                    204:     "DEK-Info: AES-256-CBC," 
                    205: };
                    206: 
                    207: /**
                    208:  * Take a base64 blob of data and decrypt it (using AES) into its 
                    209:  * proper ASN.1 form.
                    210:  */
                    211: static int pem_decrypt(const char *where, const char *end,
                    212:                         const char *password, SSLObjLoader *ssl_obj)
                    213: {
                    214:     int ret = -1;
                    215:     int is_aes_256 = 0;
                    216:     char *start = NULL;
                    217:     uint8_t iv[IV_SIZE];
                    218:     int i, pem_size;
                    219:     MD5_CTX md5_ctx;
                    220:     AES_CTX aes_ctx;
                    221:     uint8_t key[32];        /* AES256 size */
                    222: 
                    223:     if (password == NULL || strlen(password) == 0)
                    224:     {
                    225: #ifdef CONFIG_SSL_FULL_MODE
                    226:         printf("Error: Need a password for this PEM file\n"); TTY_FLUSH();
                    227: #endif
                    228:         goto error;
                    229:     }
                    230: 
                    231:     if ((start = strstr((const char *)where, aes_str[0])))         /* AES128? */
                    232:     {
                    233:         start += strlen(aes_str[0]);
                    234:     }
                    235:     else if ((start = strstr((const char *)where, aes_str[1])))    /* AES256? */
                    236:     {
                    237:         is_aes_256 = 1;
                    238:         start += strlen(aes_str[1]);
                    239:     }
                    240:     else 
                    241:     {
                    242: #ifdef CONFIG_SSL_FULL_MODE
                    243:         printf("Error: Unsupported password cipher\n"); TTY_FLUSH();
                    244: #endif
                    245:         goto error;
                    246:     }
                    247: 
                    248:     /* convert from hex to binary - assumes uppercase hex */
                    249:     for (i = 0; i < IV_SIZE; i++)
                    250:     {
                    251:         char c = *start++ - '0';
                    252:         iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4;
                    253:         c = *start++ - '0';
                    254:         iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c);
                    255:     }
                    256: 
                    257:     while (*start == '\r' || *start == '\n')
                    258:         start++;
                    259: 
                    260:     /* turn base64 into binary */
                    261:     pem_size = (int)(end-start);
                    262:     if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0)
                    263:         goto error;
                    264: 
                    265:     /* work out the key */
                    266:     MD5_Init(&md5_ctx);
                    267:     MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
                    268:     MD5_Update(&md5_ctx, iv, SALT_SIZE);
                    269:     MD5_Final(key, &md5_ctx);
                    270: 
                    271:     if (is_aes_256)
                    272:     {
                    273:         MD5_Init(&md5_ctx);
                    274:         MD5_Update(&md5_ctx, key, MD5_SIZE);
                    275:         MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
                    276:         MD5_Update(&md5_ctx, iv, SALT_SIZE);
                    277:         MD5_Final(&key[MD5_SIZE], &md5_ctx);
                    278:     }
                    279: 
                    280:     /* decrypt using the key/iv */
                    281:     AES_set_key(&aes_ctx, key, iv, is_aes_256 ? AES_MODE_256 : AES_MODE_128);
                    282:     AES_convert_key(&aes_ctx);
                    283:     AES_cbc_decrypt(&aes_ctx, ssl_obj->buf, ssl_obj->buf, ssl_obj->len);
                    284:     ret = 0;
                    285: 
                    286: error:
                    287:     return ret; 
                    288: }
                    289: 
                    290: /**
                    291:  * Take a base64 blob of data and turn it into its proper ASN.1 form.
                    292:  */
                    293: static int new_pem_obj(SSL_CTX *ssl_ctx, int is_cacert, char *where, 
                    294:                     int remain, const char *password)
                    295: {
                    296:     int ret = SSL_ERROR_BAD_CERTIFICATE;
                    297:     SSLObjLoader *ssl_obj = NULL;
                    298: 
                    299:     while (remain > 0)
                    300:     {
                    301:         int i, pem_size, obj_type;
                    302:         char *start = NULL, *end = NULL;
                    303: 
                    304:         for (i = 0; i < NUM_PEM_TYPES; i++)
                    305:         {
                    306:             if ((start = strstr(where, begins[i])) &&
                    307:                     (end = strstr(where, ends[i])))
                    308:             {
                    309:                 remain -= (int)(end-where);
                    310:                 start += strlen(begins[i]);
                    311:                 pem_size = (int)(end-start);
                    312: 
                    313:                 ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
                    314: 
                    315:                 /* 4/3 bigger than what we need but so what */
                    316:                 ssl_obj->buf = (uint8_t *)calloc(1, pem_size);
                    317:                 ssl_obj->len = pem_size;
                    318: 
                    319:                 if (i == IS_RSA_PRIVATE_KEY && 
                    320:                             strstr(start, "Proc-Type:") && 
                    321:                             strstr(start, "4,ENCRYPTED"))
                    322:                 {
                    323:                     /* check for encrypted PEM file */
                    324:                     if (pem_decrypt(start, end, password, ssl_obj) < 0)
                    325:                     {
                    326:                         ret = SSL_ERROR_BAD_CERTIFICATE;
                    327:                         goto error;
                    328:                     }
                    329:                 }
                    330:                 else 
                    331:                 {
                    332:                     ssl_obj->len = pem_size;
                    333:                     if (base64_decode(start, pem_size, 
                    334:                                 ssl_obj->buf, &ssl_obj->len) != 0)
                    335:                     {
                    336:                         ret = SSL_ERROR_BAD_CERTIFICATE;
                    337:                         goto error;
                    338:                     }
                    339:                 }
                    340: 
                    341:                 switch (i)
                    342:                 {
                    343:                     case IS_RSA_PRIVATE_KEY:
                    344:                         obj_type = SSL_OBJ_RSA_KEY;
                    345:                         break;
                    346: 
                    347:                     case IS_ENCRYPTED_PRIVATE_KEY:
                    348:                     case IS_PRIVATE_KEY:
                    349:                         obj_type = SSL_OBJ_PKCS8;
                    350:                         break;
                    351: 
                    352:                     case IS_CERTIFICATE:
                    353:                         obj_type = is_cacert ?
                    354:                                         SSL_OBJ_X509_CACERT : SSL_OBJ_X509_CERT;
                    355:                         break;
                    356: 
                    357:                     default:
                    358:                         ret = SSL_ERROR_BAD_CERTIFICATE;
                    359:                         goto error;
                    360:                 }
                    361: 
                    362:                 /* In a format we can now understand - so process it */
                    363:                 if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password)))
                    364:                     goto error;
                    365: 
                    366:                 end += strlen(ends[i]);
                    367:                 remain -= strlen(ends[i]);
                    368:                 while (remain > 0 && (*end == '\r' || *end == '\n'))
                    369:                 {
                    370:                     end++;
                    371:                     remain--;
                    372:                 }
                    373: 
                    374:                 where = end;
                    375:                 break;
                    376:             }
                    377:         }
                    378: 
                    379:         ssl_obj_free(ssl_obj);
                    380:         ssl_obj = NULL;
                    381:         if (start == NULL)
                    382:            break;
                    383:     }
                    384: error:
                    385:     ssl_obj_free(ssl_obj);
                    386:     return ret;
                    387: }
                    388: 
                    389: /*
                    390:  * Load a file into memory that is in ASCII PEM format.
                    391:  */
                    392: static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type, 
                    393:                         SSLObjLoader *ssl_obj, const char *password)
                    394: {
                    395:     char *start;
                    396: 
                    397:     /* add a null terminator */
                    398:     ssl_obj->len++;
                    399:     ssl_obj->buf = (uint8_t *)realloc(ssl_obj->buf, ssl_obj->len);
                    400:     ssl_obj->buf[ssl_obj->len-1] = 0;
                    401:     start = (char *)ssl_obj->buf;
                    402:     return new_pem_obj(ssl_ctx, obj_type == SSL_OBJ_X509_CACERT,
                    403:                                 start, ssl_obj->len, password);
                    404: }
                    405: #endif /* CONFIG_SSL_HAS_PEM */
                    406: 
                    407: /**
                    408:  * Load the key/certificates in memory depending on compile-time and user
                    409:  * options. 
                    410:  */
                    411: int load_key_certs(SSL_CTX *ssl_ctx)
                    412: {
                    413:     int ret = SSL_OK;
                    414:     uint32_t options = ssl_ctx->options;
                    415: #ifdef CONFIG_SSL_GENERATE_X509_CERT 
                    416:     uint8_t *cert_data = NULL;
                    417:     int cert_size;
                    418:     static const char *dn[] = 
                    419:     {
                    420:         CONFIG_SSL_X509_COMMON_NAME,
                    421:         CONFIG_SSL_X509_ORGANIZATION_NAME,
                    422:         CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME
                    423:     };
                    424: #endif
                    425: 
                    426:     /* do the private key first */
                    427:     if (strlen(CONFIG_SSL_PRIVATE_KEY_LOCATION) > 0)
                    428:     {
                    429:         if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY, 
                    430:                                 CONFIG_SSL_PRIVATE_KEY_LOCATION,
                    431:                                 CONFIG_SSL_PRIVATE_KEY_PASSWORD)) < 0)
                    432:             goto error;
                    433:     }
                    434:     else if (!(options & SSL_NO_DEFAULT_KEY))
                    435:     {
                    436: #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
                    437:         static const    /* saves a few more bytes */
                    438: #include "private_key.h"
                    439: 
                    440:         ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key,
                    441:                 default_private_key_len, NULL); 
                    442: #endif
                    443:     }
                    444: 
                    445:     /* now load the certificate */
                    446: #ifdef CONFIG_SSL_GENERATE_X509_CERT 
                    447:     if ((cert_size = ssl_x509_create(ssl_ctx, 0, dn, &cert_data)) < 0)
                    448:     {
                    449:         ret = cert_size;
                    450:         goto error;
                    451:     }
                    452: 
                    453:     ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, cert_data, cert_size, NULL);
                    454:     free(cert_data);
                    455: #else
                    456:     if (strlen(CONFIG_SSL_X509_CERT_LOCATION))
                    457:     {
                    458:         if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, 
                    459:                                 CONFIG_SSL_X509_CERT_LOCATION, NULL)) < 0)
                    460:             goto error;
                    461:     }
                    462:     else if (!(options & SSL_NO_DEFAULT_KEY))
                    463:     {
                    464: #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
                    465:         static const    /* saves a few bytes and RAM */
                    466: #include "cert.h"
                    467:         ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, 
                    468:                     default_certificate, default_certificate_len, NULL);
                    469: #endif
                    470:     }
                    471: #endif
                    472: 
                    473: error:
                    474: #ifdef CONFIG_SSL_FULL_MODE
                    475:     if (ret)
                    476:     {
                    477:         printf("Error: Certificate or key not loaded\n"); TTY_FLUSH();
                    478:     }
                    479: #endif
                    480: 
                    481:     return ret;
                    482: 
                    483: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>