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  */
ssl_obj_load(SSL_CTX * ssl_ctx,int obj_type,const char * filename,const char * password)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  */
ssl_obj_memory_load(SSL_CTX * ssl_ctx,int mem_type,const uint8_t * data,int len,const char * password)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  */
do_obj(SSL_CTX * ssl_ctx,int obj_type,SSLObjLoader * ssl_obj,const char * password)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  */
ssl_obj_free(SSLObjLoader * ssl_obj)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  */
pem_decrypt(const char * where,const char * end,const char * password,SSLObjLoader * ssl_obj)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  */
new_pem_obj(SSL_CTX * ssl_ctx,int is_cacert,char * where,int remain,const char * password)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  */
ssl_obj_PEM_load(SSL_CTX * ssl_ctx,int obj_type,SSLObjLoader * ssl_obj,const char * password)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  */
load_key_certs(SSL_CTX * ssl_ctx)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 }
484