0f55a9d168630f56f03539e809f66d376dba3bfa
[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 #include <mbedtls/sha1.h>
47
48 const int ciphers[] =
49 {
50         MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
51         MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
52         MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
53         MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
54         MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
55         MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
56     0
57 };
58
59 static mbedtls_x509_crt certificate;
60 static inline int x509parse_keyfile(mbedtls_pk_context *pk, const char *path, const char *pwd)
61 {
62     int ret;
63
64     mbedtls_pk_init(pk);
65     ret = mbedtls_pk_parse_keyfile(pk, path, pwd);
66     if (ret == 0 && !mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA) && !mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA))
67         {
68         ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
69         }
70
71     return ret;
72 }
73
74 static mbedtls_pk_context key;
75 bool_t builtInTestCertificate;
76
77 #ifdef USE_MBEDTLS_HAVEGE
78 havege_state hs;
79 #else
80 int urandom_fd;
81 #endif
82
83 static void initCert()
84 {
85         int rc;
86         char *crtfile = (char *)getStrConf(CERTIFICATE);
87
88         if (crtfile == NULL) {
89                 Log_fatal("No certificate file specified");
90                 return;
91         }
92
93         rc = mbedtls_x509_crt_parse_file(&certificate, crtfile);
94
95         if (rc != 0) {
96                 Log_fatal("Could not read certificate file '%s'", crtfile);
97                 return;
98         }
99 }
100
101 static void initKey()
102 {
103         int rc;
104         char *keyfile = (char *)getStrConf(KEY);
105
106         if (keyfile == NULL)
107                 Log_fatal("No key file specified");
108         rc = x509parse_keyfile(&key, keyfile, NULL);
109         if (rc != 0)
110                 Log_fatal("Could not read private key file %s", keyfile);
111 }
112
113 #ifndef USE_MBEDTLS_HAVEGE
114 int urandom_bytes(void *ctx, unsigned char *dest, size_t len)
115 {
116         int cur;
117
118         while (len) {
119                 cur = read(urandom_fd, dest, len);
120                 if (cur < 0)
121                         continue;
122                 len -= cur;
123         }
124         return 0;
125 }
126 #endif
127
128 #define DEBUG_LEVEL 0
129 static void pssl_debug(void *ctx, int level, const char *file, int line, const char *str)
130 {
131     if (level <= DEBUG_LEVEL)
132                 Log_info("mbedTLS [level %d]: %s", level, str);
133 }
134
135 mbedtls_ssl_config *conf;
136
137 void SSLi_init(void)
138 {
139         char verstring[12];
140         int rc;
141
142         initCert();
143         initKey();
144
145         /* Initialize random number generator */
146 #ifdef USE_MBEDTLS_HAVEGE
147     mbedtls_havege_init(&hs);
148 #else
149     urandom_fd = open("/dev/urandom", O_RDONLY);
150     if (urandom_fd < 0)
151             Log_fatal("Cannot open /dev/urandom");
152 #endif
153
154         /* Initialize config */
155         conf = Memory_safeCalloc(1, sizeof(mbedtls_ssl_config));
156
157         if (!conf)
158                 Log_fatal("Out of memory");
159
160         mbedtls_ssl_config_init(conf);
161
162         if((rc = mbedtls_ssl_config_defaults(conf,
163                         MBEDTLS_SSL_IS_SERVER,
164                         MBEDTLS_SSL_TRANSPORT_STREAM,
165                         MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
166                 Log_fatal("mbedtls_ssl_config_defaults returned %d", rc);
167
168         mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
169 #ifdef USE_MBEDTLS_HAVEGE
170         mbedtls_ssl_conf_rng(conf, HAVEGE_RAND, &hs);
171 #else
172         mbedtls_ssl_conf_rng(conf, urandom_bytes, NULL);
173 #endif
174         mbedtls_ssl_conf_dbg(conf, pssl_debug, NULL);
175
176         mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
177
178         mbedtls_ssl_conf_ciphersuites(conf, (const int*)&ciphers);
179
180         mbedtls_ssl_conf_ca_chain(conf, &certificate, NULL);
181
182         if((rc = mbedtls_ssl_conf_own_cert(conf, &certificate, &key)) != 0)
183                 Log_fatal("mbedtls_ssl_conf_own_cert returned %d", rc);
184
185 #ifdef MBEDTLS_VERSION_FEATURES
186     mbedtls_version_get_string(verstring);
187     Log_info("mbedTLS library version %s initialized", verstring);
188 #else
189     Log_info("mbedTLS library initialized");
190 #endif
191 }
192
193 void SSLi_deinit(void)
194 {
195         mbedtls_ssl_config_free(conf);
196         free(conf);
197         mbedtls_x509_crt_free(&certificate);
198         mbedtls_pk_free(&key);
199 }
200
201 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
202 {
203         mbedtls_x509_crt const *cert;
204         cert = mbedtls_ssl_get_peer_cert(ssl);
205
206         if (!cert) {
207                 return false;
208         }
209         mbedtls_sha1(cert->raw.p, cert->raw.len, hash);
210         return true;
211 }
212
213 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
214 {
215         mbedtls_ssl_context *ssl;
216         mbedtls_ssl_session *ssn;
217         int rc;
218
219         ssl = Memory_safeCalloc(1, sizeof(mbedtls_ssl_context));
220         ssn = Memory_safeCalloc(1, sizeof(mbedtls_ssl_session));
221
222         if (!ssl || !ssn)
223                 Log_fatal("Out of memory");
224
225         mbedtls_ssl_init(ssl);
226         mbedtls_ssl_set_bio(ssl, fd, mbedtls_net_send, mbedtls_net_recv, NULL);
227         mbedtls_ssl_set_session(ssl, ssn);
228
229         if((rc = mbedtls_ssl_setup(ssl, conf)) != 0)
230                 Log_fatal("mbedtls_ssl_setup returned %d", rc);
231
232         return ssl;
233 }
234
235 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
236 {
237         int rc;
238
239         rc = mbedtls_ssl_handshake(ssl);
240         if (rc != 0) {
241                 if (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE) {
242                         return 0;
243                 } else if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { /* Allow this (selfsigned etc) */
244                         return 0;
245                 } else {
246                         Log_warn("SSL handshake failed: %d", rc);
247                         return -1;
248                 }
249         }
250         *SSLready = true;
251         return 0;
252 }
253
254 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
255 {
256         int rc;
257
258         rc = mbedtls_ssl_read(ssl, buf, len);
259         if (rc == MBEDTLS_ERR_SSL_WANT_READ)
260                 return SSLI_ERROR_WANT_READ;
261         return rc;
262 }
263
264 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
265 {
266         int rc;
267
268         rc = mbedtls_ssl_write(ssl, buf, len);
269         if (rc == MBEDTLS_ERR_SSL_WANT_WRITE)
270                 return SSLI_ERROR_WANT_WRITE;
271         return rc;
272 }
273
274 int SSLi_get_error(SSL_handle_t *ssl, int code)
275 {
276         return code;
277 }
278
279 bool_t SSLi_data_pending(SSL_handle_t *ssl)
280 {
281         return mbedtls_ssl_get_bytes_avail(ssl) > 0;
282 }
283
284 void SSLi_shutdown(SSL_handle_t *ssl)
285 {
286         mbedtls_ssl_close_notify(ssl);
287 }
288
289 void SSLi_free(SSL_handle_t *ssl)
290 {
291         Log_debug("SSLi_free");
292         mbedtls_ssl_free(ssl);
293         free(ssl);
294 }
295