From f48abdecd43435809777629e20a257448a68a578 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 4 Feb 2013 17:41:54 +0100 Subject: [PATCH] split cyassl and openssl sources, add ssl library abstraction Signed-off-by: Felix Fietkau --- CMakeLists.txt | 6 +- ustream-internal.h | 41 +++++++ ustream-io-cyassl.c | 70 ++++++++++++ ustream-io.c => ustream-io-openssl.c | 56 +--------- ustream-openssl.c | 148 +++++++++++++++++++++++++ ustream-io.h => ustream-openssl.h | 21 +++- ustream-ssl.c | 156 ++++----------------------- ustream-ssl.h | 2 + 8 files changed, 307 insertions(+), 193 deletions(-) create mode 100644 ustream-internal.h create mode 100644 ustream-io-cyassl.c rename ustream-io.c => ustream-io-openssl.c (68%) create mode 100644 ustream-openssl.c rename ustream-io.h => ustream-openssl.h (70%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f39ca23..6af1750 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,13 +10,15 @@ IF(APPLE) LINK_DIRECTORIES(/opt/local/lib) ENDIF() -IF (CYASSL) +IF(CYASSL) + SET(SSL_SRC ustream-io-cyassl.c ustream-openssl.c) SET(SSL_LIB cyassl m) ELSE() + SET(SSL_SRC ustream-io-openssl.c ustream-openssl.c) SET(SSL_LIB crypto ssl) ENDIF() -ADD_LIBRARY(ustream-ssl SHARED ustream-ssl.c ustream-io.c) +ADD_LIBRARY(ustream-ssl SHARED ustream-ssl.c ${SSL_SRC}) TARGET_LINK_LIBRARIES(ustream-ssl ubox ${SSL_LIB}) ADD_EXECUTABLE(ustream-example ustream-example.c) diff --git a/ustream-internal.h b/ustream-internal.h new file mode 100644 index 0000000..40f1d4e --- /dev/null +++ b/ustream-internal.h @@ -0,0 +1,41 @@ +/* + * ustream-ssl - library for SSL over ustream + * + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __USTREAM_BIO_H +#define __USTREAM_BIO_H + +#define __hidden __attribute__((visibility("hidden"))) + +#include "ustream-openssl.h" + +enum ssl_conn_status { + U_SSL_OK = 0, + U_SSL_PENDING = -1, + U_SSL_ERROR = -2, +}; + +void ustream_set_io(void *ctx, void *ssl, struct ustream *s); +void *__ustream_ssl_context_new(bool server); +int __ustream_ssl_set_crt_file(void *ctx, const char *file); +int __ustream_ssl_set_key_file(void *ctx, const char *file); +void __ustream_ssl_context_free(void *ctx); +enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us); +int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len); +int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len); + +#endif diff --git a/ustream-io-cyassl.c b/ustream-io-cyassl.c new file mode 100644 index 0000000..1787cd0 --- /dev/null +++ b/ustream-io-cyassl.c @@ -0,0 +1,70 @@ +/* + * ustream-ssl - library for SSL over ustream + * + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "ustream-ssl.h" +#include "ustream-internal.h" + +/* not defined in the header file */ +typedef int (*CallbackIORecv)(char *buf, int sz, void *ctx); +typedef int (*CallbackIOSend)(char *buf, int sz, void *ctx); + +void SetCallbackIORecv_Ctx(SSL_CTX*, CallbackIORecv); +void SetCallbackIOSend_Ctx(SSL_CTX*, CallbackIOSend); +void SetCallbackIO_ReadCtx(SSL* ssl, void *rctx); +void SetCallbackIO_WriteCtx(SSL* ssl, void *wctx); + +static int s_ustream_read(char *buf, int len, void *ctx) +{ + struct ustream *s = ctx; + char *sbuf; + int slen; + + if (s->eof) + return -3; + + sbuf = ustream_get_read_buf(s, &slen); + if (slen > len) + slen = len; + + if (!slen) + return -2; + + memcpy(buf, sbuf, slen); + ustream_consume(s, slen); + + return slen; +} + +static int s_ustream_write(char *buf, int len, void *ctx) +{ + struct ustream *s = ctx; + + return ustream_write(s, buf, len, false); +} + +__hidden void ustream_set_io(void *ctx, void *ssl, struct ustream *conn) +{ + SetCallbackIO_ReadCtx(ssl, conn); + SetCallbackIO_WriteCtx(ssl, conn); + SetCallbackIORecv_Ctx(ctx, s_ustream_read); + SetCallbackIOSend_Ctx(ctx, s_ustream_write); +} diff --git a/ustream-io.c b/ustream-io-openssl.c similarity index 68% rename from ustream-io.c rename to ustream-io-openssl.c index b04b844..41e69f7 100644 --- a/ustream-io.c +++ b/ustream-io-openssl.c @@ -20,58 +20,8 @@ #include -#include "ustream-io.h" #include "ustream-ssl.h" - -#ifdef CYASSL_OPENSSL_H_ - -/* not defined in the header file */ -typedef int (*CallbackIORecv)(char *buf, int sz, void *ctx); -typedef int (*CallbackIOSend)(char *buf, int sz, void *ctx); - -void SetCallbackIORecv_Ctx(SSL_CTX*, CallbackIORecv); -void SetCallbackIOSend_Ctx(SSL_CTX*, CallbackIOSend); -void SetCallbackIO_ReadCtx(SSL* ssl, void *rctx); -void SetCallbackIO_WriteCtx(SSL* ssl, void *wctx); - -static int s_ustream_read(char *buf, int len, void *ctx) -{ - struct ustream *s = ctx; - char *sbuf; - int slen; - - if (s->eof) - return -3; - - sbuf = ustream_get_read_buf(s, &slen); - if (slen > len) - slen = len; - - if (!slen) - return -2; - - memcpy(buf, sbuf, slen); - ustream_consume(s, slen); - - return slen; -} - -static int s_ustream_write(char *buf, int len, void *ctx) -{ - struct ustream *s = ctx; - - return ustream_write(s, buf, len, false); -} - -void ustream_set_io(SSL_CTX *ctx, SSL *ssl, struct ustream *conn) -{ - SetCallbackIO_ReadCtx(ssl, conn); - SetCallbackIO_WriteCtx(ssl, conn); - SetCallbackIORecv_Ctx(ctx, s_ustream_read); - SetCallbackIOSend_Ctx(ctx, s_ustream_write); -} - -#else +#include "ustream-internal.h" static int s_ustream_new(BIO *b) @@ -185,10 +135,8 @@ static BIO *ustream_bio_new(struct ustream *s) return bio; } -void ustream_set_io(SSL_CTX *ctx, SSL *ssl, struct ustream *conn) +__hidden void ustream_set_io(void *ctx, void *ssl, struct ustream *conn) { BIO *bio = ustream_bio_new(conn); SSL_set_bio(ssl, bio, bio); } - -#endif diff --git a/ustream-openssl.c b/ustream-openssl.c new file mode 100644 index 0000000..2d569f3 --- /dev/null +++ b/ustream-openssl.c @@ -0,0 +1,148 @@ +/* + * ustream-ssl - library for SSL over ustream + * + * Copyright (C) 2012 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ustream-ssl.h" +#include "ustream-internal.h" + +__hidden void * __ustream_ssl_context_new(bool server) +{ + static bool _init = false; + const void *m; + SSL_CTX *c; + + if (!_init) { + SSL_load_error_strings(); + SSL_library_init(); + _init = true; + } + +#ifdef CYASSL_OPENSSL_H_ + if (server) + m = SSLv23_server_method(); + else + m = SSLv23_client_method(); +#else + if (server) + m = TLSv1_server_method(); + else + m = TLSv1_client_method(); +#endif + + c = SSL_CTX_new((void *) m); + if (!c) + return NULL; + + if (server) + SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL); + + return c; +} + +__hidden int __ustream_ssl_set_crt_file(void *ctx, const char *file) +{ + int ret; + + ret = SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_PEM); + if (ret < 1) + ret = SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_ASN1); + + if (ret < 1) + return -1; + + return 0; +} + +__hidden int __ustream_ssl_set_key_file(void *ctx, const char *file) +{ + int ret; + + ret = SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_PEM); + if (ret < 1) + ret = SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_ASN1); + + if (ret < 1) + return -1; + + return 0; +} + +__hidden void __ustream_ssl_context_free(void *ctx) +{ + SSL_CTX_free(ctx); +} + +static void ustream_ssl_error(struct ustream_ssl *us, int ret) +{ + us->error = ret; + uloop_timeout_set(&us->error_timer, 0); +} + +__hidden enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us) +{ + void *ssl = us->ssl; + int r; + + if (us->server) + r = SSL_accept(ssl); + else + r = SSL_connect(ssl); + + if (r == 1) + return U_SSL_OK; + + r = SSL_get_error(ssl, r); + if (r == SSL_ERROR_WANT_READ || r == SSL_ERROR_WANT_WRITE) + return U_SSL_PENDING; + + ustream_ssl_error(us, r); + return U_SSL_ERROR; +} + +__hidden int __ustream_ssl_write(struct ustream_ssl *us, const char *buf, int len) +{ + void *ssl = us->ssl; + int ret = SSL_write(ssl, buf, len); + + if (ret < 0) { + int err = SSL_get_error(ssl, ret); + if (err == SSL_ERROR_WANT_WRITE) + return 0; + + ustream_ssl_error(us, err); + return -1; + } + + return ret; +} + +__hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len) +{ + int ret = SSL_read(us->ssl, buf, len); + + if (ret < 0) { + ret = SSL_get_error(us->ssl, ret); + if (ret == SSL_ERROR_WANT_READ) + return U_SSL_PENDING; + + ustream_ssl_error(us, ret); + return U_SSL_ERROR; + } + + return ret; +} + diff --git a/ustream-io.h b/ustream-openssl.h similarity index 70% rename from ustream-io.h rename to ustream-openssl.h index 1e660e7..76d2bad 100644 --- a/ustream-io.h +++ b/ustream-openssl.h @@ -16,14 +16,27 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef __USTREAM_BIO_H -#define __USTREAM_BIO_H +#ifndef __USTREAM_OPENSSL_H +#define __USTREAM_OPENSSL_H #include #include +#include -#include "ustream-ssl.h" +static inline void *__ustream_ssl_session_new(void *ctx) +{ + return SSL_new(ctx); +} -void ustream_set_io(SSL_CTX *ctx, SSL *ssl, struct ustream *s); +static inline void __ustream_ssl_session_free(void *ssl) +{ + SSL_shutdown(ssl); + SSL_free(ssl); +} + +static inline char *__ustream_ssl_strerror(int error, char *buffer, int len) +{ + return ERR_error_string(error, buffer); +} #endif diff --git a/ustream-ssl.c b/ustream-ssl.c index bbc6b11..0ae5df6 100644 --- a/ustream-ssl.c +++ b/ustream-ssl.c @@ -17,26 +17,10 @@ */ #include - -#include -#include - #include -#include "ustream-io.h" -#include "ustream-ssl.h" - -static void ssl_init(void) -{ - static bool _init = false; - - if (_init) - return; - - SSL_load_error_strings(); - SSL_library_init(); - _init = true; -} +#include "ustream-ssl.h" +#include "ustream-internal.h" static void ustream_ssl_error_cb(struct uloop_timeout *t) { @@ -45,39 +29,19 @@ static void ustream_ssl_error_cb(struct uloop_timeout *t) int error = us->error; if (us->notify_error) - us->notify_error(us, error, ERR_error_string(us->error, buffer)); -} - -static void ustream_ssl_error(struct ustream_ssl *us, int error) -{ - us->error = error; - uloop_timeout_set(&us->error_timer, 0); + us->notify_error(us, error, __ustream_ssl_strerror(us->error, buffer, sizeof(buffer))); } static void ustream_ssl_check_conn(struct ustream_ssl *us) { - int ret; - if (us->connected || us->error) return; - if (us->server) - ret = SSL_accept(us->ssl); - else - ret = SSL_connect(us->ssl); - - if (ret == 1) { + if (__ustream_ssl_connect(us) == U_SSL_OK) { us->connected = true; if (us->notify_connected) us->notify_connected(us); - return; } - - ret = SSL_get_error(us->ssl, ret); - if (ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_WANT_WRITE) - return; - - ustream_ssl_error(us, ret); } static bool __ustream_ssl_poll(struct ustream *s) @@ -96,24 +60,21 @@ static bool __ustream_ssl_poll(struct ustream *s) if (!len) break; - ret = SSL_read(us->ssl, buf, len); - if (ret < 0) { - ret = SSL_get_error(us->ssl, ret); - - if (ret == SSL_ERROR_WANT_READ) - break; - - ustream_ssl_error(us, ret); - break; - } - if (ret == 0) { + ret = __ustream_ssl_read(us, buf, len); + switch (ret) { + case U_SSL_PENDING: + return more; + case U_SSL_ERROR: + return false; + case 0: us->stream.eof = true; ustream_state_change(&us->stream); - break; + return false; + default: + ustream_fill_read(&us->stream, ret); + more = true; + continue; } - - ustream_fill_read(&us->stream, ret); - more = true; } while (1); return more; @@ -141,7 +102,6 @@ static void ustream_ssl_notify_state(struct ustream *s) static int ustream_ssl_write(struct ustream *s, const char *buf, int len, bool more) { struct ustream_ssl *us = container_of(s, struct ustream_ssl, stream); - int ret; if (!us->connected || us->error) return 0; @@ -149,14 +109,7 @@ static int ustream_ssl_write(struct ustream *s, const char *buf, int len, bool m if (us->conn->w.data_bytes) return 0; - ret = SSL_write(us->ssl, buf, len); - if (ret < 0) { - int err = SSL_get_error(us->ssl, ret); - if (err == SSL_ERROR_WANT_WRITE) - return 0; - } - - return ret; + return __ustream_ssl_write(us, buf, len); } static void ustream_ssl_set_read_blocked(struct ustream *s) @@ -178,8 +131,7 @@ static void ustream_ssl_free(struct ustream *s) } uloop_timeout_cancel(&us->error_timer); - SSL_shutdown(us->ssl); - SSL_free(us->ssl); + __ustream_ssl_session_free(us->ssl); us->ctx = NULL; us->ssl = NULL; us->conn = NULL; @@ -212,68 +164,6 @@ static void ustream_ssl_stream_init(struct ustream_ssl *us) ustream_init_defaults(s); } -static void *_ustream_ssl_context_new(bool server) -{ - SSL_CTX *c; - const void *m; - - ssl_init(); - -#ifdef CYASSL_OPENSSL_H_ - if (server) - m = SSLv23_server_method(); - else - m = SSLv23_client_method(); -#else - if (server) - m = TLSv1_server_method(); - else - m = TLSv1_client_method(); -#endif - - c = SSL_CTX_new((void *) m); - if (!c) - return NULL; - - if (server) - SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL); - - return c; -} - -static int _ustream_ssl_context_set_crt_file(void *ctx, const char *file) -{ - int ret; - - ret = SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_PEM); - if (ret < 1) - ret = SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_ASN1); - - if (ret < 1) - return -1; - - return 0; -} - -static int _ustream_ssl_context_set_key_file(void *ctx, const char *file) -{ - int ret; - - ret = SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_PEM); - if (ret < 1) - ret = SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_ASN1); - - if (ret < 1) - return -1; - - return 0; -} - -static void _ustream_ssl_context_free(void *ctx) -{ - SSL_CTX_free(ctx); -} - static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, void *ctx, bool server) { us->error_timer.cb = ustream_ssl_error_cb; @@ -281,7 +171,7 @@ static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, void us->conn = conn; us->ctx = ctx; - us->ssl = SSL_new(us->ctx); + us->ssl = __ustream_ssl_session_new(us->ctx); if (!us->ssl) return -ENOMEM; @@ -293,9 +183,9 @@ static int _ustream_ssl_init(struct ustream_ssl *us, struct ustream *conn, void } const struct ustream_ssl_ops ustream_ssl_ops = { - .context_new = _ustream_ssl_context_new, - .context_set_crt_file = _ustream_ssl_context_set_crt_file, - .context_set_key_file = _ustream_ssl_context_set_key_file, - .context_free = _ustream_ssl_context_free, + .context_new = __ustream_ssl_context_new, + .context_set_crt_file = __ustream_ssl_set_crt_file, + .context_set_key_file = __ustream_ssl_set_key_file, + .context_free = __ustream_ssl_context_free, .init = _ustream_ssl_init, }; diff --git a/ustream-ssl.h b/ustream-ssl.h index 21d89d5..aa1ced5 100644 --- a/ustream-ssl.h +++ b/ustream-ssl.h @@ -19,6 +19,8 @@ #ifndef __USTREAM_SSL_H #define __USTREAM_SSL_H +#include + struct ustream_ssl { struct ustream stream; struct ustream *conn; -- 2.25.1