• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ustream-ssl/ustream-openssl.c

  1 /*
  2  * ustream-ssl - library for SSL over ustream
  3  *
  4  * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
  5  *
  6  * Permission to use, copy, modify, and/or distribute this software for any
  7  * purpose with or without fee is hereby granted, provided that the above
  8  * copyright notice and this permission notice appear in all copies.
  9  *
 10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 17  */
 18 
 19 #include <limits.h>
 20 #include <string.h>
 21 #include <ctype.h>
 22 #include <arpa/inet.h>
 23 #include "ustream-ssl.h"
 24 #include "ustream-internal.h"
 25 
 26 #if !defined(HAVE_WOLFSSL)
 27 #include <openssl/x509v3.h>
 28 #endif
 29 
 30 #if defined(HAVE_WOLFSSL) && defined(DEBUG)
 31 #include <wolfssl/test.h>
 32 #endif
 33 
 34 /* Ciphersuite preference:
 35  * - for server, no weak ciphers are used if you use an ECDSA key.
 36  * - forward-secret (pfs), authenticated (AEAD) ciphers are at the top:
 37  *      chacha20-poly1305, the fastest in software, 256-bits
 38  *      aes128-gcm, 128-bits
 39  *      aes256-gcm, 256-bits
 40  * - key exchange: prefer ECDHE, then DHE (client only)
 41  * - forward-secret ECDSA CBC ciphers (client-only)
 42  * - forward-secret RSA CBC ciphers
 43  * - non-pfs ciphers
 44  *      aes128, aes256, 3DES(client only)
 45  */
 46 
 47 #ifdef WOLFSSL_SSL_H
 48 # define top_ciphers                                                    \
 49                                 "TLS13-CHACHA20-POLY1305-SHA256:"       \
 50                                 "TLS13-AES128-GCM-SHA256:"              \
 51                                 "TLS13-AES256-GCM-SHA384:"              \
 52                                 ecdhe_aead_ciphers
 53 #else
 54 # define tls13_ciphersuites     "TLS_CHACHA20_POLY1305_SHA256:"         \
 55                                 "TLS_AES_128_GCM_SHA256:"               \
 56                                 "TLS_AES_256_GCM_SHA384"
 57 
 58 # define top_ciphers                                                    \
 59                                 ecdhe_aead_ciphers
 60 #endif
 61 
 62 #define ecdhe_aead_ciphers                                              \
 63                                 "ECDHE-ECDSA-CHACHA20-POLY1305:"        \
 64                                 "ECDHE-ECDSA-AES128-GCM-SHA256:"        \
 65                                 "ECDHE-ECDSA-AES256-GCM-SHA384:"        \
 66                                 "ECDHE-RSA-CHACHA20-POLY1305:"          \
 67                                 "ECDHE-RSA-AES128-GCM-SHA256:"          \
 68                                 "ECDHE-RSA-AES256-GCM-SHA384"
 69 
 70 #define dhe_aead_ciphers                                                \
 71                                 "DHE-RSA-CHACHA20-POLY1305:"            \
 72                                 "DHE-RSA-AES128-GCM-SHA256:"            \
 73                                 "DHE-RSA-AES256-GCM-SHA384"
 74 
 75 #define ecdhe_ecdsa_cbc_ciphers                                         \
 76                                 "ECDHE-ECDSA-AES128-SHA:"               \
 77                                 "ECDHE-ECDSA-AES256-SHA"
 78 
 79 #define ecdhe_rsa_cbc_ciphers                                           \
 80                                 "ECDHE-RSA-AES128-SHA:"                 \
 81                                 "ECDHE-RSA-AES256-SHA"
 82 
 83 #define dhe_cbc_ciphers                                                 \
 84                                 "DHE-RSA-AES128-SHA:"                   \
 85                                 "DHE-RSA-AES256-SHA:"                   \
 86                                 "DHE-DES-CBC3-SHA"
 87 
 88 #define non_pfs_aes                                                     \
 89                                 "AES128-GCM-SHA256:"                    \
 90                                 "AES256-GCM-SHA384:"                    \
 91                                 "AES128-SHA:"                           \
 92                                 "AES256-SHA"
 93 
 94 #define server_cipher_list                                              \
 95                                 top_ciphers ":"                         \
 96                                 ecdhe_rsa_cbc_ciphers ":"               \
 97                                 non_pfs_aes
 98 
 99 #define client_cipher_list                                              \
