c826e4e9bace45ccf5899528fe56f5e85952e515
[project/ustream-ssl.git] / 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 "ustream-ssl.h"
20 #include "ustream-internal.h"
21
22 __hidden struct ustream_ssl_ctx *
23 __ustream_ssl_context_new(bool server)
24 {
25 static bool _init = false;
26 const void *m;
27 SSL_CTX *c;
28
29 if (!_init) {
30 SSL_load_error_strings();
31 SSL_library_init();
32 _init = true;
33 }
34
35 #ifdef CYASSL_OPENSSL_H_
36 if (server)
37 m = SSLv23_server_method();
38 else
39 m = SSLv23_client_method();
40 #else
41 if (server)
42 m = TLSv1_server_method();
43 else
44 m = TLSv1_client_method();
45 #endif
46
47 c = SSL_CTX_new((void *) m);
48 if (!c)
49 return NULL;
50
51 if (server)
52 SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL);
53
54 return (void *) c;
55 }
56
57 __hidden int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char *file)
58 {
59 int ret;
60
61 ret = SSL_CTX_use_certificate_file((void *) ctx, file, SSL_FILETYPE_PEM);
62 if (ret < 1)
63 ret = SSL_CTX_use_certificate_file((void *) ctx, file, SSL_FILETYPE_ASN1);
64
65 if (ret < 1)
66 return -1;
67
68 return 0;
69 }
70
71 __hidden int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char *file)
72 {
73 int ret;
74
75 ret = SSL_CTX_use_PrivateKey_file((void *) ctx, file, SSL_FILETYPE_PEM);
76 if (ret < 1)
77 ret = SSL_CTX_use_PrivateKey_file((void *) ctx, file, SSL_FILETYPE_ASN1);
78
79 if (ret < 1)
80 return -1;
81
82 return 0;
83 }
84
85 __hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx)
86 {
87 SSL_CTX_free((void *) ctx);
88 }
89
90 static void ustream_ssl_error(struct ustream_ssl *us, int ret)
91 {
92 us->error = ret;
93 uloop_timeout_set(&us->error_timer, 0);
94 }
95
96 __hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us)
97 {
98 void *ssl = us->ssl;
99 int r;
100
101 if (us->server)
102 r = SSL_accept(ssl);
103 else
104 r = SSL_connect(ssl);
105
106 if (r == 1)
107 return U_SSL_OK;
108
109 r = SSL_get_error(ssl, r);
110 if (r == SSL_ERROR_WANT_READ || r == SSL_ERROR_WANT_WRITE)
111 return U_SSL_PENDING;
112
113 ustream_ssl_error(us, r);
114 return U_SSL_ERROR;
115 }
116
117 __hidden int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len)
118 {
119 void *ssl = us->ssl;
120 int ret = SSL_write(ssl, buf, len);
121
122 if (ret < 0) {
123 int err = SSL_get_error(ssl, ret);
124 if (err == SSL_ERROR_WANT_WRITE)
125 return 0;
126
127 ustream_ssl_error(us, err);
128 return -1;
129 }
130
131 return ret;
132 }
133
134 __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len)
135 {
136 int ret = SSL_read(us->ssl, buf, len);
137
138 if (ret < 0) {
139 ret = SSL_get_error(us->ssl, ret);
140 if (ret == SSL_ERROR_WANT_READ)
141 return U_SSL_PENDING;
142
143 ustream_ssl_error(us, ret);
144 return U_SSL_ERROR;
145 }
146
147 return ret;
148 }
149