2 * ustream-ssl - library for SSL over ustream
4 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
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.
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.
21 #include <openssl/ssl.h>
22 #include <openssl/err.h>
24 #include <libubox/ustream.h>
25 #include "ustream-io.h"
26 #include "ustream-ssl.h"
28 static void ssl_init(void)
30 static bool _init
= false;
35 SSL_load_error_strings();
41 static void ustream_ssl_error_cb(struct uloop_timeout
*t
)
43 struct ustream_ssl
*us
= container_of(t
, struct ustream_ssl
, error_timer
);
44 static char buffer
[128];
45 int error
= us
->error
;
48 us
->notify_error(us
, error
, ERR_error_string(us
->error
, buffer
));
51 static void ustream_ssl_error(struct ustream_ssl
*us
, int error
)
54 uloop_timeout_set(&us
->error_timer
, 0);
57 static void ustream_ssl_check_conn(struct ustream_ssl
*us
)
61 if (us
->connected
|| us
->error
)
65 ret
= SSL_accept(us
->ssl
);
67 ret
= SSL_connect(us
->ssl
);
71 if (us
->notify_connected
)
72 us
->notify_connected(us
);
76 ret
= SSL_get_error(us
->ssl
, ret
);
77 if (ret
== SSL_ERROR_WANT_READ
|| ret
== SSL_ERROR_WANT_WRITE
)
80 ustream_ssl_error(us
, ret
);
83 static void ustream_ssl_notify_read(struct ustream
*s
, int bytes
)
85 struct ustream_ssl
*us
= container_of(s
->next
, struct ustream_ssl
, stream
);
89 ustream_ssl_check_conn(us
);
90 if (!us
->connected
|| us
->error
)
93 buf
= ustream_reserve(&us
->stream
, 1, &len
);
98 ret
= SSL_read(us
->ssl
, buf
, len
);
100 ret
= SSL_get_error(us
->ssl
, ret
);
102 if (ret
== SSL_ERROR_WANT_READ
)
105 ustream_ssl_error(us
, ret
);
109 us
->stream
.eof
= true;
110 ustream_state_change(&us
->stream
);
120 ustream_fill_read(&us
->stream
, wr
);
123 static void ustream_ssl_notify_write(struct ustream
*s
, int bytes
)
125 struct ustream_ssl
*us
= container_of(s
->next
, struct ustream_ssl
, stream
);
127 ustream_ssl_check_conn(us
);
128 ustream_write_pending(s
->next
);
131 static void ustream_ssl_notify_state(struct ustream
*s
)
133 s
->next
->write_error
= true;
134 ustream_state_change(s
->next
);
137 static int ustream_ssl_write(struct ustream
*s
, const char *buf
, int len
, bool more
)
139 struct ustream_ssl
*us
= container_of(s
, struct ustream_ssl
, stream
);
142 if (!us
->connected
|| us
->error
)
145 if (us
->conn
->w
.data_bytes
)
148 ret
= SSL_write(us
->ssl
, buf
, len
);
150 int err
= SSL_get_error(us
->ssl
, ret
);
151 if (err
== SSL_ERROR_WANT_WRITE
)
158 static void ustream_ssl_set_read_blocked(struct ustream
*s
)
160 struct ustream_ssl
*us
= container_of(s
, struct ustream_ssl
, stream
);
162 ustream_set_read_blocked(us
->conn
, !!s
->read_blocked
);
165 static void ustream_ssl_free(struct ustream
*s
)
167 struct ustream_ssl
*us
= container_of(s
, struct ustream_ssl
, stream
);
170 us
->conn
->next
= NULL
;
171 us
->conn
->notify_read
= NULL
;
172 us
->conn
->notify_write
= NULL
;
173 us
->conn
->notify_state
= NULL
;
176 uloop_timeout_cancel(&us
->error_timer
);
177 SSL_shutdown(us
->ssl
);
182 us
->connected
= false;
186 static void ustream_ssl_stream_init(struct ustream_ssl
*us
)
188 struct ustream
*conn
= us
->conn
;
189 struct ustream
*s
= &us
->stream
;
191 conn
->notify_read
= ustream_ssl_notify_read
;
192 conn
->notify_write
= ustream_ssl_notify_write
;
193 conn
->notify_state
= ustream_ssl_notify_state
;
195 s
->free
= ustream_ssl_free
;
196 s
->write
= ustream_ssl_write
;
197 s
->set_read_blocked
= ustream_ssl_set_read_blocked
;
198 ustream_init_defaults(s
);
201 static void *_ustream_ssl_context_new(bool server
)
208 #ifdef CYASSL_OPENSSL_H_
210 m
= SSLv23_server_method();
212 m
= SSLv23_client_method();
215 m
= TLSv1_server_method();
217 m
= TLSv1_client_method();
220 c
= SSL_CTX_new((void *) m
);
225 SSL_CTX_set_verify(c
, SSL_VERIFY_NONE
, NULL
);
230 static int _ustream_ssl_context_set_crt_file(void *ctx
, const char *file
)
234 ret
= SSL_CTX_use_certificate_file(ctx
, file
, SSL_FILETYPE_PEM
);
236 ret
= SSL_CTX_use_certificate_file(ctx
, file
, SSL_FILETYPE_ASN1
);
244 static int _ustream_ssl_context_set_key_file(void *ctx
, const char *file
)
248 ret
= SSL_CTX_use_PrivateKey_file(ctx
, file
, SSL_FILETYPE_PEM
);
250 ret
= SSL_CTX_use_PrivateKey_file(ctx
, file
, SSL_FILETYPE_ASN1
);
258 static void _ustream_ssl_context_free(void *ctx
)
263 static int _ustream_ssl_init(struct ustream_ssl
*us
, struct ustream
*conn
, void *ctx
, bool server
)
265 us
->error_timer
.cb
= ustream_ssl_error_cb
;
270 us
->ssl
= SSL_new(us
->ctx
);
274 conn
->next
= &us
->stream
;
275 ustream_set_io(ctx
, us
->ssl
, conn
);
276 ustream_ssl_stream_init(us
);
281 const struct ustream_ssl_ops ustream_ssl_ops
= {
282 .context_new
= _ustream_ssl_context_new
,
283 .context_set_crt_file
= _ustream_ssl_context_set_crt_file
,
284 .context_set_key_file
= _ustream_ssl_context_set_key_file
,
285 .context_free
= _ustream_ssl_context_free
,
286 .init
= _ustream_ssl_init
,