Fix const-correctness warnings in OpenSSL's SSLi_init().
[umurmur.git] / src / ssli_openssl.c
1 /* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
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
8    are met:
9
10    - Redistributions of source code must retain the above copyright notice,
11      this list of conditions and the following disclaimer.
12    - Redistributions in binary form must reproduce the above copyright notice,
13      this list of conditions and the following disclaimer in the documentation
14      and/or other materials provided with the distribution.
15    - Neither the name of the Developers nor the names of its contributors may
16      be used to endorse or promote products derived from this software without
17      specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <stdlib.h>
32 #include <fcntl.h>
33
34 #include "conf.h"
35 #include "log.h"
36 #include "memory.h"
37 #include "ssl.h"
38
39 /*
40  * OpenSSL interface
41  */
42
43 #include <openssl/x509v3.h>
44 #include <openssl/ssl.h>
45 #include <openssl/err.h>
46 #include <openssl/safestack.h>
47 static X509 *x509;
48 static RSA *rsa;
49 static SSL_CTX *context;
50 static EVP_PKEY *pkey;
51
52 static char const * ciphers = "EECDH+CHACHA20:EECDH+AESGCM:EECDH+AES+TLSv1.2:EECDH+AES:AESGCM:AES:!aNULL:!DHE:!kECDH";
53
54 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
55
56 static int SSL_add_ext(X509 * crt, int nid, char *value) {
57         X509_EXTENSION *ex;
58         X509V3_CTX ctx;
59         X509V3_set_ctx_nodb(&ctx);
60         X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
61         ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
62         if (!ex)
63                 return 0;
64
65         X509_add_ext(crt, ex, -1);
66         X509_EXTENSION_free(ex);
67         return 1;
68 }
69
70 static RSA *SSL_readprivatekey(char *keyfile)
71 {
72         FILE *fp;
73         RSA *rsa;
74
75 /* open the private key file for reading */
76         fp = fopen(keyfile, "r");
77         if (fp == NULL) {
78                 Log_warn("Unable to open the private key file %s for reading.", keyfile);
79                 return NULL;
80         }
81
82 /* allocate memory for the RSA structure */
83         rsa = RSA_new();
84
85         /* assign a callback function for the password */
86
87         /* read a private key from file */
88         if (PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL) <= 0) {
89                 /* error reading the key - check the error stack */
90                 Log_warn("Error trying to read private key.");
91                 RSA_free(rsa);
92                 fclose(fp);
93                 return NULL;
94         }
95         fclose(fp);
96         return rsa;
97 }
98
99 static void SSL_writecert(char *certfile, X509 *x509)
100 {
101         FILE *fp;
102
103         /* open the private key file */
104         fp = fopen(certfile, "w");
105         if (fp == NULL) {
106                 Log_warn("Unable to open the X509 file %s for writing", certfile);
107                 return;
108         }
109         if (PEM_write_X509(fp, x509) == 0) {
110                 Log_warn("Error trying to write X509 info.");
111         }
112         fclose(fp);
113 }
114
115 static void SSL_writekey(char *keyfile, RSA *rsa)
116 {
117         FILE *fp;
118
119         /* open the private key file for reading */
120         fp = fopen(keyfile, "w");
121         if (fp == NULL) {
122                 Log_warn("Unable to open the private key file %s for writing.", keyfile);
123                 return;
124         }
125
126         if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) {
127                 Log_warn("Error trying to write private key");
128         }
129         fclose(fp);
130 }
131
132 static void SSL_initializeCert() {
133
134         char *crt = (char *)getStrConf(CERTIFICATE);
135         char *key = (char *)getStrConf(KEY);
136
137         if (context) {
138                 bool_t did_load_cert = SSL_CTX_use_certificate_chain_file(context, crt);
139                 rsa = SSL_readprivatekey(key);
140
141                 if (!rsa || !did_load_cert) {
142                         Log_info("Generating new server certificate.");
143
144
145                         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
146
147                         x509 = X509_new();
148                         pkey = EVP_PKEY_new();
149                         rsa = RSA_generate_key(4096,RSA_F4,NULL,NULL);
150                         EVP_PKEY_assign_RSA(pkey, rsa);
151
152                         X509_set_version(x509, 2);
153                         ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
154                         X509_gmtime_adj(X509_get_notBefore(x509),0);
155                         X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
156                         X509_set_pubkey(x509, pkey);
157
158                         X509_NAME *name=X509_get_subject_name(x509);
159
160                         X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"Murmur Autogenerated Certificate v2", -1, -1, 0);
161                         X509_set_issuer_name(x509, name);
162                         SSL_add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
163                         SSL_add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
164                         SSL_add_ext(x509, NID_subject_key_identifier, "hash");
165                         SSL_add_ext(x509, NID_netscape_comment, "Generated from umurmur");
166
167                         X509_sign(x509, pkey, EVP_md5());
168
169                         SSL_writecert(crt, x509);
170                         SSL_writekey(key, rsa);
171
172                         SSL_CTX_use_certificate(context, x509);
173                 } else {
174                   pkey = EVP_PKEY_new();
175                   EVP_PKEY_assign_RSA(pkey, rsa);
176                 }
177
178                 SSL_CTX_use_PrivateKey(context, pkey);
179
180         } else {
181                 Log_fatal("Failed to initialize TLS context.");
182         }
183
184 }
185
186 void SSLi_init(void)
187 {
188         SSL *ssl;
189         int i, offset = 0, cipherstringlen = 0;
190         STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
191         const SSL_CIPHER *cipher;
192         char *cipherstring = NULL;
193
194         SSL_library_init();
195         OpenSSL_add_all_algorithms();
196         SSL_load_error_strings();
197         ERR_load_crypto_strings();
198
199         context = SSL_CTX_new(SSLv23_server_method());
200         SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
201         SSL_CTX_set_options(context, SSL_OP_NO_SSLv3);
202         SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
203         if (context == NULL)
204         {
205                 ERR_print_errors_fp(stderr);
206                 abort();
207         }
208
209         SSL_CTX_set_cipher_list(context, ciphers);
210
211         EC_KEY *ecdhkey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
212         SSL_CTX_set_tmp_ecdh(context, ecdhkey);
213         EC_KEY_free(ecdhkey);
214
215         char const * sslCAPath = getStrConf(CAPATH);
216         if(sslCAPath != NULL)
217         {
218                 SSL_CTX_load_verify_locations(context, NULL, sslCAPath);
219         }
220
221         SSL_initializeCert();
222
223         /* Set cipher list */
224         ssl = SSL_new(context);
225         cipherlist = (STACK_OF(SSL_CIPHER) *) SSL_get_ciphers(ssl);
226         cipherlist_new = (STACK_OF(SSL_CIPHER) *) sk_SSL_CIPHER_new_null();
227
228         for ( i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist, i)) != NULL; i++) {
229                 if (SSL_CIPHER_get_bits(cipher, NULL) >= 128) {
230                         sk_SSL_CIPHER_push(cipherlist_new, cipher);
231                 }
232         }
233         Log_debug("List of ciphers:");
234         if (cipherlist_new) {
235                 for (i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
236                         Log_debug("%s", SSL_CIPHER_get_name(cipher));
237                         cipherstringlen += strlen(SSL_CIPHER_get_name(cipher)) + 1;
238                 }
239                 cipherstring = Memory_safeMalloc(1, cipherstringlen + 1);
240                 for (i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
241                         offset += sprintf(cipherstring + offset, "%s:", SSL_CIPHER_get_name(cipher));
242                 }
243         }
244
245         if (cipherlist_new)
246                 sk_SSL_CIPHER_free(cipherlist_new);
247
248         if (!cipherstring || !*cipherstring)
249                 Log_fatal("No suitable ciphers found!");
250
251         if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
252                 Log_fatal("Failed to set cipher list!");
253
254         free(cipherstring);
255
256         SSL_CTX_set_verify(context, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
257                            verify_callback);
258
259         SSL_free(ssl);
260         Log_info("OpenSSL library initialized");
261
262 }
263
264 void SSLi_deinit(void)
265 {
266         SSL_CTX_free(context);
267         EVP_cleanup();
268 }
269
270 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
271 {
272         int rc;
273         rc = SSL_accept(ssl);
274         if (rc < 0) {
275                 if (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ ||
276                         SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE) {
277                         Log_debug("SSL not ready");
278                         return 0;
279                 } else {
280                         Log_warn("SSL error: %s", ERR_error_string(SSL_get_error(ssl, rc), NULL));
281                         return -1;
282                 }
283         }
284         *SSLready = true;
285         return 0;
286 }
287
288 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
289 {
290         SSL *ssl;
291
292         *SSLready = false;
293         ssl = SSL_new(context);
294         SSL_set_fd(ssl, *fd);
295         if (SSLi_nonblockaccept(ssl, SSLready) < 0) {
296                 SSL_free(ssl);
297                 return NULL;
298         }
299         return ssl;
300 }
301
302 /* Create SHA1 of last certificate in the peer's chain. */
303 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
304 {
305         X509 *x509;
306         uint8_t *buf, *p;
307         int len;
308
309         x509 = SSL_get_peer_certificate(ssl);
310         if (!x509) {
311                 return false;
312         }
313
314         len = i2d_X509(x509, NULL);
315         buf = Memory_safeMalloc(1, len);
316
317         p = buf;
318         i2d_X509(x509, &p);
319
320         SHA1(buf, len, hash);
321         free(buf);
322         return true;
323 }
324
325 void SSLi_closeconnection(SSL_handle_t *ssl)
326 {
327         SSL_free(ssl);
328 }
329
330 void SSLi_shutdown(SSL_handle_t *ssl)
331 {
332         SSL_shutdown(ssl);
333 }
334
335 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
336 {
337         return SSL_read(ssl, buf, len);
338 }
339
340 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
341 {
342         return SSL_write(ssl, buf, len);
343 }
344
345 int SSLi_get_error(SSL_handle_t *ssl, int code)
346 {
347         return SSL_get_error(ssl, code);
348 }
349
350 bool_t SSLi_data_pending(SSL_handle_t *ssl)
351 {
352         return SSL_pending(ssl);
353 }
354
355 void SSLi_free(SSL_handle_t *ssl)
356 {
357         SSL_free(ssl);
358 }
359
360 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
361 {
362         char    buf[256];
363         X509   *err_cert;
364         int     err, depth;
365         SSL    *ssl;
366
367     err_cert = X509_STORE_CTX_get_current_cert(ctx);
368     err = X509_STORE_CTX_get_error(ctx);
369     depth = X509_STORE_CTX_get_error_depth(ctx);
370
371     ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
372     X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
373
374     if (depth > 5) {
375         preverify_ok = 0;
376         err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
377         X509_STORE_CTX_set_error(ctx, err);
378     }
379     if (!preverify_ok) {
380             Log_warn("SSL: verify error:num=%d:%s:depth=%d:%s\n", err,
381                      X509_verify_cert_error_string(err), depth, buf);
382     }
383     /*
384      * At this point, err contains the last verification error. We can use
385      * it for something special
386      */
387     if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
388             X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
389             Log_warn("issuer= %s", buf);
390     }
391     return 1;
392 }