mbedTLS 2.x support
[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 void SSLi_init(void)
179 {
180         char verstring[12];
181
182         initCert();
183 #ifdef USE_MBEDTLS_TESTCERT
184         if (builtInTestCertificate) {
185                 Log_warn("*** Using built-in test certificate and RSA key ***");
186                 Log_warn("*** This is not secure! Please use a CA-signed certificate or create a key and self-signed certificate ***");
187                 initTestKey();
188         }
189         else
190                 initKey();
191 #else
192         initKey();
193 #endif
194
195         /* Initialize random number generator */
196 #ifdef USE_MBEDTLS_HAVEGE
197     mbedtls_havege_init(&hs);
198 #else
199     urandom_fd = open("/dev/urandom", O_RDONLY);
200     if (urandom_fd < 0)
201             Log_fatal("Cannot open /dev/urandom");
202 #endif
203
204 #ifdef MBEDTLS_VERSION_FEATURES
205     mbedtls_version_get_string(verstring);
206     Log_info("mbedTLS library version %s initialized", verstring);
207 #else
208     Log_info("mbedTLS library initialized");
209 #endif
210 }
211
212 void SSLi_deinit(void)
213 {
214         mbedtls_x509_crt_free(&certificate);
215         mbedtls_pk_free(&key);
216 }
217
218 /* Create SHA1 of last certificate in the peer's chain. */
219 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
220 {
221         mbedtls_x509_crt const *cert;
222         cert = mbedtls_ssl_get_peer_cert(ssl);
223
224         if (!cert) {
225                 return false;
226         }
227         mbedtls_sha1(cert->raw.p, cert->raw.len, hash);
228         return true;
229 }
230
231 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
232 {
233         mbedtls_ssl_context *ssl;
234         mbedtls_ssl_session *ssn;
235         mbedtls_ssl_config *conf;
236         int rc;
237
238         ssl = calloc(1, sizeof(mbedtls_ssl_context));
239         ssn = calloc(1, sizeof(mbedtls_ssl_session));
240         conf = calloc(1, sizeof(mbedtls_ssl_config));
241
242         if (!ssl || !ssn || !conf)
243                 Log_fatal("Out of memory");
244
245         mbedtls_ssl_init(ssl);
246         mbedtls_ssl_config_init(conf);
247
248         if((rc = mbedtls_ssl_config_defaults(conf,
249                         MBEDTLS_SSL_IS_SERVER,
250                         MBEDTLS_SSL_TRANSPORT_STREAM,
251                         MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
252                 Log_fatal("mbedtls_ssl_config_defaults returned %d", rc);
253
254         mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
255 #ifdef USE_MBEDTLS_HAVEGE
256         mbedtls_ssl_conf_rng(conf, HAVEGE_RAND, &hs);
257 #else
258         mbedtls_ssl_conf_rng(conf, urandom_bytes, NULL);
259 #endif
260         mbedtls_ssl_conf_dbg(conf, pssl_debug, NULL);
261         mbedtls_ssl_set_bio(ssl, fd, mbedtls_net_send, mbedtls_net_recv, NULL);
262         mbedtls_ssl_conf_ciphersuites(conf, (const int*)&ciphers);
263         mbedtls_ssl_set_session(ssl, ssn);
264         mbedtls_ssl_conf_ca_chain(conf, &certificate, NULL);
265
266         if((rc = mbedtls_ssl_conf_own_cert(conf, &certificate, &key)) != 0)
267                 Log_fatal("mbedtls_ssl_conf_own_cert returned %d", rc);
268
269         if((rc = mbedtls_ssl_conf_dh_param(conf, my_dhm_P, my_dhm_G)) != 0)
270                 Log_fatal("mbedtls_ssl_conf_dh_param returned %d", rc);
271
272         if((rc = mbedtls_ssl_setup(ssl, conf)) != 0)
273                 Log_fatal("mbedtls_ssl_setup returned %d", rc);
274
275         return ssl;
276 }
277
278 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
279 {
280         int rc;
281
282         rc = mbedtls_ssl_handshake(ssl);
283         if (rc != 0) {
284                 if (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE) {
285                         return 0;
286                 } else if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { /* Allow this (selfsigned etc) */
287                         return 0;
288                 } else {
289                         Log_warn("SSL handshake failed: %d", rc);
290                         return -1;
291                 }
292         }
293         *SSLready = true;
294         return 0;
295 }
296
297 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
298 {
299         int rc;
300
301         rc = mbedtls_ssl_read(ssl, buf, len);
302         if (rc == MBEDTLS_ERR_SSL_WANT_READ)
303                 return SSLI_ERROR_WANT_READ;
304         return rc;
305 }
306
307 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
308 {
309         int rc;
310
311         rc = mbedtls_ssl_write(ssl, buf, len);
312         if (rc == MBEDTLS_ERR_SSL_WANT_WRITE)
313                 return SSLI_ERROR_WANT_WRITE;
314         return rc;
315 }
316
317 int SSLi_get_error(SSL_handle_t *ssl, int code)
318 {
319         return code;
320 }
321
322 bool_t SSLi_data_pending(SSL_handle_t *ssl)
323 {
324         return mbedtls_ssl_get_bytes_avail(ssl) > 0;
325 }
326
327 void SSLi_shutdown(SSL_handle_t *ssl)
328 {
329         mbedtls_ssl_close_notify(ssl);
330 }
331
332 void SSLi_free(SSL_handle_t *ssl)
333 {
334         Log_debug("SSLi_free");
335         mbedtls_ssl_config_free((mbedtls_ssl_config*)ssl->conf);
336         mbedtls_ssl_free(ssl);
337         free((mbedtls_ssl_config*)ssl->conf);
338         free(ssl);
339 }
340