2017-03-24 14:53:39 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* machinarium.
|
|
|
|
*
|
|
|
|
* cooperative multitasking engine.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <machinarium_private.h>
|
|
|
|
#include <machinarium.h>
|
|
|
|
|
2017-03-28 11:51:57 +00:00
|
|
|
void mm_tls_init(void)
|
2017-03-24 14:53:39 +00:00
|
|
|
{
|
|
|
|
SSL_library_init();
|
|
|
|
SSL_load_error_strings();
|
2017-03-28 11:51:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void mm_tlsio_init(mm_tlsio_t *io, void *io_arg)
|
|
|
|
{
|
|
|
|
memset(io, 0, sizeof(*io));
|
|
|
|
io->io = io_arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mm_tlsio_free(mm_tlsio_t *io)
|
|
|
|
{
|
|
|
|
(void)io;
|
2017-03-24 14:53:39 +00:00
|
|
|
}
|
|
|
|
|
2017-03-29 12:33:20 +00:00
|
|
|
static inline void
|
|
|
|
mm_tlsio_error_reset(mm_tlsio_t *io)
|
|
|
|
{
|
|
|
|
io->error = 0;
|
2017-03-29 13:04:05 +00:00
|
|
|
io->error_msg[0] = 0;
|
2017-03-30 10:30:24 +00:00
|
|
|
ERR_clear_error();
|
2017-03-29 12:33:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(mm_tlsio_t *io, int ssl_rc, char *fmt, ...)
|
2017-03-29 12:33:20 +00:00
|
|
|
{
|
2017-03-29 13:04:05 +00:00
|
|
|
unsigned int error;
|
2017-03-29 12:33:20 +00:00
|
|
|
io->error = 1;
|
|
|
|
|
2017-03-29 13:04:05 +00:00
|
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
|
|
int len = 0;
|
|
|
|
len = vsnprintf(io->error_msg, sizeof(io->error_msg), fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
(void)ssl_rc;
|
|
|
|
#if 0
|
|
|
|
error = SSL_get_error(io->ssl, ssl_rc);
|
|
|
|
switch (error) {
|
2017-03-29 12:33:20 +00:00
|
|
|
case SSL_ERROR_SYSCALL:
|
2017-03-29 13:04:05 +00:00
|
|
|
case SSL_ERROR_SSL:
|
|
|
|
goto set_error_message;
|
2017-03-29 12:33:20 +00:00
|
|
|
case SSL_ERROR_NONE:
|
|
|
|
case SSL_ERROR_ZERO_RETURN:
|
|
|
|
case SSL_ERROR_WANT_CONNECT:
|
|
|
|
case SSL_ERROR_WANT_ACCEPT:
|
|
|
|
case SSL_ERROR_WANT_READ:
|
|
|
|
case SSL_ERROR_WANT_WRITE:
|
|
|
|
case SSL_ERROR_WANT_X509_LOOKUP:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2017-03-29 13:04:05 +00:00
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
error = ERR_peek_last_error();
|
|
|
|
if (error != 0) {
|
|
|
|
len += snprintf(io->error_msg + len, sizeof(io->error_msg) - len,
|
|
|
|
": %s",
|
|
|
|
ERR_error_string(error, NULL));
|
|
|
|
}
|
2017-03-29 12:33:20 +00:00
|
|
|
}
|
|
|
|
|
2017-03-28 10:14:52 +00:00
|
|
|
static int
|
2017-03-28 11:51:57 +00:00
|
|
|
mm_tlsio_write_cb(BIO *bio, const char *buf, int size)
|
2017-03-28 10:14:52 +00:00
|
|
|
{
|
2017-03-28 10:31:14 +00:00
|
|
|
mm_tlsio_t *io;
|
2017-03-28 10:14:52 +00:00
|
|
|
io = BIO_get_app_data(bio);
|
2017-03-28 11:51:57 +00:00
|
|
|
int rc = mm_write(io->io, (char*)buf, size, 0);
|
|
|
|
if (rc == -1)
|
|
|
|
return -1;
|
|
|
|
return size;
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-03-28 11:51:57 +00:00
|
|
|
mm_tlsio_read_cb(BIO *bio, char *buf, int size)
|
2017-03-28 10:14:52 +00:00
|
|
|
{
|
2017-03-28 10:31:14 +00:00
|
|
|
mm_tlsio_t *io;
|
2017-03-28 10:14:52 +00:00
|
|
|
io = BIO_get_app_data(bio);
|
2017-03-28 11:51:57 +00:00
|
|
|
int rc = mm_read(io->io, buf, size, 0);
|
|
|
|
if (rc == -1)
|
|
|
|
return -1;
|
|
|
|
return size;
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
|
|
|
|
2017-03-30 10:30:24 +00:00
|
|
|
static long
|
|
|
|
mm_tlsio_ctrl_cb(BIO *bio, int cmd, long larg, void *parg)
|
|
|
|
{
|
|
|
|
(void)parg;
|
|
|
|
long ret = 1;
|
|
|
|
switch (cmd) {
|
|
|
|
case BIO_CTRL_GET_CLOSE:
|
|
|
|
ret = (long)BIO_get_shutdown(bio);
|
|
|
|
break;
|
|
|
|
case BIO_CTRL_SET_CLOSE:
|
|
|
|
BIO_set_shutdown(bio, (int)larg);
|
|
|
|
break;
|
|
|
|
case BIO_CTRL_DUP:
|
|
|
|
case BIO_CTRL_FLUSH:
|
|
|
|
break;
|
|
|
|
case BIO_CTRL_INFO:
|
|
|
|
case BIO_CTRL_GET:
|
|
|
|
case BIO_CTRL_SET:
|
|
|
|
case BIO_CTRL_PUSH:
|
|
|
|
case BIO_CTRL_POP:
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-03-28 10:14:52 +00:00
|
|
|
static int
|
2017-03-28 11:51:57 +00:00
|
|
|
mm_tlsio_prepare(mm_tls_t *tls, mm_tlsio_t *io)
|
2017-03-24 14:53:39 +00:00
|
|
|
{
|
2017-03-29 12:33:20 +00:00
|
|
|
SSL_CTX *ctx = NULL;
|
|
|
|
SSL *ssl = NULL;
|
|
|
|
BIO_METHOD *bio_method = NULL;
|
|
|
|
BIO *bio = NULL;
|
2017-03-28 11:51:57 +00:00
|
|
|
|
2017-03-29 13:04:05 +00:00
|
|
|
ctx = SSL_CTX_new((SSL_METHOD*)TLS_client_method());
|
2017-03-29 12:33:20 +00:00
|
|
|
if (ctx == NULL) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, 0, "SSL_CTX_new()");
|
2017-03-24 14:53:39 +00:00
|
|
|
return -1;
|
2017-03-29 12:33:20 +00:00
|
|
|
}
|
2017-03-28 10:14:52 +00:00
|
|
|
|
|
|
|
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
|
|
|
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
|
|
|
|
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
|
|
|
|
SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
|
|
|
|
|
2017-03-29 13:04:05 +00:00
|
|
|
/* verify mode */
|
2017-03-30 10:48:03 +00:00
|
|
|
int verify;
|
|
|
|
switch (tls->verify) {
|
|
|
|
case MM_TLS_NONE:
|
|
|
|
verify = SSL_VERIFY_NONE;
|
|
|
|
break;
|
|
|
|
case MM_TLS_PEER:
|
|
|
|
verify = SSL_VERIFY_PEER;
|
|
|
|
break;
|
|
|
|
case MM_TLS_PEER_STRICT:
|
|
|
|
verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SSL_CTX_set_verify(ctx, verify, NULL);
|
2017-03-29 13:04:05 +00:00
|
|
|
SSL_CTX_set_verify_depth(ctx, 6);
|
|
|
|
|
2017-03-28 10:14:52 +00:00
|
|
|
/* cert file */
|
|
|
|
int rc;
|
|
|
|
if (tls->cert_file) {
|
|
|
|
rc = SSL_CTX_use_certificate_chain_file(ctx, tls->cert_file);
|
|
|
|
if (! rc) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, 0, "SSL_CTX_use_certificate_chain_file()");
|
2017-03-29 12:33:20 +00:00
|
|
|
goto error;
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* key file */
|
|
|
|
if (tls->key_file) {
|
|
|
|
rc = SSL_CTX_use_PrivateKey_file(ctx, tls->key_file, SSL_FILETYPE_PEM);
|
|
|
|
if (! rc) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, 0, "SSL_CTX_use_PrivateKey_file()");
|
2017-03-29 12:33:20 +00:00
|
|
|
goto error;
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
|
|
|
}
|
2017-03-29 13:04:05 +00:00
|
|
|
if (tls->cert_file && tls->key_file) {
|
|
|
|
rc = SSL_CTX_check_private_key(ctx);
|
|
|
|
if(! rc) {
|
|
|
|
mm_tlsio_error(io, 0, "SSL_CTX_check_private_key()");
|
|
|
|
goto error;
|
|
|
|
}
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ca file and ca_path */
|
|
|
|
if (tls->ca_file || tls->ca_path) {
|
|
|
|
rc = SSL_CTX_load_verify_locations(ctx, tls->ca_file, tls->ca_path);
|
|
|
|
if (! rc) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, 0, "SSL_CTX_load_verify_locations()");
|
2017-03-29 12:33:20 +00:00
|
|
|
goto error;
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ocsp */
|
|
|
|
/*
|
|
|
|
SSL_set_cipher_list()
|
|
|
|
SSL_set_tlsext_host_name()
|
|
|
|
*/
|
|
|
|
|
|
|
|
ssl = SSL_new(ctx);
|
|
|
|
if (ssl == NULL) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, 0, "SSL_new()");
|
2017-03-29 12:33:20 +00:00
|
|
|
goto error;
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bio_method = BIO_meth_new(BIO_TYPE_MEM, "machinarium-tls");
|
|
|
|
if (bio_method == NULL) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, 0, "SSL_meth_new()");
|
2017-03-29 12:33:20 +00:00
|
|
|
goto error;
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
2017-03-28 11:51:57 +00:00
|
|
|
BIO_meth_set_write(bio_method, mm_tlsio_write_cb);
|
|
|
|
BIO_meth_set_read(bio_method, mm_tlsio_read_cb);
|
2017-03-30 10:30:24 +00:00
|
|
|
BIO_meth_set_ctrl(bio_method, mm_tlsio_ctrl_cb);
|
2017-03-28 10:14:52 +00:00
|
|
|
|
|
|
|
bio = BIO_new(bio_method);
|
|
|
|
if (bio == NULL) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, 0, "BIO_new()");
|
2017-03-29 12:33:20 +00:00
|
|
|
goto error;
|
2017-03-28 10:14:52 +00:00
|
|
|
}
|
|
|
|
BIO_set_app_data(bio, io);
|
2017-03-30 10:30:24 +00:00
|
|
|
BIO_set_init(bio, 1);
|
|
|
|
|
2017-03-28 10:14:52 +00:00
|
|
|
SSL_set_bio(ssl, bio, bio);
|
|
|
|
|
2017-03-28 11:51:57 +00:00
|
|
|
io->ctx = ctx;
|
|
|
|
io->ssl = ssl;
|
|
|
|
io->bio = bio;
|
|
|
|
io->bio_method = bio_method;
|
|
|
|
return 0;
|
2017-03-29 12:33:20 +00:00
|
|
|
error:
|
|
|
|
SSL_CTX_free(ctx);
|
|
|
|
if (ssl)
|
|
|
|
SSL_free(ssl);
|
|
|
|
if (bio)
|
|
|
|
BIO_free(bio);
|
|
|
|
if (bio_method)
|
|
|
|
BIO_meth_free(bio_method);
|
|
|
|
return -1;
|
2017-03-28 11:51:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int mm_tlsio_connect(mm_tlsio_t *io, mm_tls_t *tls)
|
|
|
|
{
|
2017-03-29 12:33:20 +00:00
|
|
|
mm_tlsio_error_reset(io);
|
2017-03-28 11:51:57 +00:00
|
|
|
int rc;
|
|
|
|
rc = mm_tlsio_prepare(tls, io);
|
|
|
|
if (rc == -1)
|
|
|
|
return -1;
|
|
|
|
rc = SSL_connect(io->ssl);
|
2017-03-30 10:30:24 +00:00
|
|
|
if (! rc) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, rc, "SSL_connect()");
|
2017-03-28 11:51:57 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-03-30 10:30:24 +00:00
|
|
|
|
|
|
|
/* todo: verify */
|
2017-03-28 11:51:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-03-28 10:14:52 +00:00
|
|
|
|
2017-03-28 11:51:57 +00:00
|
|
|
int mm_tlsio_close(mm_tlsio_t *io)
|
|
|
|
{
|
2017-03-29 12:33:20 +00:00
|
|
|
mm_tlsio_error_reset(io);
|
2017-03-28 10:14:52 +00:00
|
|
|
(void)io;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-28 11:51:57 +00:00
|
|
|
int mm_tlsio_write(mm_tlsio_t *io, char *buf, int size)
|
2017-03-28 10:14:52 +00:00
|
|
|
{
|
2017-03-29 12:33:20 +00:00
|
|
|
mm_tlsio_error_reset(io);
|
2017-03-28 10:14:52 +00:00
|
|
|
int rc;
|
2017-03-28 11:51:57 +00:00
|
|
|
rc = SSL_write(io->ssl, buf, size);
|
2017-03-29 12:33:20 +00:00
|
|
|
if (rc <= 0) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, rc, "SSL_write()");
|
2017-03-28 11:51:57 +00:00
|
|
|
return -1;
|
2017-03-29 12:33:20 +00:00
|
|
|
}
|
2017-03-28 11:51:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mm_tlsio_read(mm_tlsio_t *io, char *buf, int size)
|
|
|
|
{
|
2017-03-29 12:33:20 +00:00
|
|
|
mm_tlsio_error_reset(io);
|
2017-03-28 11:51:57 +00:00
|
|
|
int rc;
|
|
|
|
rc = SSL_read(io->ssl, buf, size);
|
2017-03-29 12:33:20 +00:00
|
|
|
if (rc <= 0) {
|
2017-03-29 13:04:05 +00:00
|
|
|
mm_tlsio_error(io, rc, "SSL_read()");
|
2017-03-28 10:14:52 +00:00
|
|
|
return -1;
|
2017-03-29 12:33:20 +00:00
|
|
|
}
|
2017-03-24 14:53:39 +00:00
|
|
|
return 0;
|
|
|
|
}
|