100                                 top_ciphers ":"                         \
101                                 dhe_aead_ciphers ":"                    \
102                                 ecdhe_ecdsa_cbc_ciphers ":"             \
103                                 ecdhe_rsa_cbc_ciphers ":"               \
104                                 dhe_cbc_ciphers ":"                     \
105                                 non_pfs_aes ":"                         \
106                                 "DES-CBC3-SHA"
107 
108 __hidden struct ustream_ssl_ctx *
109 __ustream_ssl_context_new(bool server)
110 {
111         struct ustream_ssl_ctx *ctx;
112         const void *m;
113         SSL_CTX *c;
114 
115 #if OPENSSL_VERSION_NUMBER < 0x10100000L
116         static bool _init = false;
117 
118         if (!_init) {
119                 SSL_load_error_strings();
120                 SSL_library_init();
121                 _init = true;
122         }
123 # ifndef TLS_server_method
124 #  define TLS_server_method SSLv23_server_method
125 # endif
126 # ifndef TLS_client_method
127 #  define TLS_client_method SSLv23_client_method
128 # endif
129 #endif
130 
131         if (server) {
132                 m = TLS_server_method();
133         } else
134                 m = TLS_client_method();
135 
136         c = SSL_CTX_new((void *) m);
137         if (!c)
138                 return NULL;
139 
140         ctx = calloc(1, sizeof(*ctx));
141         if (!ctx) {
142                 SSL_CTX_free(c);
143                 return NULL;
144         }
145         ctx->ssl = c;
146 
147 #if defined(HAVE_WOLFSSL)
148         if (server)
149                 SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
150         else
151                 SSL_CTX_set_verify(c, SSL_VERIFY_PEER, NULL);
152 #else
153         SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
154 #endif
155 
156         SSL_CTX_set_options(c, SSL_OP_NO_COMPRESSION | SSL_OP_SINGLE_ECDH_USE |
157                                SSL_OP_CIPHER_SERVER_PREFERENCE);
158 
159         /* Blocked writes are buffered by the ustream core and retried from the
160          * buffers instead of the original caller address. Limit the write
161          * state pending inside the SSL library to a single record and allow
162          * the retry to come from a different address.
163          */
164 #ifdef SSL_MODE_ENABLE_PARTIAL_WRITE
165 # ifdef SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
166         SSL_CTX_set_mode(c, SSL_MODE_ENABLE_PARTIAL_WRITE |
167                             SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
168 # else
169         SSL_CTX_set_mode(c, SSL_MODE_ENABLE_PARTIAL_WRITE);
170 # endif
171 #endif
172 #if defined(SSL_CTX_set_ecdh_auto) && OPENSSL_VERSION_NUMBER < 0x10100000L
173         SSL_CTX_set_ecdh_auto(c, 1);
174 #elif OPENSSL_VERSION_NUMBER >= 0x10101000L
175         SSL_CTX_set_ciphersuites(c, tls13_ciphersuites);
176 #endif
177         if (server) {
178 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
179                 SSL_CTX_set_min_proto_version(c, TLS1_2_VERSION);
180 #else
181                 SSL_CTX_set_options(c, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 |
182                                        SSL_OP_NO_TLSv1_1);
183 #endif
184 #if defined(HAVE_WOLFSSL)
185                 SSL_CTX_set_options(c, SSL_AD_NO_RENEGOTIATION);
186 #else
187                 SSL_CTX_set_options(c, SSL_OP_NO_RENEGOTIATION);
188 #endif
189 
190                 SSL_CTX_set_cipher_list(c, server_cipher_list);
191         } else {
192                 SSL_CTX_set_cipher_list(c, client_cipher_list);
193         }
194         SSL_CTX_set_quiet_shutdown(c, 1);
195 
196         return ctx;
197 }
198 
199 __hidden int __ustream_ssl_add_ca_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
200 {
201         int ret;
202 
203         ret = SSL_CTX_load_verify_locations(ctx->ssl, file, NULL);
204         if (ret < 1)
205                 return -1;
206 
207         return 0;
208 }
209 
210 __hidden int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
211 {
212         int ret;
213 
214         ret = SSL_CTX_use_certificate_chain_file(ctx->ssl, file);
215         if (ret < 1)
216                 ret = SSL_CTX_use_certificate_file(ctx->ssl, file, SSL_FILETYPE_ASN1);
217 
218         if (ret < 1)
219                 return -1;
220 
221         return 0;
222 }
223 
224 __hidden int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char *file)
225 {
226         int ret;
227 
228         ret = SSL_CTX_use_PrivateKey_file(ctx->ssl, file, SSL_FILETYPE_PEM);
229         if (ret < 1)
230                 ret = SSL_CTX_use_PrivateKey_file(ctx->ssl, file, SSL_FILETYPE_ASN1);
231 
232         if (ret < 1)
233                 return -1;
234 
235         return 0;
236 }
237 
238 __hidden int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *ciphers)
239 {
240         int ret = SSL_CTX_set_cipher_list(ctx->ssl, ciphers);
241 
242         if (ret == 0)
243                 return -1;
244 
245         return 0;
246 }
247 
248 __hidden int __ustream_ssl_set_require_validation(struct ustream_ssl_ctx *ctx, bool require)
249 {
250         int mode = SSL_VERIFY_PEER;
251 
252         if (!require)
253                 mode = SSL_VERIFY_NONE;
254 
255         SSL_CTX_set_verify(ctx->ssl, mode, NULL);
256 
257         return 0;
258 }
259 
260 __hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx)
261 {
262         SSL_CTX_free(ctx->ssl);
263         if (ctx->debug_bio)
264                 BIO_free(ctx->debug_bio);
265         free(ctx);
266 }
267 
268 __hidden void __ustream_ssl_session_free(struct ustream_ssl *us)
269 {
270         SSL_shutdown(us->ssl);
271         SSL_free(us->ssl);
272 }
273 
274 static void ustream_ssl_error(struct ustream_ssl *us, int ret)
275 {
276         unsigned long err = ERR_peek_error();
277 
278         /* The error member is passed to ERR_error_string(), which can only
279          * decode packed error queue codes, not SSL_get_error() class codes.
280          * Keep the class code when the queue is empty or the code does not
281          * survive the round trip through the int member.
282          */
283         if (err && err <= INT_MAX)
284                 us->error = err;
285         else
286                 us->error = ret;
287 
288         uloop_timeout_set(&us->error_timer, 0);
289 }
290 
291 #ifndef WOLFSSL_OPENSSL_H_
292 static bool peer_cn_is_ip_addr(const char *peer_cn)
293 {
294         struct in6_addr addr;
295 
296         return inet_pton(AF_INET, peer_cn, &addr) == 1 ||
297                inet_pton(AF_INET6, peer_cn, &addr) == 1;
298 }
299 #endif
300 
301 static bool ustream_ssl_verify_cn(struct ustream_ssl *us, X509 *cert)
302 {
303         int ret;
304 
305         if (!us->peer_cn)
306                 return false;
307 
308 # ifndef WOLFSSL_OPENSSL_H_
309         if (peer_cn_is_ip_addr(us->peer_cn))
310                 ret = X509_check_ip_asc(cert, us->peer_cn, 0);
311         else
312                 ret = X509_check_host(cert, us->peer_cn, 0, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS, NULL);
313 # else
314         ret = wolfSSL_X509_check_host(cert, us->peer_cn, 0, 0, NULL);
315 # endif
316         return ret == 1;
317 }
318 
319 static void ustream_ssl_verify_cert(struct ustream_ssl *us)
320 {
321         void *ssl = us->ssl;
322         X509 *cert;
323         int res;
324 
325 #if defined(HAVE_WOLFSSL) && defined(DEBUG)
326         showPeer(ssl);
327 #endif
328 
329         res = SSL_get_verify_result(ssl);
330         if (res != X509_V_OK) {
331                 if (us->notify_verify_error)
332                         us->notify_verify_error(us, res, X509_verify_cert_error_string(res));
333                 return;
334         }
335 
336 #if defined(HAVE_WOLFSSL)
337         cert = SSL_get_peer_certificate(ssl);
338 #else
339         cert = SSL_get1_peer_certificate(ssl);
340 #endif
341         if (!cert)
342                 return;
343 
344         us->valid_cert = true;
345         us->valid_cn = ustream_ssl_verify_cn(us, cert);
346 
347         X509_free(cert);
348 }
349 
350 #ifdef WOLFSSL_SSL_H
351 static bool handle_wolfssl_asn_error(struct ustream_ssl *us, int r)
352 {
353         switch (r) {
354         case ASN_PARSE_E:
355         case ASN_VERSION_E:
356         case ASN_GETINT_E:
357         case ASN_RSA_KEY_E:
358         case ASN_OBJECT_ID_E:
359         case ASN_TAG_NULL_E:
360         case ASN_EXPECT_0_E:
361         case ASN_BITSTR_E:
362         case ASN_UNKNOWN_OID_E:
363         case ASN_DATE_SZ_E:
364         case ASN_BEFORE_DATE_E:
365         case ASN_AFTER_DATE_E:
366         case ASN_SIG_OID_E:
367         case ASN_TIME_E:
368         case ASN_INPUT_E:
369         case ASN_SIG_CONFIRM_E:
370         case ASN_SIG_HASH_E:
371         case ASN_SIG_KEY_E:
372         case ASN_DH_KEY_E:
373 #if LIBWOLFSSL_VERSION_HEX < 0x05000000
374         case ASN_NTRU_KEY_E:
375 #endif
376         case ASN_CRIT_EXT_E:
377         case ASN_ALT_NAME_E:
378         case ASN_NO_PEM_HEADER:
379         case ASN_ECC_KEY_E:
380         case ASN_NO_SIGNER_E:
381         case ASN_CRL_CONFIRM_E:
382         case ASN_CRL_NO_SIGNER_E:
383         case ASN_OCSP_CONFIRM_E:
384         case ASN_NAME_INVALID_E:
385         case ASN_NO_SKID:
386         case ASN_NO_AKID:
387         case ASN_NO_KEYUSAGE:
388         case ASN_COUNTRY_SIZE_E:
389         case ASN_PATHLEN_SIZE_E:
390         case ASN_PATHLEN_INV_E:
391         case ASN_SELF_SIGNED_E:
392                 if (us->notify_verify_error)
393                         us->notify_verify_error(us, r, wc_GetErrorString(r));
394                 return true;
395         }
396 
397         return false;
398 }
399 #endif
400 
401 __hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us)
402 {
403         void *ssl = us->ssl;
404         int r;
405 
406         ERR_clear_error();
407 
408         if (us->server)
409                 r = SSL_accept(ssl);
410         else
411                 r = SSL_connect(ssl);
412 
413         if (r == 1) {
414                 ustream_ssl_verify_cert(us);
415                 return U_SSL_OK;
416         }
417 
418         r = SSL_get_error(ssl, r);
419         if (r == SSL_ERROR_WANT_READ || r == SSL_ERROR_WANT_WRITE)
420                 return U_SSL_PENDING;
421 
422 #ifdef WOLFSSL_SSL_H
423         if (handle_wolfssl_asn_error(us, r))
424                 return U_SSL_OK;
425 #endif
426 
427         ustream_ssl_error(us, r);
428         return U_SSL_ERROR;
429 }
430 
431 __hidden int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len)
432 {
433         void *ssl = us->ssl;
434         int ret;
435 
436         ERR_clear_error();
437 
438         ret = SSL_write(ssl, buf, len);
439 
440         if (ret < 0) {
441                 int err = SSL_get_error(ssl, ret);
442                 if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
443                         return 0;
444 
445                 ustream_ssl_error(us, err);
446                 return -1;
447         }
448 
449         return ret;
450 }
451 
452 __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len)
453 {
454         int ret;
455 
456         ERR_clear_error();
457 
458         ret = SSL_read(us->ssl, buf, len);
459 
460         if (ret < 0) {
461                 ret = SSL_get_error(us->ssl, ret);
462                 if (ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_WANT_WRITE)
463                         return U_SSL_PENDING;
464 
465                 ustream_ssl_error(us, ret);
466                 return U_SSL_ERROR;
467         }
468 
469         return ret;
470 }
471 
472 #ifndef WOLFSSL_SSL_H
473 static long
474 debug_cb(BIO *bio, int cmd, const char *argp, size_t len, int argi, long argl,
475          int ret, size_t *processed)
476 {
477         struct ustream_ssl_ctx *ctx = (void *)BIO_get_callback_arg(bio);
478         char buf[256];
479         char *str, *sep;
480         ssize_t cur_len;
481 
482         if (cmd != (BIO_CB_WRITE|BIO_CB_RETURN))
483             goto out;
484 
485         while (1) {
486                 cur_len = BIO_get_mem_data(bio, (void *)&str);
487                 if (!cur_len)
488                         break;
489 
490                 sep = memchr(str, '\n', cur_len);
491                 if (!sep)
492                         break;
493 
494                 cur_len = sep + 1 - str;
495                 if (cur_len >= (ssize_t)sizeof(buf))
496                         cur_len = sizeof(buf) - 1;
497 
498                 cur_len = BIO_read(bio, buf, cur_len);
499                 if (cur_len <= 1)
500                         break;
501 
502                 cur_len--;
503                 buf[cur_len] = 0;
504                 if (ctx->debug_cb)
505                         ctx->debug_cb(ctx->debug_cb_priv, 1, buf);
506         }
507 
508 out:
509         return ret;
510 }
511 #endif
512 
513 __hidden void __ustream_ssl_set_debug(struct ustream_ssl_ctx *ctx, int level,
514                                       ustream_ssl_debug_cb cb, void *cb_priv)
515 {
516 #ifndef WOLFSSL_SSL_H
517         if (!ctx->debug_bio)
518                 ctx->debug_bio = BIO_new(BIO_s_mem());
519         if (!ctx->debug_bio)
520                 return;
521 
522         ctx->debug_cb = cb;
523         ctx->debug_cb_priv = cb_priv;
524         SSL_CTX_set_msg_callback(ctx->ssl, SSL_trace);
525         SSL_CTX_set_msg_callback_arg(ctx->ssl, ctx->debug_bio);
526 
527         BIO_set_callback_ex(ctx->debug_bio, debug_cb);
528         BIO_set_callback_arg(ctx->debug_bio, (void *)ctx);
529 #endif
530 }
531 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt