• 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 <string.h>
 20 #include <ctype.h>
 21 #include "ustream-ssl.h"
 22 #include "ustream-internal.h"
 23 
 24 #if !defined(HAVE_WOLFSSL)
 25 #include <openssl/x509v3.h>
 26 #endif
 27 
 28 /* Ciphersuite preference:
 29  * - for server, no weak ciphers are used if you use an ECDSA key.
 30  * - forward-secret (pfs), authenticated (AEAD) ciphers are at the top:
 31  *      chacha20-poly1305, the fastest in software, 256-bits
 32  *      aes128-gcm, 128-bits
 33  *      aes256-gcm, 256-bits
 34  * - key exchange: prefer ECDHE, then DHE (client only)
 35  * - forward-secret ECDSA CBC ciphers (client-only)
 36  * - forward-secret RSA CBC ciphers
 37  * - non-pfs ciphers
 38  *      aes128, aes256, 3DES(client only)
 39  */
 40 
 41 #ifdef WOLFSSL_SSL_H
 42 # define top_ciphers                                                    \
 43                                 "TLS13-CHACHA20-POLY1305-SHA256:"       \
 44                                 "TLS13-AES128-GCM-SHA256:"              \
 45                                 "TLS13-AES256-GCM-SHA384:"              \
 46                                 ecdhe_aead_ciphers
 47 #else
 48 # define tls13_ciphersuites     "TLS_CHACHA20_POLY1305_SHA256:"         \
 49                                 "TLS_AES_128_GCM_SHA256:"               \
 50                                 "TLS_AES_256_GCM_SHA384"
 51 
 52 # define top_ciphers                                                    \
 53                                 ecdhe_aead_ciphers
 54 #endif
 55 
 56 #define ecdhe_aead_ciphers                                              \
 57                                 "ECDHE-ECDSA-CHACHA20-POLY1305:"        \
 58                                 "ECDHE-ECDSA-AES128-GCM-SHA256:"        \
 59                                 "ECDHE-ECDSA-AES256-GCM-SHA384:"        \
 60                                 "ECDHE-RSA-CHACHA20-POLY1305:"          \
 61                                 "ECDHE-RSA-AES128-GCM-SHA256:"          \
 62                                 "ECDHE-RSA-AES256-GCM-SHA384"
 63 
 64 #define dhe_aead_ciphers                                                \
 65                                 "DHE-RSA-CHACHA20-POLY1305:"            \
 66                                 "DHE-RSA-AES128-GCM-SHA256:"            \
 67                                 "DHE-RSA-AES256-GCM-SHA384"
 68 
 69 #define ecdhe_ecdsa_cbc_ciphers                                         \
 70                                 "ECDHE-ECDSA-AES128-SHA:"               \
 71                                 "ECDHE-ECDSA-AES256-SHA"
 72 
 73 #define ecdhe_rsa_cbc_ciphers                                           \
 74                                 "ECDHE-RSA-AES128-SHA:"                 \
 75                                 "ECDHE-RSA-AES256-SHA"
 76 
 77 #define dhe_cbc_ciphers                                                 \
 78                                 "DHE-RSA-AES128-SHA:"                   \
 79                                 "DHE-RSA-AES256-SHA:"                   \
 80                                 "DHE-DES-CBC3-SHA"
 81 
 82 #define non_pfs_aes                                                     \
 83                                 "AES128-GCM-SHA256:"                    \
 84                                 "AES256-GCM-SHA384:"                    \
 85                                 "AES128-SHA:"                           \
 86                                 "AES256-SHA"
 87 
 88 #define server_cipher_list                                              \
 89                                 top_ciphers ":"                         \
 90                                 ecdhe_rsa_cbc_ciphers ":"               \
 91                                 non_pfs_aes
 92 
 93 #define client_cipher_list                                              \
 94                                 top_ciphers ":"                         \
 95                                 dhe_aead_ciphers ":"                    \
 96                                 ecdhe_ecdsa_cbc_ciphers ":"             \
 97                                 ecdhe_rsa_cbc_ciphers ":"               \
 98                                 dhe_cbc_ciphers ":"                     \
 99                                 non_pfs_aes ":"                         \
100                                 "DES-CBC3-SHA"
101 
102 __hidden struct ustream_ssl_ctx *
103 __ustream_ssl_context_new(bool server)
104 {
105         const void *m;
106         SSL_CTX *c;
107 
108 #if OPENSSL_VERSION_NUMBER < 0x10100000L
109         static bool _init = false;
110 
111         if (!_init) {
112                 SSL_load_error_strings();
113                 SSL_library_init();
114                 _init = true;
115         }
116 # ifndef TLS_server_method
117 #  define TLS_server_method SSLv23_server_method
118 # endif
119 # ifndef TLS_client_method
120 #  define TLS_client_method SSLv23_client_method
121 # endif
122 #endif
123 
124         if (server) {
125                 m = TLS_server_method();
126         } else
127                 m = TLS_client_method();
128 
129         c = SSL_CTX_new((void *) m);
130         if (!c)
131                 return NULL;
132 
133 #if defined(HAVE_WOLFSSL)
134         if (server)
135                 SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
136         else
137                 SSL_CTX_set_verify(c, SSL_VERIFY_PEER, NULL);
138 #else
139         SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
140 #endif
141 
142         SSL_CTX_set_options(c, SSL_OP_NO_COMPRESSION | SSL_OP_SINGLE_ECDH_USE |
143                                SSL_OP_CIPHER_SERVER_PREFERENCE);
144 #if defined(SSL_CTX_set_ecdh_auto) && OPENSSL_VERSION_NUMBER < 0x10100000L
145         SSL_CTX_set_ecdh_auto(c, 1);
146 #elif OPENSSL_VERSION_NUMBER >= 0x10101000L
147         SSL_CTX_set_ciphersuites(c, tls13_ciphersuites);
148 #endif
149         if (server) {
150 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
151                 SSL_CTX_set_min_proto_version(c, TLS1_2_VERSION);
152 #else
153                 SSL_CTX_set_options(c, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 |
154                                        SSL_OP_NO_TLSv1_1);
155 #endif
156                 SSL_CTX_set_cipher_list(c, server_cipher_list);
157         } else {
158                 SSL_CTX_set_cipher_list(c, client_cipher_list);
159         }
160         SSL_CTX_set_quiet_shutdown(c, 1);
161 
162         return (void *) c;
163 }
164 
165 __hidden int __ustream_ssl_add_ca_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
166 {
167         int ret;
168 
169         ret = SSL_CTX_load_verify_locations((void *) ctx, file, NULL);
170         if (ret < 1)
171                 return -1;
172 
173         return 0;
174 }
175 
176 __hidden int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
177 {
178         int ret;
179 
180         ret = SSL_CTX_use_certificate_chain_file((void *) ctx, file);
181         if (ret < 1)
182                 ret = SSL_CTX_use_certificate_file((void *) ctx, file, SSL_FILETYPE_ASN1);
183 
184         if (ret < 1)
185                 return -1;
186 
187         return 0;
188 }
189 
190 __hidden int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char *file)
191 {
192         int ret;
193 
194         ret = SSL_CTX_use_PrivateKey_file((void *) ctx, file, SSL_FILETYPE_PEM);
195         if (ret < 1)
196                 ret = SSL_CTX_use_PrivateKey_file((void *) ctx, file, SSL_FILETYPE_ASN1);
197 
198         if (ret < 1)
199                 return -1;
200 
201         return 0;
202 }
203 
204 __hidden int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *ciphers)
205 {
206         int ret = SSL_CTX_set_cipher_list((void *) ctx, ciphers);
207 
208         if (ret == 0)
209                 return -1;
210 
211         return 0;
212 }
213 
214 __hidden int __ustream_ssl_set_require_validation(struct ustream_ssl_ctx *ctx, bool require)
215 {
216         int mode = SSL_VERIFY_PEER;
217 
218         if (!require)
219                 mode = SSL_VERIFY_NONE;
220 
221         SSL_CTX_set_verify((void *) ctx, mode, NULL);
222 
223         return 0;
224 }
225 
226 __hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx)
227 {
228         SSL_CTX_free((void *) ctx);
229 }
230 
231 void __ustream_ssl_session_free(void *ssl)
232 {
233         BIO *bio = SSL_get_wbio(ssl);
234         struct bio_ctx *ctx = BIO_get_data(bio);
235 
236         SSL_shutdown(ssl);
237         SSL_free(ssl);
238         if (ctx) {
239                 BIO_meth_free(ctx->meth);
240                 free(ctx);
241         }
242 }
243 
244 static void ustream_ssl_error(struct ustream_ssl *us, int ret)
245 {
246         us->error = ret;
247         uloop_timeout_set(&us->error_timer, 0);
248 }
249 
250 static bool ustream_ssl_verify_cn(struct ustream_ssl *us, X509 *cert)
251 {
252         int ret;
253 
254         if (!us->peer_cn)
255                 return false;
256 
257 # ifndef WOLFSSL_OPENSSL_H_
258         ret = X509_check_host(cert, us->peer_cn, 0, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS, NULL);
259 # else
260         ret = wolfSSL_X509_check_host(cert, us->peer_cn, 0, 0, NULL);
261 # endif
262         return ret == 1;
263 }
264 
265 static void ustream_ssl_verify_cert(struct ustream_ssl *us)
266 {
267         void *ssl = us->ssl;
268         X509 *cert;
269         int res;
270 
271         res = SSL_get_verify_result(ssl);
272         if (res != X509_V_OK) {
273                 if (us->notify_verify_error)
274                         us->notify_verify_error(us, res, X509_verify_cert_error_string(res));
275                 return;
276         }
277 
278         cert = SSL_get_peer_certificate(ssl);
279         if (!cert)
280                 return;
281 
282         us->valid_cert = true;
283         us->valid_cn = ustream_ssl_verify_cn(us, cert);
284 
285         X509_free(cert);
286 }
287 
288 #ifdef WOLFSSL_SSL_H
289 static bool handle_wolfssl_asn_error(struct ustream_ssl *us, int r)
290 {
291         switch (r) {
292         case ASN_PARSE_E:
293         case ASN_VERSION_E:
294         case ASN_GETINT_E:
295         case ASN_RSA_KEY_E:
296         case ASN_OBJECT_ID_E:
297         case ASN_TAG_NULL_E:
298         case ASN_EXPECT_0_E:
299         case ASN_BITSTR_E:
300         case ASN_UNKNOWN_OID_E:
301         case ASN_DATE_SZ_E:
302         case ASN_BEFORE_DATE_E:
303         case ASN_AFTER_DATE_E:
304         case ASN_SIG_OID_E:
305         case ASN_TIME_E:
306         case ASN_INPUT_E:
307         case ASN_SIG_CONFIRM_E:
308         case ASN_SIG_HASH_E:
309         case ASN_SIG_KEY_E:
310         case ASN_DH_KEY_E:
311         case ASN_NTRU_KEY_E:
312         case ASN_CRIT_EXT_E:
313         case ASN_ALT_NAME_E:
314         case ASN_NO_PEM_HEADER:
315         case ASN_ECC_KEY_E:
316         case ASN_NO_SIGNER_E:
317         case ASN_CRL_CONFIRM_E:
318         case ASN_CRL_NO_SIGNER_E:
319         case ASN_OCSP_CONFIRM_E:
320         case ASN_NAME_INVALID_E:
321         case ASN_NO_SKID:
322         case ASN_NO_AKID:
323         case ASN_NO_KEYUSAGE:
324         case ASN_COUNTRY_SIZE_E:
325         case ASN_PATHLEN_SIZE_E:
326         case ASN_PATHLEN_INV_E:
327         case ASN_SELF_SIGNED_E:
328                 if (us->notify_verify_error)
329                         us->notify_verify_error(us, r, wc_GetErrorString(r));
330                 return true;
331         }
332 
333         return false;
334 }
335 #endif
336 
337 __hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us)
338 {
339         void *ssl = us->ssl;
340         int r;
341 
342         ERR_clear_error();
343 
344         if (us->server)
345                 r = SSL_accept(ssl);
346         else
347                 r = SSL_connect(ssl);
348 
349         if (r == 1) {
350                 ustream_ssl_verify_cert(us);
351                 return U_SSL_OK;
352         }
353 
354         r = SSL_get_error(ssl, r);
355         if (r == SSL_ERROR_WANT_READ || r == SSL_ERROR_WANT_WRITE)
356                 return U_SSL_PENDING;
357 
358 #ifdef WOLFSSL_SSL_H
359         if (handle_wolfssl_asn_error(us, r))
360                 return U_SSL_OK;
361 #endif
362 
363         ustream_ssl_error(us, r);
364         return U_SSL_ERROR;
365 }
366 
367 __hidden int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len)
368 {
369         void *ssl = us->ssl;
370         int ret;
371 
372         ERR_clear_error();
373 
374         ret = SSL_write(ssl, buf, len);
375 
376         if (ret < 0) {
377                 int err = SSL_get_error(ssl, ret);
378                 if (err == SSL_ERROR_WANT_WRITE)
379                         return 0;
380 
381                 ustream_ssl_error(us, err);
382                 return -1;
383         }
384 
385         return ret;
386 }
387 
388 __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len)
389 {
390         int ret;
391 
392         ERR_clear_error();
393 
394         ret = SSL_read(us->ssl, buf, len);
395 
396         if (ret < 0) {
397                 ret = SSL_get_error(us->ssl, ret);
398                 if (ret == SSL_ERROR_WANT_READ)
399                         return U_SSL_PENDING;
400 
401                 ustream_ssl_error(us, ret);
402                 return U_SSL_ERROR;
403         }
404 
405         return ret;
406 }
407 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt