Add axTLS sourcecode
[project/luci.git] / libs / nixio / axTLS / ssl / loader.c
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
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 (strncmp((char *)ssl_obj->buf, begin, strlen(begin)) == 0)
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 ret = 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 3
179 #define IV_SIZE 16
180 #define IS_RSA_PRIVATE_KEY 0
181 #define IS_ENCRYPTED_PRIVATE_KEY 1
182 #define IS_CERTIFICATE 2
183
184 static const char * const begins[NUM_PEM_TYPES] =
185 {
186 "-----BEGIN RSA PRIVATE KEY-----",
187 "-----BEGIN ENCRYPTED PRIVATE KEY-----",
188 "-----BEGIN CERTIFICATE-----",
189 };
190
191 static const char * const ends[NUM_PEM_TYPES] =
192 {
193 "-----END RSA PRIVATE KEY-----",
194 "-----END ENCRYPTED PRIVATE KEY-----",
195 "-----END CERTIFICATE-----",
196 };
197
198 static const char * const aes_str[2] =
199 {
200 "DEK-Info: AES-128-CBC,",
201 "DEK-Info: AES-256-CBC,"
202 };
203
204 /**
205 * Take a base64 blob of data and decrypt it (using AES) into its
206 * proper ASN.1 form.
207 */
208 static int pem_decrypt(const char *where, const char *end,
209 const char *password, SSLObjLoader *ssl_obj)
210 {
211 int ret = -1;
212 int is_aes_256 = 0;
213 char *start = NULL;
214 uint8_t iv[IV_SIZE];
215 int i, pem_size;
216 MD5_CTX md5_ctx;
217 AES_CTX aes_ctx;
218 uint8_t key[32]; /* AES256 size */
219
220 if (password == NULL || strlen(password) == 0)
221 {
222 #ifdef CONFIG_SSL_FULL_MODE
223 printf("Error: Need a password for this PEM file\n"); TTY_FLUSH();
224 #endif
225 goto error;
226 }
227
228 if ((start = strstr((const char *)where, aes_str[0]))) /* AES128? */
229 {
230 start += strlen(aes_str[0]);
231 }
232 else if ((start = strstr((const char *)where, aes_str[1]))) /* AES256? */
233 {
234 is_aes_256 = 1;
235 start += strlen(aes_str[1]);
236 }
237 else
238 {
239 #ifdef CONFIG_SSL_FULL_MODE
240 printf("Error: Unsupported password cipher\n"); TTY_FLUSH();
241 #endif
242 goto error;
243 }
244
245 /* convert from hex to binary - assumes uppercase hex */
246 for (i = 0; i < IV_SIZE; i++)
247 {
248 char c = *start++ - '0';
249 iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4;
250 c = *start++ - '0';
251 iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c);
252 }
253
254 while (*start == '\r' || *start == '\n')
255 start++;
256
257 /* turn base64 into binary */
258 pem_size = (int)(end-start);
259 if (base64_decode(start, pem_size, ssl_obj->buf, &ssl_obj->len) != 0)
260 goto error;
261
262 /* work out the key */
263 MD5_Init(&md5_ctx);
264 MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
265 MD5_Update(&md5_ctx, iv, SALT_SIZE);
266 MD5_Final(key, &md5_ctx);
267
268 if (is_aes_256)
269 {
270 MD5_Init(&md5_ctx);
271 MD5_Update(&md5_ctx, key, MD5_SIZE);
272 MD5_Update(&md5_ctx, (const uint8_t *)password, strlen(password));
273 MD5_Update(&md5_ctx, iv, SALT_SIZE);
274 MD5_Final(&key[MD5_SIZE], &md5_ctx);
275 }
276
277 /* decrypt using the key/iv */
278 AES_set_key(&aes_ctx, key, iv, is_aes_256 ? AES_MODE_256 : AES_MODE_128);
279 AES_convert_key(&aes_ctx);
280 AES_cbc_decrypt(&aes_ctx, ssl_obj->buf, ssl_obj->buf, ssl_obj->len);
281 ret = 0;
282
283 error:
284 return ret;
285 }
286
287 /**
288 * Take a base64 blob of data and turn it into its proper ASN.1 form.
289 */
290 static int new_pem_obj(SSL_CTX *ssl_ctx, int is_cacert, char *where,
291 int remain, const char *password)
292 {
293 int ret = SSL_OK;
294 SSLObjLoader *ssl_obj = NULL;
295 int i, pem_size, obj_type;
296 char *start = NULL, *end = NULL;
297
298 for (i = 0; i < NUM_PEM_TYPES; i++)
299 {
300 if ((start = strstr(where, begins[i])) &&
301 (end = strstr(where, ends[i])))
302 {
303 remain -= (int)(end-start);
304 start += strlen(begins[i]);
305 pem_size = (int)(end-start);
306
307 ssl_obj = (SSLObjLoader *)calloc(1, sizeof(SSLObjLoader));
308
309 /* 4/3 bigger than what we need but so what */
310 ssl_obj->buf = (uint8_t *)calloc(1, pem_size);
311
312 if (i == IS_RSA_PRIVATE_KEY &&
313 strstr(start, "Proc-Type:") &&
314 strstr(start, "4,ENCRYPTED"))
315 {
316 /* check for encrypted PEM file */
317 if (pem_decrypt(start, end, password, ssl_obj) < 0)
318 goto error;
319 }
320 else if (base64_decode(start, pem_size,
321 ssl_obj->buf, &ssl_obj->len) != 0)
322 goto error;
323
324 switch (i)
325 {
326 case IS_RSA_PRIVATE_KEY:
327 obj_type = SSL_OBJ_RSA_KEY;
328 break;
329
330 case IS_ENCRYPTED_PRIVATE_KEY:
331 obj_type = SSL_OBJ_PKCS8;
332 break;
333
334 case IS_CERTIFICATE:
335 obj_type = is_cacert ?
336 SSL_OBJ_X509_CACERT : SSL_OBJ_X509_CERT;
337 break;
338
339 default:
340 goto error;
341 }
342
343 /* In a format we can now understand - so process it */
344 if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password)))
345 goto error;
346
347 end += strlen(ends[i]);
348 remain -= strlen(ends[i]);
349 while (remain > 0 && (*end == '\r' || *end == '\n'))
350 {
351 end++;
352 remain--;
353 }
354
355 break;
356 }
357 }
358
359 if (i == NUM_PEM_TYPES)
360 goto error;
361
362 /* more PEM stuff to process? */
363 if (remain)
364 ret = new_pem_obj(ssl_ctx, is_cacert, end, remain, password);
365
366 error:
367 ssl_obj_free(ssl_obj);
368 return ret;
369 }
370
371 /*
372 * Load a file into memory that is in ASCII PEM format.
373 */
374 static int ssl_obj_PEM_load(SSL_CTX *ssl_ctx, int obj_type,
375 SSLObjLoader *ssl_obj, const char *password)
376 {
377 char *start;
378
379 /* add a null terminator */
380 ssl_obj->len++;
381 ssl_obj->buf = (uint8_t *)realloc(ssl_obj->buf, ssl_obj->len);
382 ssl_obj->buf[ssl_obj->len-1] = 0;
383 start = (char *)ssl_obj->buf;
384 return new_pem_obj(ssl_ctx, obj_type == SSL_OBJ_X509_CACERT,
385 start, ssl_obj->len, password);
386 }
387 #endif /* CONFIG_SSL_HAS_PEM */
388
389 /**
390 * Load the key/certificates in memory depending on compile-time and user
391 * options.
392 */
393 int load_key_certs(SSL_CTX *ssl_ctx)
394 {
395 int ret = SSL_OK;
396 uint32_t options = ssl_ctx->options;
397 #ifdef CONFIG_SSL_GENERATE_X509_CERT
398 uint8_t *cert_data = NULL;
399 int cert_size;
400 static const char *dn[] =
401 {
402 CONFIG_SSL_X509_COMMON_NAME,
403 CONFIG_SSL_X509_ORGANIZATION_NAME,
404 CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME
405 };
406 #endif
407
408 /* do the private key first */
409 if (strlen(CONFIG_SSL_PRIVATE_KEY_LOCATION) > 0)
410 {
411 if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY,
412 CONFIG_SSL_PRIVATE_KEY_LOCATION,
413 CONFIG_SSL_PRIVATE_KEY_PASSWORD)) < 0)
414 goto error;
415 }
416 else if (!(options & SSL_NO_DEFAULT_KEY))
417 {
418 #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
419 static const /* saves a few more bytes */
420 #include "private_key.h"
421
422 ssl_obj_memory_load(ssl_ctx, SSL_OBJ_RSA_KEY, default_private_key,
423 default_private_key_len, NULL);
424 #endif
425 }
426
427 /* now load the certificate */
428 #ifdef CONFIG_SSL_GENERATE_X509_CERT
429 if ((cert_size = ssl_x509_create(ssl_ctx, 0, dn, &cert_data)) < 0)
430 {
431 ret = cert_size;
432 goto error;
433 }
434
435 ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT, cert_data, cert_size, NULL);
436 free(cert_data);
437 #else
438 if (strlen(CONFIG_SSL_X509_CERT_LOCATION))
439 {
440 if ((ret = ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT,
441 CONFIG_SSL_X509_CERT_LOCATION, NULL)) < 0)
442 goto error;
443 }
444 else if (!(options & SSL_NO_DEFAULT_KEY))
445 {
446 #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
447 static const /* saves a few bytes and RAM */
448 #include "cert.h"
449 ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT,
450 default_certificate, default_certificate_len, NULL);
451 #endif
452 }
453 #endif
454
455 error:
456 #ifdef CONFIG_SSL_FULL_MODE
457 if (ret)
458 {
459 printf("Error: Certificate or key not loaded\n"); TTY_FLUSH();
460 }
461 #endif
462
463 return ret;
464
465 }