a843d976906c87cb51a2082f18a12bbbb36ef11d
[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 #include "memory.h"
36
37 #include <stdlib.h>
38 #include <fcntl.h>
39
40 #include <mbedtls/config.h>
41 #include <mbedtls/havege.h>
42 #include <mbedtls/certs.h>
43 #include <mbedtls/x509.h>
44 #include <mbedtls/ssl.h>
45 #include <mbedtls/net.h>
46
47 const int ciphers[] =
48 {
49     MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
50     MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
51     MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
52     0
53 };
54
55 static mbedtls_x509_crt certificate;
56 static inline int x509parse_keyfile(mbedtls_pk_context *pk, const char *path,
57                                     const char *pwd)
58 {
59     int ret;
60
61     mbedtls_pk_init(pk);
62     ret = mbedtls_pk_parse_keyfile(pk, path, pwd);
63     if (ret == 0 && !mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA))
64         ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
65
66     return ret;
67 }
68
69 static mbedtls_pk_context key;
70 bool_t builtInTestCertificate;
71
72 #ifdef USE_MBEDTLS_HAVEGE
73 havege_state hs;
74 #else
75 int urandom_fd;
76 #endif
77
78 /* DH prime */
79 char *my_dhm_P =
80         "9CE85640903BF123906947FEDE767261" \
81         "D9B4A973EB8F7D984A8C656E2BCC161C" \
82         "183D4CA471BA78225F940F16D1D99CA3" \
83         "E66152CC68EDCE1311A390F307741835" \
84         "44FF6AB553EC7073AD0CB608F2A3B480" \
85         "19E6C02BCED40BD30E91BB2469089670" \
86         "DEF409C08E8AC24D1732A6128D2220DC53";
87 char *my_dhm_G = "4";
88
89 #ifdef USE_MBEDTLS_TESTCERT
90 static void initTestCert()
91 {
92         int rc;
93         builtInTestCertificate = true;
94         rc = mbedtls_x509_crt_parse_rsa(&certificate, (unsigned char *)test_srv_crt,
95                 strlen(test_srv_crt));
96
97         if (rc != 0)
98                 Log_fatal("Could not parse built-in test certificate");
99 }
100
101 static void initTestKey()
102 {
103         int rc;
104
105         rc = mbedtls_x509parse_key_rsa(&key, (unsigned char *)test_srv_key,
106                                strlen(test_srv_key), NULL, 0);
107         if (rc != 0)
108                 Log_fatal("Could not parse built-in test RSA key");
109 }
110 #endif
111
112 /*
113  * How to generate a self-signed cert with openssl:
114  * openssl genrsa 1024 > host.key
115  * openssl req -new -x509 -nodes -sha1 -days 365 -key host.key > host.cert
116  */
117 static void initCert()
118 {
119         int rc;
120         char *crtfile = (char *)getStrConf(CERTIFICATE);
121
122         if (crtfile == NULL) {
123 #ifdef USE_MBEDTLS_TESTCERT
124                 Log_warn("No certificate file specified. Falling back to test certificate.");
125                 initTestCert();
126 #else
127                 Log_fatal("No certificate file specified");
128 #endif
129                 return;
130         }
131
132         rc = mbedtls_x509_crt_parse_file(&certificate, crtfile);
133
134         if (rc != 0) {
135 #ifdef USE_MBEDTLS_TESTCERT
136                 Log_warn("Could not read certificate file '%s'. Falling back to test certificate.", crtfile);
137                 initTestCert();
138 #else
139                 Log_fatal("Could not read certificate file '%s'", crtfile);
140 #endif
141                 return;
142         }
143 }
144
145 static void initKey()
146 {
147         int rc;
148         char *keyfile = (char *)getStrConf(KEY);
149
150         if (keyfile == NULL)
151                 Log_fatal("No key file specified");
152         rc = x509parse_keyfile(&key, keyfile, NULL);
153         if (rc != 0)
154                 Log_fatal("Could not read RSA key file %s", keyfile);
155 }
156
157 #ifndef USE_MBEDTLS_HAVEGE
158 int urandom_bytes(void *ctx, unsigned char *dest, size_t len)
159 {
160         int cur;
161
162         while (len) {
163                 cur = read(urandom_fd, dest, len);
164                 if (cur < 0)
165                         continue;
166                 len -= cur;
167         }
168         return 0;
169 }
170 #endif
171
172 #define DEBUG_LEVEL 0
173 static void pssl_debug(void *ctx, int level, const char *file, int line, const char *str)
174 {
175     if (level <= DEBUG_LEVEL)
176                 Log_info("mbedTLS [level %d]: %s", level, str);
177 }
178
179 mbedtls_ssl_config *conf;
180
181 void SSLi_init(void)
182 {
183         char verstring[12];
184         int rc;
185
186         initCert();
187 #ifdef USE_MBEDTLS_TESTCERT
188         if (builtInTestCertificate) {
189                 Log_warn("*** Using built-in test certificate and RSA key ***");
190                 Log_warn("*** This is not secure! Please use a CA-signed certificate or create a key and self-signed certificate ***");
191                 initTestKey();
192         }
193         else
194                 initKey();
195 #else
196         initKey();
197 #endif
198
199         /* Initialize random number generator */
200 #ifdef USE_MBEDTLS_HAVEGE
201     mbedtls_havege_init(&hs);
202 #else
203     urandom_fd = open("/dev/urandom", O_RDONLY);
204     if (urandom_fd < 0)
205             Log_fatal("Cannot open /dev/urandom");
206 #endif
207
208         /* Initialize config */
209         conf = Memory_safeCalloc(1, sizeof(mbedtls_ssl_config));
210
211         if (!conf)
212                 Log_fatal("Out of memory");
213
214         mbedtls_ssl_config_init(conf);
215
216         if((rc = mbedtls_ssl_config_defaults(conf,
217                         MBEDTLS_SSL_IS_SERVER,
218                         MBEDTLS_SSL_TRANSPORT_STREAM,
219                         MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
220                 Log_fatal("mbedtls_ssl_config_defaults returned %d", rc);
221
222         mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
223 #ifdef USE_MBEDTLS_HAVEGE
224         mbedtls_ssl_conf_rng(conf, HAVEGE_RAND, &hs);
225 #else
226         mbedtls_ssl_conf_rng(conf, urandom_bytes, NULL);
227 #endif
228         mbedtls_ssl_conf_dbg(conf, pssl_debug, NULL);
229
230         mbedtls_ssl_conf_ciphersuites(conf, (const int*)&ciphers);
231
232         mbedtls_ssl_conf_ca_chain(conf, &certificate, NULL);
233
234         if((rc = mbedtls_ssl_conf_own_cert(conf, &certificate, &key)) != 0)
235                 Log_fatal("mbedtls_ssl_conf_own_cert returned %d", rc);
236
237         if((rc = mbedtls_ssl_conf_dh_param(conf, my_dhm_P, my_dhm_G)) != 0)
238                 Log_fatal("mbedtls_ssl_conf_dh_param returned %d", rc);
239
240 #ifdef MBEDTLS_VERSION_FEATURES
241     mbedtls_version_get_string(verstring);
242     Log_info("mbedTLS library version %s initialized", verstring);
243 #else
244     Log_info("mbedTLS library initialized");
245 #endif
246 }
247
248 void SSLi_deinit(void)
249 {
250         mbedtls_ssl_config_free(conf);
251         free(conf);
252         mbedtls_x509_crt_free(&certificate);
253         mbedtls_pk_free(&key);
254 }
255
256 /* Create SHA1 of last certificate in the peer's chain. */
257 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
258 {
259         mbedtls_x509_crt const *cert;
260         cert = mbedtls_ssl_get_peer_cert(ssl);
261
262         if (!cert) {
263                 return false;
264         }
265         mbedtls_sha1(cert->raw.p, cert->raw.len, hash);
266         return true;
267 }
268
269 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
270 {
271         mbedtls_ssl_context *ssl;
272         mbedtls_ssl_session *ssn;
273         int rc;
274
275         ssl = Memory_safeCalloc(1, sizeof(mbedtls_ssl_context));
276         ssn = Memory_safeCalloc(1, sizeof(mbedtls_ssl_session));
277
278         if (!ssl || !ssn)
279                 Log_fatal("Out of memory");
280
281         mbedtls_ssl_init(ssl);
282         mbedtls_ssl_set_bio(ssl, fd, mbedtls_net_send, mbedtls_net_recv, NULL);
283         mbedtls_ssl_set_session(ssl, ssn);
284
285         if((rc = mbedtls_ssl_setup(ssl, conf)) != 0)
286                 Log_fatal("mbedtls_ssl_setup returned %d", rc);
287
288         return ssl;
289 }
290
291 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
292 {
293         int rc;
294
295         rc = mbedtls_ssl_handshake(ssl);
296         if (rc != 0) {
297                 if (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE) {
298                         return 0;
299                 } else if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { /* Allow this (selfsigned etc) */
300                         return 0;
301                 } else {
302                         Log_warn("SSL handshake failed: %d", rc);
303                         return -1;
304                 }
305         }
306         *SSLready = true;
307         return 0;
308 }
309
310 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
311 {
312         int rc;
313
314         rc = mbedtls_ssl_read(ssl, buf, len);
315         if (rc == MBEDTLS_ERR_SSL_WANT_READ)
316                 return SSLI_ERROR_WANT_READ;
317         return rc;
318 }
319
320 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
321 {
322         int rc;
323
324         rc = mbedtls_ssl_write(ssl, buf, len);
325         if (rc == MBEDTLS_ERR_SSL_WANT_WRITE)
326                 return SSLI_ERROR_WANT_WRITE;
327         return rc;
328 }
329
330 int SSLi_get_error(SSL_handle_t *ssl, int code)
331 {
332         return code;
333 }
334
335 bool_t SSLi_data_pending(SSL_handle_t *ssl)
336 {
337         return mbedtls_ssl_get_bytes_avail(ssl) > 0;
338 }
339
340 void SSLi_shutdown(SSL_handle_t *ssl)
341 {
342         mbedtls_ssl_close_notify(ssl);
343 }
344
345 void SSLi_free(SSL_handle_t *ssl)
346 {
347         Log_debug("SSLi_free");
348         mbedtls_ssl_free(ssl);
349         free(ssl);
350 }
351