mirror of
https://github.com/libevent/libevent.git
synced 2025-01-09 00:56:20 +08:00
347 lines
9.7 KiB
C
347 lines
9.7 KiB
C
/*
|
|
* Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
/** For event_debug() usage/coverage */
|
|
#define EVENT_VISIBILITY_WANT_DLLIMPORT
|
|
|
|
#include "event2/util.h"
|
|
#include <mbedtls/version.h>
|
|
#include <mbedtls/ssl.h>
|
|
#include <mbedtls/entropy.h>
|
|
#include <mbedtls/ctr_drbg.h>
|
|
#include <mbedtls/debug.h>
|
|
#include "regress.h"
|
|
#include "tinytest.h"
|
|
|
|
#define TESTCASES_NAME mbedtls_testcases
|
|
|
|
#ifdef OPENSSL_VERSION_NUMBER
|
|
#undef OPENSSL_VERSION_NUMBER
|
|
#endif
|
|
#define OPENSSL_VERSION_NUMBER 0
|
|
#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT
|
|
#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER
|
|
|
|
#define get_ssl_ctx get_mbedtls_config
|
|
|
|
/* FIXME: clean this up, add some prefix, i.e. le_ssl_ */
|
|
#if MBEDTLS_VERSION_MAJOR < 3
|
|
#define SSL_renegotiate mbedtls_ssl_renegotiate
|
|
#endif
|
|
#undef SSL_get_peer_certificate
|
|
#define SSL_get_peer_certificate mbedtls_ssl_get_peer_cert
|
|
#define SSL_get1_peer_certificate mbedtls_ssl_get_peer_cert
|
|
#define SSL_new bufferevent_mbedtls_dyncontext_new
|
|
#define SSL_use_certificate(a, b) \
|
|
do { \
|
|
} while (0);
|
|
#define SSL_use_PrivateKey(a, b) \
|
|
do { \
|
|
} while (0);
|
|
#define X509_free(x) \
|
|
do { \
|
|
} while (0);
|
|
|
|
#define X509 const mbedtls_x509_crt
|
|
#define SSL mbedtls_ssl_context
|
|
|
|
#define bufferevent_ssl_get_ssl bufferevent_mbedtls_get_ssl
|
|
#define bufferevent_ssl_set_allow_dirty_shutdown \
|
|
bufferevent_mbedtls_set_allow_dirty_shutdown
|
|
#define bufferevent_ssl_socket_new bufferevent_mbedtls_socket_new
|
|
#define bufferevent_ssl_filter_new bufferevent_mbedtls_filter_new
|
|
|
|
struct rwcount;
|
|
static void BIO_setup(SSL *ssl, struct rwcount *rw);
|
|
static void *mbedtls_test_setup(const struct testcase_t *testcase);
|
|
static int mbedtls_test_cleanup(const struct testcase_t *testcase, void *ptr);
|
|
const struct testcase_setup_t mbedtls_setup = {
|
|
mbedtls_test_setup, mbedtls_test_cleanup};
|
|
#define ssl_setup mbedtls_setup
|
|
#include "regress_ssl.c"
|
|
static mbedtls_ssl_config *the_mbedtls_conf[2] = {NULL, NULL};
|
|
static mbedtls_entropy_context entropy;
|
|
static mbedtls_ctr_drbg_context ctr_drbg;
|
|
static mbedtls_x509_crt *the_cert;
|
|
static mbedtls_pk_context *the_key;
|
|
|
|
static void
|
|
mbedtls_debug(
|
|
void *userdata, int level, const char *file, int line, const char *str)
|
|
{
|
|
int loglen = strlen(str);
|
|
if (str[loglen - 1] == '\n')
|
|
loglen--;
|
|
event_debug(("[mbedtls][%s][%d][%s][%d]%.*s", (char *)userdata, level, file,
|
|
line, loglen, str));
|
|
}
|
|
|
|
static int
|
|
mbedtls_rng(void* ctx, unsigned char* buffer, size_t len)
|
|
{
|
|
int rc;
|
|
|
|
(void)ctx;
|
|
|
|
rc = evutil_secure_rng_init();
|
|
if (rc != 0)
|
|
return rc;
|
|
evutil_secure_rng_get_bytes(buffer, len);
|
|
return 0;
|
|
}
|
|
|
|
static mbedtls_pk_context *
|
|
mbedtls_getkey(void)
|
|
{
|
|
int ret = 0;
|
|
mbedtls_pk_context *pk = malloc(sizeof(mbedtls_pk_context));
|
|
tt_assert(pk);
|
|
mbedtls_pk_init(pk);
|
|
ret = mbedtls_pk_parse_key(pk,
|
|
(const unsigned char *)KEY, sizeof(KEY),
|
|
NULL, 0
|
|
#if MBEDTLS_VERSION_MAJOR >= 3
|
|
, mbedtls_rng, NULL
|
|
#endif
|
|
);
|
|
tt_assert(ret == 0);
|
|
return pk;
|
|
end:
|
|
if (pk) {
|
|
mbedtls_pk_free(pk);
|
|
free(pk);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
create_tm_from_unix_epoch(struct tm *cur_p, const time_t t)
|
|
{
|
|
#ifdef _WIN32
|
|
struct tm *tmp = gmtime(&t);
|
|
if (!tmp) {
|
|
fprintf(stderr, "gmtime: %s (%i)", strerror(errno), (int)t);
|
|
exit(1);
|
|
}
|
|
*cur_p = *tmp;
|
|
#else
|
|
gmtime_r(&t, cur_p);
|
|
#endif
|
|
}
|
|
|
|
static mbedtls_x509_crt *
|
|
mbedtls_getcert(mbedtls_pk_context *pk)
|
|
{
|
|
const char *name = "commonName=example.com";
|
|
time_t now = time(NULL);
|
|
char now_string[32] = "";
|
|
char not_before[32] = "";
|
|
char not_after[32] = "";
|
|
unsigned char certbuf[8192];
|
|
struct tm tm;
|
|
mbedtls_x509_crt *crt = NULL;
|
|
int ret = 0;
|
|
|
|
mbedtls_mpi serial;
|
|
mbedtls_x509write_cert write_cert;
|
|
|
|
snprintf(now_string, sizeof(now_string), "%lld", (long long)now);
|
|
|
|
create_tm_from_unix_epoch(&tm, now);
|
|
strftime(not_before, sizeof(not_before), "%Y%m%d%H%M%S", &tm);
|
|
now += 3600;
|
|
create_tm_from_unix_epoch(&tm, now);
|
|
strftime(not_after, sizeof(not_after), "%Y%m%d%H%M%S", &tm);
|
|
|
|
mbedtls_x509write_crt_init(&write_cert);
|
|
mbedtls_x509write_crt_set_version(&write_cert, 2);
|
|
|
|
mbedtls_mpi_init(&serial);
|
|
ret = mbedtls_mpi_read_string(&serial, 10, now_string);
|
|
tt_assert(ret == 0);
|
|
ret = mbedtls_x509write_crt_set_serial(&write_cert, &serial);
|
|
tt_assert(ret == 0);
|
|
mbedtls_mpi_free(&serial);
|
|
|
|
ret = mbedtls_x509write_crt_set_subject_name(&write_cert, name);
|
|
tt_assert(ret == 0);
|
|
ret = mbedtls_x509write_crt_set_issuer_name(&write_cert, name);
|
|
tt_assert(ret == 0);
|
|
|
|
mbedtls_x509write_crt_set_md_alg(&write_cert, MBEDTLS_MD_SHA256);
|
|
|
|
ret =
|
|
mbedtls_x509write_crt_set_validity(&write_cert, not_before, not_after);
|
|
tt_assert(ret == 0);
|
|
mbedtls_x509write_crt_set_issuer_key(&write_cert, pk);
|
|
mbedtls_x509write_crt_set_subject_key(&write_cert, pk);
|
|
|
|
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
|
(const unsigned char *)name, strlen(name));
|
|
tt_assert(ret == 0);
|
|
ret = mbedtls_x509write_crt_pem(&write_cert, certbuf, sizeof(certbuf),
|
|
mbedtls_ctr_drbg_random, &ctr_drbg);
|
|
tt_assert(ret == 0);
|
|
mbedtls_x509write_crt_free(&write_cert);
|
|
|
|
crt = malloc(sizeof(mbedtls_x509_crt));
|
|
tt_assert(crt);
|
|
mbedtls_x509_crt_init(crt);
|
|
ret = mbedtls_x509_crt_parse(crt, certbuf, strlen((char *)certbuf) + 1);
|
|
tt_assert(ret == 0);
|
|
return crt;
|
|
end:
|
|
if (crt) {
|
|
mbedtls_x509_crt_free(crt);
|
|
free(crt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
mbedtls_ssl_config *
|
|
get_mbedtls_config(int endpoint)
|
|
{
|
|
if (the_mbedtls_conf[endpoint])
|
|
return the_mbedtls_conf[endpoint];
|
|
the_mbedtls_conf[endpoint] = malloc(sizeof(mbedtls_ssl_config));
|
|
if (!the_mbedtls_conf[endpoint])
|
|
return NULL;
|
|
mbedtls_ssl_config_init(the_mbedtls_conf[endpoint]);
|
|
mbedtls_ssl_conf_renegotiation(
|
|
the_mbedtls_conf[endpoint], MBEDTLS_SSL_RENEGOTIATION_ENABLED);
|
|
mbedtls_ssl_conf_dbg(the_mbedtls_conf[endpoint], mbedtls_debug,
|
|
(void *)(endpoint == MBEDTLS_SSL_IS_SERVER ? "server" : "client"));
|
|
mbedtls_ssl_config_defaults(the_mbedtls_conf[endpoint], endpoint,
|
|
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
|
mbedtls_ssl_conf_rng(
|
|
the_mbedtls_conf[endpoint], mbedtls_ctr_drbg_random, &ctr_drbg);
|
|
#if MBEDTLS_VERSION_MAJOR < 3
|
|
/* Mbed-TLS 3 doesn't support anything below TLS v1.2 */
|
|
if (disable_tls_11_and_12) {
|
|
mbedtls_ssl_conf_max_version(the_mbedtls_conf[endpoint],
|
|
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1);
|
|
}
|
|
#endif
|
|
if (endpoint == MBEDTLS_SSL_IS_SERVER) {
|
|
mbedtls_ssl_conf_own_cert(
|
|
the_mbedtls_conf[endpoint], the_cert, the_key);
|
|
} else { /* MBEDTLS_SSL_IS_CLIENT */
|
|
mbedtls_ssl_conf_ca_chain(the_mbedtls_conf[endpoint], the_cert, NULL);
|
|
}
|
|
return the_mbedtls_conf[endpoint];
|
|
}
|
|
|
|
static void
|
|
init_mbedtls(void)
|
|
{
|
|
mbedtls_debug_set_threshold(5);
|
|
}
|
|
|
|
static void *
|
|
mbedtls_test_setup(const struct testcase_t *testcase)
|
|
{
|
|
init_mbedtls();
|
|
|
|
mbedtls_entropy_init(&entropy);
|
|
mbedtls_ctr_drbg_init(&ctr_drbg);
|
|
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
|
(const unsigned char *)"libevent", sizeof("libevent"));
|
|
|
|
the_key = mbedtls_getkey();
|
|
EVUTIL_ASSERT(the_key);
|
|
|
|
the_cert = mbedtls_getcert(the_key);
|
|
EVUTIL_ASSERT(the_cert);
|
|
|
|
disable_tls_11_and_12 = 0;
|
|
|
|
return basic_test_setup(testcase);
|
|
}
|
|
static int
|
|
mbedtls_test_cleanup(const struct testcase_t *testcase, void *ptr)
|
|
{
|
|
int ret = basic_test_cleanup(testcase, ptr);
|
|
if (!ret) {
|
|
return ret;
|
|
}
|
|
|
|
test_is_done = 0;
|
|
n_connected = 0;
|
|
got_close = 0;
|
|
got_error = 0;
|
|
got_timeout = 0;
|
|
renegotiate_at = -1;
|
|
stop_when_connected = 0;
|
|
pending_connect_events = 0;
|
|
exit_base = NULL;
|
|
|
|
mbedtls_x509_crt_free(the_cert);
|
|
free(the_cert);
|
|
mbedtls_pk_free(the_key);
|
|
free(the_key);
|
|
|
|
if (the_mbedtls_conf[0]) {
|
|
mbedtls_ssl_config_free(the_mbedtls_conf[0]);
|
|
free(the_mbedtls_conf[0]);
|
|
the_mbedtls_conf[0] = NULL;
|
|
}
|
|
if (the_mbedtls_conf[1]) {
|
|
mbedtls_ssl_config_free(the_mbedtls_conf[1]);
|
|
free(the_mbedtls_conf[1]);
|
|
the_mbedtls_conf[1] = NULL;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
bio_rwcount_read(void *ctx, unsigned char *out, size_t outlen)
|
|
{
|
|
struct rwcount *rw = ctx;
|
|
ev_ssize_t ret = recv(rw->fd, out, outlen, 0);
|
|
++rw->read;
|
|
if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
|
|
return MBEDTLS_ERR_SSL_WANT_READ;
|
|
}
|
|
return ret;
|
|
}
|
|
static int
|
|
bio_rwcount_write(void *ctx, const unsigned char *in, size_t inlen)
|
|
{
|
|
struct rwcount *rw = ctx;
|
|
ev_ssize_t ret = send(rw->fd, in, inlen, 0);
|
|
++rw->write;
|
|
if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
|
|
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
|
}
|
|
return ret;
|
|
}
|
|
static void
|
|
BIO_setup(SSL *ssl, struct rwcount *rw)
|
|
{
|
|
mbedtls_ssl_set_bio(ssl, rw, bio_rwcount_write, bio_rwcount_read,
|
|
NULL);
|
|
}
|