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