mbedTLS 2.x memory improvement
[umurmur.git] / src / ssli_mbedtls.c
1 /* Copyright (C) 2009-2015, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2015, Thorvald Natvig <thorvald@natvig.com>
3    Copyright (C) 2015-2015, Szymon Pusz <szymon@pusz.net>
4
5    All rights reserved.
6
7    Redistribution and use in source and binary forms, with or without
8    modification, are permitted provided that the following conditions
9    are met:
10
11    - Redistributions of source code must retain the above copyright notice,
12      this list of conditions and the following disclaimer.
13    - Redistributions in binary form must reproduce the above copyright notice,
14      this list of conditions and the following disclaimer in the documentation
15      and/or other materials provided with the distribution.
16    - Neither the name of the Developers nor the names of its contributors may
17      be used to endorse or promote products derived from this software without
18      specific prior written permission.
19
20    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
24    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #include "conf.h"
33 #include "log.h"
34 #include "ssl.h"
35
36 #include <stdlib.h>
37 #include <fcntl.h>
38
39 #include <mbedtls/config.h>
40 #include <mbedtls/havege.h>
41 #include <mbedtls/certs.h>
42 #include <mbedtls/x509.h>
43 #include <mbedtls/ssl.h>
44 #include <mbedtls/net.h>
45
46 const int ciphers[] =
47 {
48     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
49     MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
50     MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
51     0
52 };
53
54 static mbedtls_x509_crt certificate;
55 static inline int x509parse_keyfile(mbedtls_pk_context *pk, const char *path,
56                                     const char *pwd)
57 {
58     int ret;
59
60     mbedtls_pk_init(pk);
61     ret = mbedtls_pk_parse_keyfile(pk, path, pwd);
62     if (ret == 0 && !mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA))
63         ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
64
65     return ret;
66 }
67
68 static mbedtls_pk_context key;
69 bool_t builtInTestCertificate;
70
71 #ifdef USE_MBEDTLS_HAVEGE
72 havege_state hs;
73 #else
74 int urandom_fd;
75 #endif
76
77 /* DH prime */
78 char *my_dhm_P =
79         "9CE85640903BF123906947FEDE767261" \
80         "D9B4A973EB8F7D984A8C656E2BCC161C" \
81         "183D4CA471BA78225F940F16D1D99CA3" \
82         "E66152CC68EDCE1311A390F307741835" \
83         "44FF6AB553EC7073AD0CB608F2A3B480" \
84         "19E6C02BCED40BD30E91BB2469089670" \
85         "DEF409C08E8AC24D1732A6128D2220DC53";
86 char *my_dhm_G = "4";
87
88 #ifdef USE_MBEDTLS_TESTCERT
89 static void initTestCert()
90 {
91         int rc;
92         builtInTestCertificate = true;
93         rc = mbedtls_x509_crt_parse_rsa(&certificate, (unsigned char *)test_srv_crt,
94                 strlen(test_srv_crt));
95
96         if (rc != 0)
97                 Log_fatal("Could not parse built-in test certificate");
98 }
99
100 static void initTestKey()
101 {
102         int rc;
103
104         rc = mbedtls_x509parse_key_rsa(&key, (unsigned char *)test_srv_key,
105                                strlen(test_srv_key), NULL, 0);
106         if (rc != 0)
107                 Log_fatal("Could not parse built-in test RSA key");
108 }
109 #endif
110
111 /*
112  * How to generate a self-signed cert with openssl:
113  * openssl genrsa 1024 > host.key
114  * openssl req -new -x509 -nodes -sha1 -days 365 -key host.key > host.cert
115  */
116 static void initCert()
117 {
118         int rc;
119         char *crtfile = (char *)getStrConf(CERTIFICATE);
120
121         if (crtfile == NULL) {
122 #ifdef USE_MBEDTLS_TESTCERT
123                 Log_warn("No certificate file specified. Falling back to test certificate.");
124                 initTestCert();
125 #else
126                 Log_fatal("No certificate file specified");
127 #endif
128                 return;
129         }
130
131         rc = mbedtls_x509_crt_parse_file(&certificate, crtfile);
132
133         if (rc != 0) {
134 #ifdef USE_MBEDTLS_TESTCERT
135                 Log_warn("Could not read certificate file '%s'. Falling back to test certificate.", crtfile);
136                 initTestCert();
137 #else
138                 Log_fatal("Could not read certificate file '%s'", crtfile);
139 #endif
140                 return;
141         }
142 }
143
144 static void initKey()
145 {
146         int rc;
147         char *keyfile = (char *)getStrConf(KEY);
148
149         if (keyfile == NULL)
150                 Log_fatal("No key file specified");
151         rc = x509parse_keyfile(&key, keyfile, NULL);
152         if (rc != 0)
153                 Log_fatal("Could not read RSA key file %s", keyfile);
154 }
155
156 #ifndef USE_MBEDTLS_HAVEGE
157 int urandom_bytes(void *ctx, unsigned char *dest, size_t len)
158 {
159         int cur;
160
161         while (len) {
162                 cur = read(urandom_fd, dest, len);
163                 if (cur < 0)
164                         continue;
165                 len -= cur;
166         }
167         return 0;
168 }
169 #endif
170
171 #define DEBUG_LEVEL 0
172 static void pssl_debug(void *ctx, int level, const char *file, int line, const char *str)
173 {
174     if (level <= DEBUG_LEVEL)
175                 Log_info("mbedTLS [level %d]: %s", level, str);
176 }
177
178 mbedtls_ssl_config *conf;
179
180 void SSLi_init(void)
181 {
182         char verstring[12];
183         int rc;
184
185         initCert();
186 #ifdef USE_MBEDTLS_TESTCERT
187         if (builtInTestCertificate) {
188                 Log_warn("*** Using built-in test certificate and RSA key ***");
189                 Log_warn("*** This is not secure! Please use a CA-signed certificate or create a key and self-signed certificate ***");
190                 initTestKey();
191         }
192         else
193                 initKey();
194 #else
195         initKey();
196 #endif
197
198         /* Initialize random number generator */
199 #ifdef USE_MBEDTLS_HAVEGE
200     mbedtls_havege_init(&hs);
201 #else
202     urandom_fd = open("/dev/urandom", O_RDONLY);
203     if (urandom_fd < 0)
204             Log_fatal("Cannot open /dev/urandom");
205 #endif
206
207         /* Initialize config */
208         conf = calloc(1, sizeof(mbedtls_ssl_config));
209
210         if (!conf)
211                 Log_fatal("Out of memory");
212
213         mbedtls_ssl_config_init(conf);
214
215         if((rc = mbedtls_ssl_config_defaults(conf,
216                         MBEDTLS_SSL_IS_SERVER,
217                         MBEDTLS_SSL_TRANSPORT_STREAM,
218                         MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
219                 Log_fatal("mbedtls_ssl_config_defaults returned %d", rc);
220
221         mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
222 #ifdef USE_MBEDTLS_HAVEGE
223         mbedtls_ssl_conf_rng(conf, HAVEGE_RAND, &hs);
224 #else
225         mbedtls_ssl_conf_rng(conf, urandom_bytes, NULL);
226 #endif
227         mbedtls_ssl_conf_dbg(conf, pssl_debug, NULL);
228
229         mbedtls_ssl_conf_ciphersuites(conf, (const int*)&ciphers);
230
231         mbedtls_ssl_conf_ca_chain(conf, &certificate, NULL);
232
233         if((rc = mbedtls_ssl_conf_own_cert(conf, &certificate, &key)) != 0)
234                 Log_fatal("mbedtls_ssl_conf_own_cert returned %d", rc);
235
236         if((rc = mbedtls_ssl_conf_dh_param(conf, my_dhm_P, my_dhm_G)) != 0)
237                 Log_fatal("mbedtls_ssl_conf_dh_param returned %d", rc);
238
239 #ifdef MBEDTLS_VERSION_FEATURES
240     mbedtls_version_get_string(verstring);
241     Log_info("mbedTLS library version %s initialized", verstring);
242 #else
243     Log_info("mbedTLS library initialized");
244 #endif
245 }
246
247 void SSLi_deinit(void)
248 {
249         mbedtls_ssl_config_free(conf);
250         free(conf);
251         mbedtls_x509_crt_free(&certificate);
252         mbedtls_pk_free(&key);
253 }
254
255 /* Create SHA1 of last certificate in the peer's chain. */
256 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
257 {
258         mbedtls_x509_crt const *cert;
259         cert = mbedtls_ssl_get_peer_cert(ssl);
260
261         if (!cert) {
262                 return false;
263         }
264         mbedtls_sha1(cert->raw.p, cert->raw.len, hash);
265         return true;
266 }
267
268 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
269 {
270         mbedtls_ssl_context *ssl;
271         mbedtls_ssl_session *ssn;
272         int rc;
273
274         ssl = calloc(1, sizeof(mbedtls_ssl_context));
275         ssn = calloc(1, sizeof(mbedtls_ssl_session));
276
277         if (!ssl || !ssn)
278                 Log_fatal("Out of memory");
279
280         mbedtls_ssl_init(ssl);
281         mbedtls_ssl_set_bio(ssl, fd, mbedtls_net_send, mbedtls_net_recv, NULL);
282         mbedtls_ssl_set_session(ssl, ssn);
283         
284         if((rc = mbedtls_ssl_setup(ssl, conf)) != 0)
285                 Log_fatal("mbedtls_ssl_setup returned %d", rc);
286
287         return ssl;
288 }
289
290 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
291 {
292         int rc;
293
294         rc = mbedtls_ssl_handshake(ssl);
295         if (rc != 0) {
296                 if (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE) {
297                         return 0;
298                 } else if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { /* Allow this (selfsigned etc) */
299                         return 0;
300                 } else {
301                         Log_warn("SSL handshake failed: %d", rc);
302                         return -1;
303                 }
304         }
305         *SSLready = true;
306         return 0;
307 }
308
309 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
310 {
311         int rc;
312
313         rc = mbedtls_ssl_read(ssl, buf, len);
314         if (rc == MBEDTLS_ERR_SSL_WANT_READ)
315                 return SSLI_ERROR_WANT_READ;
316         return rc;
317 }
318
319 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
320 {
321         int rc;
322
323         rc = mbedtls_ssl_write(ssl, buf, len);
324         if (rc == MBEDTLS_ERR_SSL_WANT_WRITE)
325                 return SSLI_ERROR_WANT_WRITE;
326         return rc;
327 }
328
329 int SSLi_get_error(SSL_handle_t *ssl, int code)
330 {
331         return code;
332 }
333
334 bool_t SSLi_data_pending(SSL_handle_t *ssl)
335 {
336         return mbedtls_ssl_get_bytes_avail(ssl) > 0;
337 }
338
339 void SSLi_shutdown(SSL_handle_t *ssl)
340 {
341         mbedtls_ssl_close_notify(ssl);
342 }
343
344 void SSLi_free(SSL_handle_t *ssl)
345 {
346         Log_debug("SSLi_free");
347         mbedtls_ssl_free(ssl);
348         free(ssl);
349 }
350