mirror of
https://github.com/libevent/libevent.git
synced 2025-01-31 09:12:55 +08:00
Merge branch 'mbedtls'
This patch set provides mbed TLS support. The interface part (include/event2/bufferevent_ssl.h) LGTM, so this can be safely merged (although there are some bits left). Includes: - bufferevent_mbedtls_* - regress_mbedtls tests Left: - regress_http https_mbedtls support - ChangeLog entry * mbedtls: test: rename ssl/* -> openssl/* Join le_ssl_ops.post_init with le_ssl_ops.init Update LICENSE for ssl-client-mbedtls.c Merge ssl implementations (openssl and mbedtls) add mbedtls to CI fix build system and add test and cleanup code mbed TLS cmake support simple https client example using mbedtls mbedtls based SSL implementation
This commit is contained in:
commit
0e339b04b5
10
.github/workflows/linux.yml
vendored
10
.github/workflows/linux.yml
vendored
@ -53,6 +53,11 @@ jobs:
|
||||
path: dist
|
||||
key: ${{ matrix.os }}-cmake-dist-${{ matrix.EVENT_MATRIX }}-v2
|
||||
|
||||
- name: Install Depends
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libmbedtls-dev
|
||||
|
||||
- name: Build And Test
|
||||
shell: bash
|
||||
run: |
|
||||
@ -153,6 +158,11 @@ jobs:
|
||||
path: dist
|
||||
key: ${{ matrix.os }}-autotools-dist-${{ matrix.EVENT_MATRIX }}-v2
|
||||
|
||||
- name: Install Depends
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libmbedtls-dev
|
||||
|
||||
- name: Build And Test
|
||||
shell: bash
|
||||
run: |
|
||||
|
5
.github/workflows/macos.yml
vendored
5
.github/workflows/macos.yml
vendored
@ -45,6 +45,9 @@ jobs:
|
||||
path: build
|
||||
key: macos-10.15-cmake-${{ matrix.EVENT_MATRIX }}-v2
|
||||
|
||||
- name: Install Depends
|
||||
run: brew install mbedtls
|
||||
|
||||
- name: Build And Test
|
||||
shell: bash
|
||||
run: |
|
||||
@ -124,7 +127,7 @@ jobs:
|
||||
key: ${{ matrix.os }}-autotools-${{ matrix.EVENT_MATRIX }}-v2
|
||||
|
||||
- name: Install Depends
|
||||
run: brew install autoconf automake libtool pkg-config
|
||||
run: brew install autoconf automake libtool pkg-config mbedtls
|
||||
|
||||
- name: Build And Test
|
||||
shell: bash
|
||||
|
8
.github/workflows/mingw.yml
vendored
8
.github/workflows/mingw.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
||||
uses: actions/cache@v1.1.2
|
||||
with:
|
||||
path: build
|
||||
key: mingw-autotools-${{ matrix.EVENT_MATRIX }}-v2
|
||||
key: mingw-autotools-${{ matrix.EVENT_MATRIX }}-v3
|
||||
|
||||
- uses: numworks/setup-msys2@v1
|
||||
if: steps.cache-mingw.outputs.cache-hit != 'true'
|
||||
@ -56,7 +56,7 @@ jobs:
|
||||
- name: Install Dependes
|
||||
if: steps.cache-mingw.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
msys2do pacman -S --noconfirm mingw-w64-x86_64-gcc autoconf automake libtool mingw-w64-x86_64-openssl
|
||||
msys2do pacman -S --noconfirm mingw-w64-x86_64-gcc autoconf automake libtool mingw-w64-x86_64-openssl mingw-w64-x86_64-mbedtls
|
||||
|
||||
- name: Build And Test
|
||||
shell: powershell
|
||||
@ -115,7 +115,7 @@ jobs:
|
||||
uses: actions/cache@v1.1.2
|
||||
with:
|
||||
path: build
|
||||
key: mingw-cmake-${{ matrix.EVENT_MATRIX }}-v2
|
||||
key: mingw-cmake-${{ matrix.EVENT_MATRIX }}-v3
|
||||
|
||||
- uses: numworks/setup-msys2@v1
|
||||
if: steps.cache-mingw-cmake.outputs.cache-hit != 'true'
|
||||
@ -125,7 +125,7 @@ jobs:
|
||||
- name: Install Dependes
|
||||
if: steps.cache-mingw-cmake.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
msys2do pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-openssl
|
||||
msys2do pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-openssl mingw-w64-x86_64-mbedtls
|
||||
|
||||
- name: Build And Test
|
||||
shell: powershell
|
||||
|
20
.github/workflows/windows.yml
vendored
20
.github/workflows/windows.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
||||
uses: actions/cache@v1.0.3
|
||||
with:
|
||||
path: C:\vcpkg\installed
|
||||
key: ${{ matrix.os }}-vcpkg
|
||||
key: ${{ matrix.os }}-vcpkg-v2
|
||||
|
||||
- name: Cache Build
|
||||
uses: actions/cache@v1.0.3
|
||||
@ -50,19 +50,18 @@ jobs:
|
||||
run: |
|
||||
vcpkg install openssl:x64-windows
|
||||
vcpkg install zlib:x64-windows
|
||||
vcpkg install mbedtls:x64-windows
|
||||
|
||||
- name: Build And Test
|
||||
shell: powershell
|
||||
run: |
|
||||
$OPENSSL_ROOT_DIR="C:\vcpkg\installed\x64-windows"
|
||||
$EVENT_BUILD_PARALLEL=10
|
||||
$EVENT_TESTS_PARALLEL=1
|
||||
$env:PATH="$OPENSSL_ROOT_DIR/bin;$env:PATH"
|
||||
|
||||
mkdir build -ea 0
|
||||
cd build
|
||||
|
||||
$CMAKE_CMD="cmake -G 'Visual Studio 15 2017 Win64' .."
|
||||
$CMAKE_CMD="cmake -G 'Visual Studio 15 2017 Win64' -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake .."
|
||||
function cmake_configure($retry)
|
||||
{
|
||||
$errcode=0
|
||||
@ -142,7 +141,7 @@ jobs:
|
||||
uses: actions/cache@v1.1.0
|
||||
with:
|
||||
path: C:\vcpkg\installed
|
||||
key: ${{ matrix.os }}-vcpkg
|
||||
key: ${{ matrix.os }}-vcpkg-v2
|
||||
|
||||
- name: Cache Build
|
||||
uses: actions/cache@v1.1.0
|
||||
@ -156,17 +155,16 @@ jobs:
|
||||
run: |
|
||||
vcpkg install openssl:x64-windows
|
||||
vcpkg install zlib:x64-windows
|
||||
vcpkg install mbedtls:x64-windows
|
||||
|
||||
- name: Build And Test
|
||||
shell: powershell
|
||||
run: |
|
||||
$OPENSSL_ROOT_DIR="C:\vcpkg\installed\x64-windows"
|
||||
$EVENT_BUILD_PARALLEL=10
|
||||
$EVENT_TESTS_PARALLEL=1
|
||||
$env:PATH="$OPENSSL_ROOT_DIR/bin;$env:PATH"
|
||||
|
||||
if ( "${{ matrix.EVENT_MATRIX }}" -eq "LIBRARY_TYPE_STATIC" ) {
|
||||
$EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC"
|
||||
$EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC -DEVENT__MSVC_STATIC_RUNTIME=OFF"
|
||||
}
|
||||
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "DISABLE_OPENSSL" ) {
|
||||
$EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_OPENSSL=ON"
|
||||
@ -187,7 +185,7 @@ jobs:
|
||||
$EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
|
||||
}
|
||||
elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "TEST_EXPORT_STATIC" ) {
|
||||
$EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
|
||||
$EVENT_CMAKE_OPTIONS="-DEVENT__LIBRARY_TYPE=STATIC -DEVENT__MSVC_STATIC_RUNTIME=OFF -DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON"
|
||||
}
|
||||
else {
|
||||
$EVENT_CMAKE_OPTIONS=""
|
||||
@ -197,10 +195,10 @@ jobs:
|
||||
cd build
|
||||
|
||||
if ("${{ matrix.os }}" -eq "windows-2016") {
|
||||
$CMAKE_CMD="cmake -G 'Visual Studio 15 2017 Win64' .."
|
||||
$CMAKE_CMD="cmake -G 'Visual Studio 15 2017 Win64' -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake .."
|
||||
}
|
||||
else { # windows-2019
|
||||
$CMAKE_CMD="cmake -G 'Visual Studio 16 2019' -A x64 .. $EVENT_CMAKE_OPTIONS"
|
||||
$CMAKE_CMD="cmake -G 'Visual Studio 16 2019' -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake .. $EVENT_CMAKE_OPTIONS"
|
||||
}
|
||||
function cmake_configure($retry)
|
||||
{
|
||||
|
@ -132,6 +132,9 @@ option(EVENT__DISABLE_THREAD_SUPPORT
|
||||
option(EVENT__DISABLE_OPENSSL
|
||||
"Define if libevent should build without support for OpenSSL encryption" OFF)
|
||||
|
||||
option(EVENT__DISABLE_MBEDTLS
|
||||
"Define if libevent should build without support for mbed TLS encryption" OFF)
|
||||
|
||||
option(EVENT__DISABLE_BENCHMARK
|
||||
"Defines if libevent should build without the benchmark executables" OFF)
|
||||
|
||||
@ -861,11 +864,26 @@ if (NOT EVENT__DISABLE_OPENSSL)
|
||||
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
list(APPEND SRC_OPENSSL bufferevent_openssl.c)
|
||||
list(APPEND SRC_OPENSSL bufferevent_openssl.c bufferevent_ssl.c)
|
||||
list(APPEND HDR_PUBLIC include/event2/bufferevent_ssl.h)
|
||||
list(APPEND LIB_APPS ${OPENSSL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (NOT EVENT__DISABLE_MBEDTLS)
|
||||
find_package(MbedTLS REQUIRED)
|
||||
|
||||
set(EVENT__HAVE_MBEDTLS 1)
|
||||
|
||||
message(STATUS "mbed TLS include: ${MBEDTLS_INCLUDE_DIR}")
|
||||
message(STATUS "mbed TLS lib: ${MBEDTLS_LIBRARIES}")
|
||||
|
||||
include_directories(${MBEDTLS_INCLUDE_DIR})
|
||||
|
||||
list(APPEND SRC_MBEDTLS bufferevent_mbedtls.c bufferevent_ssl.c)
|
||||
list(APPEND HDR_PUBLIC include/event2/bufferevent_ssl.h)
|
||||
list(APPEND LIB_APPS ${MBEDTLS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (NOT EVENT__DISABLE_THREAD_SUPPORT)
|
||||
if (WIN32)
|
||||
list(APPEND SRC_CORE evthread_win32.c)
|
||||
@ -971,6 +989,14 @@ if (NOT EVENT__DISABLE_OPENSSL)
|
||||
SOURCES ${SRC_OPENSSL})
|
||||
endif()
|
||||
|
||||
if (NOT EVENT__DISABLE_MBEDTLS)
|
||||
add_event_library(event_mbedtls
|
||||
INNER_LIBRARIES event_core
|
||||
OUTER_INCLUDES ${MBEDTLS_INCLUDE_DIR}
|
||||
LIBRARIES ${MBEDTLS_LIBRARIES}
|
||||
SOURCES ${SRC_MBEDTLS})
|
||||
endif()
|
||||
|
||||
if (EVENT__HAVE_PTHREADS)
|
||||
set(SRC_PTHREADS evthread_pthread.c)
|
||||
add_event_library(event_pthreads
|
||||
@ -1014,8 +1040,8 @@ macro(add_sample_prog ssl name)
|
||||
${LIB_APPS}
|
||||
${LIB_PLATFORM})
|
||||
|
||||
if (${ssl})
|
||||
target_link_libraries(${name} event_openssl)
|
||||
if (TARGET ${ssl})
|
||||
target_link_libraries(${name} ${ssl})
|
||||
if(WIN32)
|
||||
target_link_libraries(${name} crypt32)
|
||||
endif()
|
||||
@ -1038,13 +1064,18 @@ if (NOT EVENT__DISABLE_SAMPLES)
|
||||
endif()
|
||||
|
||||
if (NOT EVENT__DISABLE_OPENSSL)
|
||||
add_sample_prog(ON https-client
|
||||
add_sample_prog(event_openssl https-client
|
||||
sample/https-client.c
|
||||
sample/openssl_hostname_validation.c
|
||||
sample/hostcheck.c)
|
||||
add_sample_prog(ON le-proxy
|
||||
add_sample_prog(event_openssl le-proxy
|
||||
sample/le-proxy.c)
|
||||
add_sample_prog(ON becat sample/becat.c ${WIN32_GETOPT})
|
||||
add_sample_prog(event_openssl becat sample/becat.c ${WIN32_GETOPT})
|
||||
endif()
|
||||
|
||||
if (NOT EVENT__DISABLE_MBEDTLS)
|
||||
add_sample_prog(event_mbedtls ssl-client-mbedtls
|
||||
sample/ssl-client-mbedtls.c)
|
||||
endif()
|
||||
|
||||
set(SAMPLES_WOPT
|
||||
@ -1156,7 +1187,11 @@ if (NOT EVENT__DISABLE_TESTS)
|
||||
endif()
|
||||
|
||||
if (NOT EVENT__DISABLE_OPENSSL)
|
||||
list(APPEND SRC_REGRESS test/regress_ssl.c)
|
||||
list(APPEND SRC_REGRESS test/regress_openssl.c)
|
||||
endif()
|
||||
|
||||
if (NOT EVENT__DISABLE_MBEDTLS)
|
||||
list(APPEND SRC_REGRESS test/regress_mbedtls.c)
|
||||
endif()
|
||||
|
||||
add_executable(regress ${SRC_REGRESS})
|
||||
@ -1169,6 +1204,9 @@ if (NOT EVENT__DISABLE_TESTS)
|
||||
if (NOT EVENT__DISABLE_OPENSSL)
|
||||
target_link_libraries(regress event_openssl)
|
||||
endif()
|
||||
if (NOT EVENT__DISABLE_MBEDTLS)
|
||||
target_link_libraries(regress event_mbedtls)
|
||||
endif()
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
target_link_libraries(regress event_pthreads)
|
||||
endif()
|
||||
|
21
LICENSE
21
LICENSE
@ -128,3 +128,24 @@ 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.
|
||||
|
||||
==============================
|
||||
|
||||
The ssl-client-mbedtls.c is available under the following license:
|
||||
|
||||
Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
This file is part of mbed TLS (https://tls.mbed.org)
|
||||
|
19
Makefile.am
19
Makefile.am
@ -101,7 +101,9 @@ LIBEVENT_PKGCONFIG=libevent.pc libevent_core.pc libevent_extra.pc
|
||||
# included from other files.
|
||||
PLATFORM_DEPENDENT_SRC = \
|
||||
arc4random.c \
|
||||
epoll_sub.c
|
||||
epoll_sub.c \
|
||||
bufferevent_ssl.c \
|
||||
test/regress_ssl.c
|
||||
|
||||
CMAKE_FILES = \
|
||||
cmake/AddCompilerFlags.cmake \
|
||||
@ -116,6 +118,7 @@ CMAKE_FILES = \
|
||||
cmake/CodeCoverage.cmake \
|
||||
cmake/COPYING-CMAKE-SCRIPTS \
|
||||
cmake/Copyright.txt \
|
||||
cmake/FindMbedTLS.cmake \
|
||||
cmake/LibeventConfig.cmake.in \
|
||||
cmake/LibeventConfigVersion.cmake.in \
|
||||
cmake/Macros.cmake \
|
||||
@ -154,6 +157,10 @@ if OPENSSL
|
||||
LIBEVENT_LIBS_LA += libevent_openssl.la
|
||||
LIBEVENT_PKGCONFIG += libevent_openssl.pc
|
||||
endif
|
||||
if MBEDTLS
|
||||
LIBEVENT_LIBS_LA += libevent_mbedtls.la
|
||||
LIBEVENT_PKGCONFIG += libevent_mbedtls.pc
|
||||
endif
|
||||
|
||||
if INSTALL_LIBEVENT
|
||||
lib_LTLIBRARIES = $(LIBEVENT_LIBS_LA)
|
||||
@ -287,12 +294,19 @@ libevent_extra_la_LIBADD = $(MAYBE_CORE) $(SYS_LIBS)
|
||||
libevent_extra_la_LDFLAGS = $(GENERIC_LDFLAGS)
|
||||
|
||||
if OPENSSL
|
||||
libevent_openssl_la_SOURCES = bufferevent_openssl.c
|
||||
libevent_openssl_la_SOURCES = bufferevent_openssl.c bufferevent_ssl.c
|
||||
libevent_openssl_la_LIBADD = $(MAYBE_CORE) $(OPENSSL_LIBS)
|
||||
libevent_openssl_la_LDFLAGS = $(GENERIC_LDFLAGS)
|
||||
libevent_openssl_la_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_INCS)
|
||||
endif
|
||||
|
||||
if MBEDTLS
|
||||
libevent_mbedtls_la_SOURCES = bufferevent_mbedtls.c bufferevent_ssl.c
|
||||
libevent_mbedtls_la_LIBADD = $(MAYBE_CORE) $(MBEDTLS_LIBS)
|
||||
libevent_mbedtls_la_LDFLAGS = $(GENERIC_LDFLAGS)
|
||||
libevent_mbedtls_la_CPPFLAGS = $(AM_CPPFLAGS) $(MBEDTLS_INCS)
|
||||
endif
|
||||
|
||||
noinst_HEADERS += \
|
||||
WIN32-Code/getopt.h \
|
||||
WIN32-Code/getopt.c \
|
||||
@ -323,6 +337,7 @@ noinst_HEADERS += \
|
||||
time-internal.h \
|
||||
util-internal.h \
|
||||
openssl-compat.h \
|
||||
ssl-compat.h \
|
||||
wepoll.h
|
||||
|
||||
EVENT1_HDRS = \
|
||||
|
@ -306,11 +306,18 @@ extern const struct bufferevent_ops bufferevent_ops_pair;
|
||||
#define BEV_IS_FILTER(bevp) ((bevp)->be_ops == &bufferevent_ops_filter)
|
||||
#define BEV_IS_PAIR(bevp) ((bevp)->be_ops == &bufferevent_ops_pair)
|
||||
|
||||
#if defined(EVENT__HAVE_OPENSSL)
|
||||
extern const struct bufferevent_ops bufferevent_ops_openssl;
|
||||
#define BEV_IS_OPENSSL(bevp) ((bevp)->be_ops == &bufferevent_ops_openssl)
|
||||
#if defined(EVENT__HAVE_OPENSSL) | defined(EVENT__HAVE_MBEDTLS)
|
||||
extern const struct bufferevent_ops bufferevent_ops_ssl;
|
||||
#define BEV_IS_SSL(bevp) ((bevp)->be_ops == &bufferevent_ops_ssl)
|
||||
#else
|
||||
#define BEV_IS_OPENSSL(bevp) 0
|
||||
#define BEV_IS_SSL(bevp) 0
|
||||
#endif
|
||||
|
||||
#if defined(EVENT__HAVE_MBEDTLS)
|
||||
extern const struct bufferevent_ops bufferevent_ops_mbedtls;
|
||||
#define BEV_IS_MBEDTLS(bevp) ((bevp)->be_ops == &bufferevent_ops_mbedtls)
|
||||
#else
|
||||
#define BEV_IS_MBEDTLS(bevp) 0
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
397
bufferevent_mbedtls.c
Normal file
397
bufferevent_mbedtls.c
Normal file
@ -0,0 +1,397 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/net_sockets.h>
|
||||
#include <mbedtls/error.h>
|
||||
|
||||
#include "event2/util.h"
|
||||
#include "util-internal.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/bufferevent.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
#include "event2/bufferevent_ssl.h"
|
||||
|
||||
#include "ssl-compat.h"
|
||||
#include "mm-internal.h"
|
||||
|
||||
struct mbedtls_context {
|
||||
mbedtls_ssl_context *ssl;
|
||||
mbedtls_net_context net;
|
||||
};
|
||||
static void *
|
||||
mbedtls_context_init(void *ssl)
|
||||
{
|
||||
struct mbedtls_context *ctx = mm_malloc(sizeof(*ctx));
|
||||
if (ctx) {
|
||||
ctx->ssl = ssl;
|
||||
ctx->net.fd = -1;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
static void
|
||||
mbedtls_context_free(void *ssl, int flags)
|
||||
{
|
||||
struct mbedtls_context *ctx = ssl;
|
||||
if (flags & BEV_OPT_CLOSE_ON_FREE)
|
||||
mbedtls_ssl_free(ctx->ssl);
|
||||
mm_free(ctx);
|
||||
}
|
||||
static int
|
||||
mbedtls_context_renegotiate(void *ssl)
|
||||
{
|
||||
struct mbedtls_context *ctx = ssl;
|
||||
return mbedtls_ssl_renegotiate(ctx->ssl);
|
||||
}
|
||||
static int
|
||||
mbedtls_context_write(void *ssl, const unsigned char *buf, size_t len)
|
||||
{
|
||||
struct mbedtls_context *ctx = ssl;
|
||||
return mbedtls_ssl_write(ctx->ssl, buf, len);
|
||||
}
|
||||
static int
|
||||
mbedtls_context_read(void *ssl, unsigned char *buf, size_t len)
|
||||
{
|
||||
struct mbedtls_context *ctx = ssl;
|
||||
return mbedtls_ssl_read(ctx->ssl, buf, len);
|
||||
}
|
||||
static size_t
|
||||
mbedtls_context_pending(void *ssl)
|
||||
{
|
||||
struct mbedtls_context *ctx = ssl;
|
||||
return mbedtls_ssl_get_bytes_avail(ctx->ssl);
|
||||
}
|
||||
static int
|
||||
mbedtls_context_handshake(void *ssl)
|
||||
{
|
||||
struct mbedtls_context *ctx = ssl;
|
||||
return mbedtls_ssl_handshake(ctx->ssl);
|
||||
}
|
||||
static int
|
||||
mbedtls_get_error(void *ssl, int ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
static void
|
||||
mbedtls_clear_error(void)
|
||||
{
|
||||
}
|
||||
static int
|
||||
mbedtls_clear(void *ssl)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
static void
|
||||
mbedtls_set_ssl_noops(void *ssl)
|
||||
{
|
||||
}
|
||||
static int
|
||||
mbedtls_is_ok(int err)
|
||||
{
|
||||
return err == 0;
|
||||
}
|
||||
static int
|
||||
mbedtls_is_want_read(int err)
|
||||
{
|
||||
return err == MBEDTLS_ERR_SSL_WANT_READ;
|
||||
}
|
||||
static int
|
||||
mbedtls_is_want_write(int err)
|
||||
{
|
||||
return err == MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
}
|
||||
|
||||
static evutil_socket_t
|
||||
be_mbedtls_get_fd(void *ssl)
|
||||
{
|
||||
struct bufferevent_ssl *bev = ssl;
|
||||
struct mbedtls_context *ctx = bev->ssl;
|
||||
return ctx->net.fd;
|
||||
}
|
||||
|
||||
static int be_mbedtls_bio_set_fd(
|
||||
struct bufferevent_ssl *bev_ssl, evutil_socket_t fd);
|
||||
|
||||
#if 0
|
||||
static void
|
||||
print_err(int val)
|
||||
{
|
||||
char buf[1024];
|
||||
mbedtls_strerror(val, buf, sizeof(buf));
|
||||
printf("Error was %d:%s\n", val, buf);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
print_err(int val)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Called to extract data from the BIO. */
|
||||
static int
|
||||
bio_bufferevent_read(void *ctx, unsigned char *out, size_t outlen)
|
||||
{
|
||||
struct bufferevent *bufev = (struct bufferevent *)ctx;
|
||||
int r = 0;
|
||||
struct evbuffer *input;
|
||||
|
||||
if (!out)
|
||||
return 0;
|
||||
if (!bufev)
|
||||
return MBEDTLS_ERR_NET_INVALID_CONTEXT;
|
||||
|
||||
input = bufferevent_get_input(bufev);
|
||||
if (evbuffer_get_length(input) == 0) {
|
||||
/* If there's no data to read, say so. */
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
} else {
|
||||
r = evbuffer_remove(input, out, outlen);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Called to write data into the BIO */
|
||||
static int
|
||||
bio_bufferevent_write(void *ctx, const unsigned char *in, size_t inlen)
|
||||
{
|
||||
struct bufferevent *bufev = (struct bufferevent *)ctx;
|
||||
struct evbuffer *output;
|
||||
size_t outlen;
|
||||
|
||||
if (!bufev)
|
||||
return MBEDTLS_ERR_NET_INVALID_CONTEXT;
|
||||
|
||||
output = bufferevent_get_output(bufev);
|
||||
outlen = evbuffer_get_length(output);
|
||||
|
||||
/* Copy only as much data onto the output buffer as can fit under the
|
||||
* high-water mark. */
|
||||
if (bufev->wm_write.high && bufev->wm_write.high <= (outlen + inlen)) {
|
||||
if (bufev->wm_write.high <= outlen) {
|
||||
/* If no data can fit, we'll need to retry later. */
|
||||
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
}
|
||||
inlen = bufev->wm_write.high - outlen;
|
||||
}
|
||||
|
||||
EVUTIL_ASSERT(inlen > 0);
|
||||
evbuffer_add(output, in, inlen);
|
||||
return inlen;
|
||||
}
|
||||
|
||||
static void
|
||||
conn_closed(struct bufferevent_ssl *bev_ssl, int when, int errcode, int ret)
|
||||
{
|
||||
int event = BEV_EVENT_ERROR;
|
||||
char buf[100];
|
||||
|
||||
if (when & BEV_EVENT_READING && ret == 0) {
|
||||
if (bev_ssl->allow_dirty_shutdown)
|
||||
event = BEV_EVENT_EOF;
|
||||
} else {
|
||||
mbedtls_strerror(errcode, buf, sizeof(buf));
|
||||
switch (errcode) {
|
||||
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
|
||||
event = BEV_EVENT_EOF;
|
||||
break;
|
||||
case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
|
||||
event_warnx("BUG: Unsupported feature %d: %s", errcode, buf);
|
||||
break;
|
||||
default:
|
||||
/* should be impossible; treat as normal error. */
|
||||
event_warnx(
|
||||
"BUG: Unexpected mbedtls error code %d: %s", errcode, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
bufferevent_ssl_put_error(bev_ssl, errcode);
|
||||
}
|
||||
|
||||
bufferevent_ssl_stop_reading(bev_ssl);
|
||||
bufferevent_ssl_stop_writing(bev_ssl);
|
||||
|
||||
bufferevent_run_eventcb_(&bev_ssl->bev.bev, when | event, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
be_mbedtls_bio_set_fd(struct bufferevent_ssl *bev_ssl, evutil_socket_t fd)
|
||||
{
|
||||
struct mbedtls_context *ctx = bev_ssl->ssl;
|
||||
if (!bev_ssl->underlying) {
|
||||
ctx->net.fd = fd;
|
||||
mbedtls_ssl_set_bio(
|
||||
ctx->ssl, &ctx->net, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
} else {
|
||||
mbedtls_ssl_set_bio(ctx->ssl, bev_ssl->underlying,
|
||||
bio_bufferevent_write, bio_bufferevent_read, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_mbedtls_get_allow_dirty_shutdown(struct bufferevent *bev)
|
||||
{
|
||||
return bufferevent_ssl_get_allow_dirty_shutdown(bev);
|
||||
}
|
||||
|
||||
void
|
||||
bufferevent_mbedtls_set_allow_dirty_shutdown(
|
||||
struct bufferevent *bev, int allow_dirty_shutdown)
|
||||
{
|
||||
bufferevent_ssl_set_allow_dirty_shutdown(bev, allow_dirty_shutdown);
|
||||
}
|
||||
|
||||
mbedtls_ssl_context *
|
||||
bufferevent_mbedtls_get_ssl(struct bufferevent *bufev)
|
||||
{
|
||||
struct mbedtls_context *ctx = NULL;
|
||||
struct bufferevent_ssl *bev_ssl = bufferevent_ssl_upcast(bufev);
|
||||
if (!bev_ssl)
|
||||
return NULL;
|
||||
ctx = bev_ssl->ssl;
|
||||
return ctx->ssl;
|
||||
}
|
||||
|
||||
int
|
||||
bufferevent_mbedtls_renegotiate(struct bufferevent *bufev)
|
||||
{
|
||||
struct bufferevent_ssl *bev_ssl = bufferevent_ssl_upcast(bufev);
|
||||
if (!bev_ssl)
|
||||
return -1;
|
||||
return bufferevent_ssl_renegotiate_impl(bufev);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
bufferevent_get_mbedtls_error(struct bufferevent *bufev)
|
||||
{
|
||||
struct bufferevent_ssl *bev_ssl = bufferevent_ssl_upcast(bufev);
|
||||
if (!bev_ssl)
|
||||
return -1;
|
||||
return bufferevent_get_ssl_error(bufev);
|
||||
}
|
||||
|
||||
static struct le_ssl_ops le_mbedtls_ops = {
|
||||
mbedtls_context_init,
|
||||
mbedtls_context_free,
|
||||
(void (*)(void *))mbedtls_ssl_free,
|
||||
mbedtls_context_renegotiate,
|
||||
mbedtls_context_write,
|
||||
mbedtls_context_read,
|
||||
mbedtls_context_pending,
|
||||
mbedtls_context_handshake,
|
||||
mbedtls_get_error,
|
||||
mbedtls_clear_error,
|
||||
mbedtls_clear,
|
||||
mbedtls_set_ssl_noops,
|
||||
mbedtls_set_ssl_noops,
|
||||
mbedtls_is_ok,
|
||||
mbedtls_is_want_read,
|
||||
mbedtls_is_want_write,
|
||||
be_mbedtls_get_fd,
|
||||
be_mbedtls_bio_set_fd,
|
||||
(void (*)(struct bufferevent_ssl *))mbedtls_set_ssl_noops,
|
||||
(void (*)(struct bufferevent_ssl *))mbedtls_set_ssl_noops,
|
||||
conn_closed,
|
||||
print_err,
|
||||
};
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_mbedtls_filter_new(struct event_base *base,
|
||||
struct bufferevent *underlying, mbedtls_ssl_context *ssl,
|
||||
enum bufferevent_ssl_state state, int options)
|
||||
{
|
||||
struct bufferevent *bev;
|
||||
|
||||
if (!underlying)
|
||||
goto err;
|
||||
|
||||
bev = bufferevent_ssl_new_impl(
|
||||
base, underlying, -1, ssl, state, options, &le_mbedtls_ops);
|
||||
|
||||
if (bev) {
|
||||
be_mbedtls_bio_set_fd(bufferevent_ssl_upcast(bev), -1);
|
||||
}
|
||||
|
||||
return bev;
|
||||
|
||||
err:
|
||||
if (options & BEV_OPT_CLOSE_ON_FREE)
|
||||
mbedtls_ssl_free(ssl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bufferevent *
|
||||
bufferevent_mbedtls_socket_new(struct event_base *base, evutil_socket_t fd,
|
||||
mbedtls_ssl_context *ssl, enum bufferevent_ssl_state state, int options)
|
||||
{
|
||||
long have_fd = -1;
|
||||
struct bufferevent *bev;
|
||||
|
||||
if (ssl->p_bio) {
|
||||
/* The SSL is already configured with bio. */
|
||||
if (ssl->f_send == mbedtls_net_send &&
|
||||
ssl->f_recv == mbedtls_net_recv) {
|
||||
have_fd = ((mbedtls_net_context *)ssl->p_bio)->fd;
|
||||
} else if (ssl->f_send == bio_bufferevent_write &&
|
||||
ssl->f_recv == bio_bufferevent_read) {
|
||||
have_fd = bufferevent_getfd(ssl->p_bio);
|
||||
} else {
|
||||
/* We don't known the fd. */
|
||||
have_fd = LONG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if (have_fd >= 0) {
|
||||
if (fd < 0) {
|
||||
/* We should learn the fd from the SSL. */
|
||||
fd = (evutil_socket_t)have_fd;
|
||||
} else if (have_fd == (long)fd) {
|
||||
/* We already know the fd from the SSL; do nothing */
|
||||
} else {
|
||||
/* We specified an fd different from that of the SSL.
|
||||
This is probably an error on our part. Fail. */
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (fd >= 0) {
|
||||
/* ... and we have an fd we want to use. */
|
||||
} else {
|
||||
/* Leave the fd unset. */
|
||||
}
|
||||
}
|
||||
|
||||
bev = bufferevent_ssl_new_impl(
|
||||
base, NULL, fd, ssl, state, options, &le_mbedtls_ops);
|
||||
|
||||
if (bev) {
|
||||
be_mbedtls_bio_set_fd(bufferevent_ssl_upcast(bev), fd);
|
||||
}
|
||||
|
||||
return bev;
|
||||
err:
|
||||
return NULL;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
1092
bufferevent_ssl.c
Normal file
1092
bufferevent_ssl.c
Normal file
File diff suppressed because it is too large
Load Diff
159
cmake/FindMbedTLS.cmake
Normal file
159
cmake/FindMbedTLS.cmake
Normal file
@ -0,0 +1,159 @@
|
||||
# Copyright 2017-2019 AVSystem <avsystem@avsystem.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#.rst:
|
||||
# FindMbedTLS
|
||||
# -----------
|
||||
#
|
||||
# Find the mbedTLS encryption library.
|
||||
#
|
||||
# Imported Targets
|
||||
# ^^^^^^^^^^^^^^^^
|
||||
#
|
||||
# This module defines the following :prop_tgt:`IMPORTED` targets:
|
||||
#
|
||||
# ``mbedtls``
|
||||
# The mbedTLS ``mbedtls`` library, if found.
|
||||
# ``mbedcrypto``
|
||||
# The mbedtls ``crypto`` library, if found.
|
||||
# ``mbedx509``
|
||||
# The mbedtls ``x509`` library, if found.
|
||||
#
|
||||
# Result Variables
|
||||
# ^^^^^^^^^^^^^^^^
|
||||
#
|
||||
# This module will set the following variables in your project:
|
||||
#
|
||||
# ``MBEDTLS_FOUND``
|
||||
# System has the mbedTLS library.
|
||||
# ``MBEDTLS_INCLUDE_DIR``
|
||||
# The mbedTLS include directory.
|
||||
# ``MBEDTLS_LIBRARY``
|
||||
# The mbedTLS SSL library.
|
||||
# ``MBEDTLS_CRYPTO_LIBRARY``
|
||||
# The mbedTLS crypto library.
|
||||
# ``MBEDTLS_X509_LIBRARY``
|
||||
# The mbedTLS x509 library.
|
||||
# ``MBEDTLS_LIBRARIES``
|
||||
# All mbedTLS libraries.
|
||||
# ``MBEDTLS_VERSION``
|
||||
# This is set to ``$major.$minor.$patch``.
|
||||
# ``MBEDTLS_VERSION_MAJOR``
|
||||
# Set to major mbedTLS version number.
|
||||
# ``MBEDTLS_VERSION_MINOR``
|
||||
# Set to minor mbedTLS version number.
|
||||
# ``MBEDTLS_VERSION_PATCH``
|
||||
# Set to patch mbedTLS version number.
|
||||
#
|
||||
# Hints
|
||||
# ^^^^^
|
||||
#
|
||||
# Set ``MBEDTLS_ROOT_DIR`` to the root directory of an mbedTLS installation.
|
||||
# Set ``MBEDTLS_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
|
||||
|
||||
if(MBEDTLS_ROOT_DIR)
|
||||
# Disable re-rooting paths in find_path/find_library.
|
||||
# This assumes MBEDTLS_ROOT_DIR is an absolute path.
|
||||
set(_EXTRA_FIND_ARGS "NO_CMAKE_FIND_ROOT_PATH")
|
||||
endif()
|
||||
|
||||
find_path(MBEDTLS_INCLUDE_DIR
|
||||
NAMES mbedtls/ssl.h
|
||||
PATH_SUFFIXES include
|
||||
HINTS ${MBEDTLS_ROOT_DIR}
|
||||
${_EXTRA_FIND_ARGS})
|
||||
|
||||
# based on https://github.com/ARMmbed/mbedtls/issues/298
|
||||
if(MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
|
||||
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" VERSION_STRING_LINE REGEX "^#define MBEDTLS_VERSION_STRING[ \\t\\n\\r]+\"[^\"]*\"$")
|
||||
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" VERSION_MAJOR_LINE REGEX "^#define MBEDTLS_VERSION_MAJOR[ \\t\\n\\r]+[0-9]+$")
|
||||
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" VERSION_MINOR_LINE REGEX "^#define MBEDTLS_VERSION_MINOR[ \\t\\n\\r]+[0-9]+$")
|
||||
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" VERSION_PATCH_LINE REGEX "^#define MBEDTLS_VERSION_PATCH[ \\t\\n\\r]+[0-9]+$")
|
||||
|
||||
string(REGEX REPLACE "^#define MBEDTLS_VERSION_STRING[ \\t\\n\\r]+\"([^\"]*)\"$" "\\1" MBEDTLS_VERSION "${VERSION_STRING_LINE}")
|
||||
string(REGEX REPLACE "^#define MBEDTLS_VERSION_MAJOR[ \\t\\n\\r]+([0-9]+)$" "\\1" MBEDTLS_VERSION_MAJOR "${VERSION_MAJOR_LINE}")
|
||||
string(REGEX REPLACE "^#define MBEDTLS_VERSION_MINOR[ \\t\\n\\r]+([0-9]+)$" "\\1" MBEDTLS_VERSION_MINOR "${VERSION_MINOR_LINE}")
|
||||
string(REGEX REPLACE "^#define MBEDTLS_VERSION_PATCH[ \\t\\n\\r]+([0-9]+)$" "\\1" MBEDTLS_VERSION_PATCH "${VERSION_PATCH_LINE}")
|
||||
endif()
|
||||
|
||||
|
||||
if(MBEDTLS_USE_STATIC_LIBS)
|
||||
set(_MBEDTLS_LIB_NAME libmbedtls.a)
|
||||
set(_MBEDTLS_CRYPTO_LIB_NAME libmbedcrypto.a)
|
||||
set(_MBEDTLS_X509_LIB_NAME libmbedx509.a)
|
||||
else()
|
||||
set(_MBEDTLS_LIB_NAME mbedtls)
|
||||
set(_MBEDTLS_CRYPTO_LIB_NAME mbedcrypto)
|
||||
set(_MBEDTLS_X509_LIB_NAME mbedx509)
|
||||
endif()
|
||||
|
||||
find_library(MBEDTLS_LIBRARY
|
||||
NAMES ${_MBEDTLS_LIB_NAME}
|
||||
PATH_SUFFIXES lib
|
||||
HINTS ${MBEDTLS_ROOT_DIR}
|
||||
${_EXTRA_FIND_ARGS})
|
||||
|
||||
find_library(MBEDTLS_CRYPTO_LIBRARY
|
||||
NAMES ${_MBEDTLS_CRYPTO_LIB_NAME}
|
||||
PATH_SUFFIXES lib
|
||||
HINTS ${MBEDTLS_ROOT_DIR}
|
||||
${_EXTRA_FIND_ARGS})
|
||||
|
||||
find_library(MBEDTLS_X509_LIBRARY
|
||||
NAMES ${_MBEDTLS_X509_LIB_NAME}
|
||||
PATH_SUFFIXES lib
|
||||
HINTS ${MBEDTLS_ROOT_DIR}
|
||||
${_EXTRA_FIND_ARGS})
|
||||
|
||||
set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY} ${MBEDTLS_X509_LIBRARY})
|
||||
|
||||
if(MBEDTLS_INCLUDE_DIR)
|
||||
set(MBEDTLS_FOUND TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(MbedTLS
|
||||
FOUND_VAR MBEDTLS_FOUND
|
||||
REQUIRED_VARS
|
||||
MBEDTLS_INCLUDE_DIR
|
||||
MBEDTLS_LIBRARY
|
||||
MBEDTLS_CRYPTO_LIBRARY
|
||||
MBEDTLS_X509_LIBRARY
|
||||
MBEDTLS_LIBRARIES
|
||||
MBEDTLS_VERSION
|
||||
VERSION_VAR MBEDTLS_VERSION)
|
||||
|
||||
|
||||
if(NOT TARGET mbedtls)
|
||||
add_library(mbedtls UNKNOWN IMPORTED)
|
||||
set_target_properties(mbedtls PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION "${MBEDTLS_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET mbedcrypto)
|
||||
add_library(mbedcrypto UNKNOWN IMPORTED)
|
||||
set_target_properties(mbedcrypto PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION "${MBEDTLS_CRYPTO_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET mbedx509)
|
||||
add_library(mbedx509 UNKNOWN IMPORTED)
|
||||
set_target_properties(mbedx509 PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
IMPORTED_LOCATION "${MBEDTLS_X509_LIBRARY}")
|
||||
endif()
|
11
configure.ac
11
configure.ac
@ -60,6 +60,9 @@ AC_ARG_ENABLE(malloc-replacement,
|
||||
AC_ARG_ENABLE(openssl,
|
||||
AS_HELP_STRING(--disable-openssl, disable support for openssl encryption),
|
||||
[], [enable_openssl=yes])
|
||||
AC_ARG_ENABLE(mbedtls,
|
||||
AS_HELP_STRING(--disable-mbedtls, disable support for mbedtls encryption),
|
||||
[], [enable_mbedtls=yes])
|
||||
AC_ARG_ENABLE(debug-mode,
|
||||
AS_HELP_STRING(--disable-debug-mode, disable support for running in debug mode),
|
||||
[], [enable_debug_mode=yes])
|
||||
@ -179,6 +182,7 @@ AC_SUBST(OPENSSL_LIBADD)
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
LIBEVENT_OPENSSL
|
||||
LIBEVENT_MBEDTLS
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_CHECK_HEADERS([ \
|
||||
@ -804,7 +808,7 @@ if test x$enable_debug_mode = xno; then
|
||||
[Define if libevent should build without support for a debug mode])
|
||||
fi
|
||||
|
||||
dnl check if we should enable verbose debugging
|
||||
dnl check if we should enable verbose debugging
|
||||
if test x$enable_verbose_debug = xyes; then
|
||||
CFLAGS="$CFLAGS -DUSE_DEBUG"
|
||||
fi
|
||||
@ -812,6 +816,9 @@ fi
|
||||
dnl check if we have and should use OpenSSL
|
||||
AM_CONDITIONAL(OPENSSL, [test "$enable_openssl" != "no" && test "$have_openssl" = "yes"])
|
||||
|
||||
# check if we have and should use mbedtls
|
||||
AM_CONDITIONAL(MBEDTLS, [test "$enable_mbedtls" != "no" && test "$have_mbedtls" = "yes"])
|
||||
|
||||
dnl enable some warnings by default
|
||||
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"],[],[-Werror])
|
||||
|
||||
@ -961,5 +968,5 @@ DX_INIT_DOXYGEN([libevent], [${top_srcdir}/Doxyfile], [doxygen])
|
||||
AM_CONDITIONAL([ENABLE_DOXYGEN], [test "$DX_FLAG_doc" = "1"])
|
||||
AM_CONDITIONAL([ENABLE_DOXYGEN_MAN], [test "$DX_FLAG_man" = "1"])
|
||||
|
||||
AC_CONFIG_FILES( [libevent.pc libevent_openssl.pc libevent_pthreads.pc libevent_core.pc libevent_extra.pc] )
|
||||
AC_CONFIG_FILES( [libevent.pc libevent_mbedtls.pc libevent_openssl.pc libevent_pthreads.pc libevent_core.pc libevent_extra.pc] )
|
||||
AC_OUTPUT(Makefile)
|
||||
|
@ -214,6 +214,9 @@
|
||||
/* Define if the system has openssl */
|
||||
#cmakedefine EVENT__HAVE_OPENSSL 1
|
||||
|
||||
/* Define if the system has mbedtls */
|
||||
#cmakedefine EVENT__HAVE_MBEDTLS 1
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
#cmakedefine EVENT__HAVE_PIPE 1
|
||||
|
||||
|
@ -39,9 +39,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This is what openssl's SSL objects are underneath. */
|
||||
struct ssl_st;
|
||||
|
||||
/**
|
||||
The state of an SSL object to be used when creating a new
|
||||
SSL bufferevent.
|
||||
@ -53,6 +50,9 @@ enum bufferevent_ssl_state {
|
||||
};
|
||||
|
||||
#if defined(EVENT__HAVE_OPENSSL) || defined(EVENT_IN_DOXYGEN_)
|
||||
/* This is what openssl's SSL objects are underneath. */
|
||||
struct ssl_st;
|
||||
|
||||
/**
|
||||
Create a new SSL bufferevent to send its data over another bufferevent.
|
||||
|
||||
@ -125,6 +125,81 @@ int bufferevent_ssl_renegotiate(struct bufferevent *bev);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
unsigned long bufferevent_get_openssl_error(struct bufferevent *bev);
|
||||
|
||||
#endif
|
||||
#if defined(EVENT__HAVE_MBEDTLS) || defined(EVENT_IN_DOXYGEN_)
|
||||
struct mbedtls_ssl_context;
|
||||
/**
|
||||
Create a new SSL bufferevent to send its data over another bufferevent.
|
||||
|
||||
@param base An event_base to use to detect reading and writing. It
|
||||
must also be the base for the underlying bufferevent.
|
||||
@param underlying A socket to use for this SSL
|
||||
@param ssl A SSL* object from openssl.
|
||||
@param state The current state of the SSL connection
|
||||
@param options One or more bufferevent_options
|
||||
@return A new bufferevent on success, or NULL on failure
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct bufferevent *
|
||||
bufferevent_mbedtls_filter_new(struct event_base *base,
|
||||
struct bufferevent *underlying,
|
||||
struct mbedtls_ssl_context *ssl,
|
||||
enum bufferevent_ssl_state state,
|
||||
int options);
|
||||
|
||||
/**
|
||||
Create a new SSL bufferevent to send its data over an SSL * on a socket.
|
||||
|
||||
@param base An event_base to use to detect reading and writing
|
||||
@param fd A socket to use for this SSL
|
||||
@param ssl A SSL* object from mbedtls.
|
||||
@param state The current state of the SSL connection
|
||||
@param options One or more bufferevent_options
|
||||
@return A new bufferevent on success, or NULL on failure.
|
||||
*/
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct bufferevent *
|
||||
bufferevent_mbedtls_socket_new(struct event_base *base,
|
||||
evutil_socket_t fd,
|
||||
struct mbedtls_ssl_context *ssl,
|
||||
enum bufferevent_ssl_state state,
|
||||
int options);
|
||||
|
||||
/** Control how to report dirty SSL shutdowns.
|
||||
|
||||
If the peer (or the network, or an attacker) closes the TCP
|
||||
connection before closing the SSL channel, and the protocol is SSL >= v3,
|
||||
this is a "dirty" shutdown. If allow_dirty_shutdown is 0 (default),
|
||||
this is reported as BEV_EVENT_ERROR.
|
||||
|
||||
If instead allow_dirty_shutdown=1, a dirty shutdown is reported as
|
||||
BEV_EVENT_EOF.
|
||||
|
||||
(Note that if the protocol is < SSLv3, you will always receive
|
||||
BEV_EVENT_EOF, since SSL 2 and earlier cannot distinguish a secure
|
||||
connection close from a dirty one. This is one reason (among many)
|
||||
not to use SSL 2.)
|
||||
*/
|
||||
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int bufferevent_mbedtls_get_allow_dirty_shutdown(struct bufferevent *bev);
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void bufferevent_mbedtls_set_allow_dirty_shutdown(struct bufferevent *bev,
|
||||
int allow_dirty_shutdown);
|
||||
|
||||
/** Return the underlying mbedtls SSL * object for an SSL bufferevent. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
struct mbedtls_ssl_context *
|
||||
bufferevent_mbedtls_get_ssl(struct bufferevent *bufev);
|
||||
|
||||
/** Tells a bufferevent to begin SSL renegotiation. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
int bufferevent_mbedtls_renegotiate(struct bufferevent *bev);
|
||||
|
||||
/** Return the most recent OpenSSL error reported on an SSL bufferevent. */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
unsigned long bufferevent_get_mbedtls_error(struct bufferevent *bev);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -33,7 +33,8 @@
|
||||
defined(event_extra_shared_EXPORTS) || \
|
||||
defined(event_core_shared_EXPORTS) || \
|
||||
defined(event_pthreads_shared_EXPORTS) || \
|
||||
defined(event_openssl_shared_EXPORTS)
|
||||
defined(event_openssl_shared_EXPORTS) || \
|
||||
defined(event_mbedtls_shared_EXPORTS)
|
||||
|
||||
# if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
# define EVENT2_EXPORT_SYMBOL __global
|
||||
|
16
libevent_mbedtls.pc.in
Normal file
16
libevent_mbedtls.pc.in
Normal file
@ -0,0 +1,16 @@
|
||||
#libevent pkg-config source file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libevent_mbedtls
|
||||
Description: libevent_mbedtls adds mbedtls-based TLS support to libevent
|
||||
Version: @VERSION@
|
||||
Requires: libevent
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -levent_mbedtls
|
||||
Libs.private: @LIBS@ @MBEDTLS_LIBS@
|
||||
Cflags: -I${includedir} @MBEDTLS_INCS@
|
||||
|
38
m4/libevent_mbedtls.m4
Normal file
38
m4/libevent_mbedtls.m4
Normal file
@ -0,0 +1,38 @@
|
||||
dnl ######################################################################
|
||||
dnl mbedtls support
|
||||
AC_DEFUN([LIBEVENT_MBEDTLS], [
|
||||
AC_REQUIRE([NTP_PKG_CONFIG])dnl
|
||||
|
||||
case "$enable_mbedtls" in
|
||||
yes)
|
||||
case "$have_mbedtls" in
|
||||
yes) ;;
|
||||
*)
|
||||
save_LIBS="$LIBS"
|
||||
LIBS=""
|
||||
MBEDTLS_LIBS=""
|
||||
# clear cache
|
||||
unset ac_cv_search_mbedtls_ssl_init
|
||||
AC_SEARCH_LIBS([mbedtls_ssl_init], [mbedtls],
|
||||
[have_mbedtls=yes
|
||||
MBEDTLS_LIBS="$LIBS -lmbedtls -lmbedcrypto -lmbedx509 $EV_LIB_GDI $EV_LIB_WS32"],
|
||||
[have_mbedtls=no],
|
||||
[-lmbedtls -lmbedcrypto -lmbedx509 $EV_LIB_GDI $EV_LIB_WS32])
|
||||
LIBS="$save_LIBS"
|
||||
test "$have_mbedtls" = "yes" && break
|
||||
esac
|
||||
CPPFLAGS_SAVE=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $MBEDTLS_INCS"
|
||||
AC_CHECK_HEADERS([mbedtls/ssl.h], [], [have_mbedtls=no])
|
||||
CPPFLAGS=$CPPFLAGS_SAVE
|
||||
AC_SUBST(MBEDTLS_INCS)
|
||||
AC_SUBST(MBEDTLS_LIBS)
|
||||
case "$have_mbedtls" in
|
||||
yes) AC_DEFINE(HAVE_MBEDTLS, 1, [Define if the system has mbedtls]) ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
# check if we have and should use mbedtls
|
||||
AM_CONDITIONAL(MBEDTLS, [test "$enable_mbedtls" != "no" && test "$have_mbedtls" = "yes"])
|
||||
])
|
@ -40,6 +40,13 @@ noinst_HEADERS += \
|
||||
sample/openssl_hostname_validation.h
|
||||
endif
|
||||
|
||||
if MBEDTLS
|
||||
SAMPLES += sample/ssl-client-mbedtls
|
||||
sample_ssl_client_mbedtls_SOURCES = sample/ssl-client-mbedtls.c
|
||||
sample_ssl_client_mbedtls_LDADD = libevent.la libevent_mbedtls.la $(MBEDTLS_LIBS) $(MBEDTLS_LIBADD)
|
||||
sample_ssl_client_mbedtls_CPPFLAGS = $(AM_CPPFLAGS) $(MBEDTLS_INCS)
|
||||
endif
|
||||
|
||||
if BUILD_SAMPLES
|
||||
noinst_PROGRAMS += $(SAMPLES)
|
||||
endif
|
||||
|
264
sample/ssl-client-mbedtls.c
Normal file
264
sample/ssl-client-mbedtls.c
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* SSL client demonstration program
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#include "mbedtls/config.h"
|
||||
#include "mbedtls/platform.h"
|
||||
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/certs.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/dns.h>
|
||||
#include <event2/bufferevent.h>
|
||||
#include <event2/bufferevent_ssl.h>
|
||||
#include <event2/util.h>
|
||||
|
||||
#define SERVER_PORT "443"
|
||||
#define SERVER_NAME "amazon.com"
|
||||
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
|
||||
|
||||
#define DEBUG_LEVEL 1
|
||||
|
||||
static void
|
||||
my_debug(void *ctx, int level, const char *file, int line, const char *str)
|
||||
{
|
||||
((void)level);
|
||||
|
||||
mbedtls_fprintf((FILE *)ctx, "%s:%04d: %s", file, line, str);
|
||||
fflush((FILE *)ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
writecb(struct bufferevent *bev, void *arg)
|
||||
{
|
||||
fprintf(stderr, "writecb\n");
|
||||
}
|
||||
|
||||
static void
|
||||
readcb(struct bufferevent *bev, void *arg)
|
||||
{
|
||||
char buf[1000];
|
||||
size_t r = 0;
|
||||
int i;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
r = bufferevent_read(bev, buf, 800);
|
||||
fprintf(stderr, "readcb %zu\n\n", r);
|
||||
if (r > 1) {
|
||||
fwrite(buf, 1, r, stdout);
|
||||
fwrite("\n", 1, r, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eventcb(struct bufferevent *bev, short what, void *arg)
|
||||
{
|
||||
fprintf(stderr, "\n---------------eventcb %d\n", what);
|
||||
if (what & BEV_EVENT_CONNECTED) {
|
||||
const char headers[] = "GET / HTTP/1.1\r\n"
|
||||
"HOST: " SERVER_NAME "\r\n"
|
||||
"User-Agent: curl/7.65.1\r\n"
|
||||
"Connection: Keep-Alive\r\n"
|
||||
"\r\n";
|
||||
bufferevent_write(
|
||||
bev, headers, sizeof(headers) - 1); // without ending '\0'
|
||||
// bufferevent_disable(bev, EV_WRITE);
|
||||
fprintf(stderr, "write request completely\n");
|
||||
} else if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
|
||||
fprintf(stderr, "closed\n");
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_net_context server_fd;
|
||||
const char *pers = "ssl_client1";
|
||||
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_x509_crt cacert;
|
||||
|
||||
struct event_base *evbase;
|
||||
struct evdns_base *evdns;
|
||||
struct bufferevent *bev;
|
||||
struct bufferevent *bevf;
|
||||
|
||||
#ifdef WIN32
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
|
||||
wVersionRequested = MAKEWORD(2, 2);
|
||||
|
||||
err = WSAStartup(wVersionRequested, &wsaData);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
mbedtls_debug_set_threshold(DEBUG_LEVEL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 0. Initialize the RNG and the session data
|
||||
*/
|
||||
mbedtls_net_init(&server_fd);
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
mbedtls_x509_crt_init(&cacert);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
|
||||
mbedtls_printf("\n . Seeding the random number generator...");
|
||||
fflush(stdout);
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
(const unsigned char *)pers, strlen(pers))) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 0. Initialize certificates
|
||||
*/
|
||||
mbedtls_printf(" . Loading the CA root certificate ...");
|
||||
fflush(stdout);
|
||||
|
||||
ret = mbedtls_x509_crt_parse(&cacert,
|
||||
(const unsigned char *)mbedtls_test_cas_pem, mbedtls_test_cas_pem_len);
|
||||
if (ret < 0) {
|
||||
mbedtls_printf(
|
||||
" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok (%d skipped)\n", ret);
|
||||
|
||||
/*
|
||||
* 1. Start the connection
|
||||
*/
|
||||
mbedtls_printf(" . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT);
|
||||
fflush(stdout);
|
||||
|
||||
if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME, SERVER_PORT,
|
||||
MBEDTLS_NET_PROTO_TCP)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 2. Setup stuff
|
||||
*/
|
||||
mbedtls_printf(" . Setting up the SSL/TLS structure...");
|
||||
fflush(stdout);
|
||||
|
||||
if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
mbedtls_printf(
|
||||
" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_printf(" ok\n");
|
||||
|
||||
/* OPTIONAL is not optimal for security,
|
||||
* but makes interop easier in this simplified example */
|
||||
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
|
||||
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) {
|
||||
mbedtls_printf(
|
||||
" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
event_enable_debug_mode();
|
||||
evbase = event_base_new();
|
||||
evdns = evdns_base_new(evbase, 1);
|
||||
evdns_base_set_option(evdns, "randomize-case:", "0");
|
||||
|
||||
evutil_make_socket_nonblocking(server_fd.fd);
|
||||
|
||||
bev = bufferevent_socket_new(evbase, server_fd.fd, BEV_OPT_CLOSE_ON_FREE);
|
||||
bevf = bufferevent_mbedtls_filter_new(
|
||||
evbase, bev, &ssl, BUFFEREVENT_SSL_CONNECTING, BEV_OPT_CLOSE_ON_FREE);
|
||||
bev = bevf;
|
||||
bufferevent_setcb(bev, readcb, writecb, eventcb, NULL);
|
||||
|
||||
bufferevent_enable(bev, EV_READ);
|
||||
|
||||
|
||||
event_base_loop(evbase, 0);
|
||||
event_base_free(evbase);
|
||||
|
||||
|
||||
exit:
|
||||
|
||||
#ifdef MBEDTLS_ERROR_C
|
||||
if (ret != 0) {
|
||||
char error_buf[100];
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
mbedtls_net_free(&server_fd);
|
||||
|
||||
mbedtls_x509_crt_free(&cacert);
|
||||
mbedtls_ssl_free(&ssl);
|
||||
mbedtls_ssl_config_free(&conf);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
|
||||
#if defined(_WIN32)
|
||||
mbedtls_printf(" + Press Enter to exit this program.\n");
|
||||
fflush(stdout);
|
||||
getchar();
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
101
ssl-compat.h
Normal file
101
ssl-compat.h
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef SSL_COMPACT_H
|
||||
#define SSL_COMPACT_H
|
||||
|
||||
#include "event.h"
|
||||
#include "bufferevent-internal.h"
|
||||
#include "event2/bufferevent_ssl.h"
|
||||
struct bufferevent_ssl;
|
||||
|
||||
struct le_ssl_ops {
|
||||
void *(*init)(void *ssl);
|
||||
void (*free)(void *ssl, int flags);
|
||||
void (*free_raw)(void *ssl);
|
||||
int (*renegotiate)(void *ssl);
|
||||
int (*write)(void *ssl, const unsigned char *buf, size_t len);
|
||||
int (*read)(void *ssl, unsigned char *buf, size_t len);
|
||||
size_t (*pending)(void *ssl);
|
||||
int (*handshake)(void *ssl);
|
||||
int (*get_error)(void *ssl, int ret);
|
||||
void (*clear_error)(void);
|
||||
int (*clear)(void *ssl);
|
||||
void (*set_connect_state)(void *ssl);
|
||||
void (*set_accept_state)(void *ssl);
|
||||
int (*err_is_ok)(int err);
|
||||
int (*err_is_want_read)(int err);
|
||||
int (*err_is_want_write)(int err);
|
||||
evutil_socket_t (*get_fd)(void *ssl);
|
||||
int (*bio_set_fd)(struct bufferevent_ssl *ssl, evutil_socket_t fd);
|
||||
void (*init_bio_counts)(struct bufferevent_ssl *bev);
|
||||
void (*decrement_buckets)(struct bufferevent_ssl *bev);
|
||||
void (*conn_closed)(
|
||||
struct bufferevent_ssl *bev, int when, int errcode, int ret);
|
||||
void (*print_err)(int err);
|
||||
};
|
||||
|
||||
struct bio_data_counts {
|
||||
unsigned long n_written;
|
||||
unsigned long n_read;
|
||||
};
|
||||
|
||||
struct bufferevent_ssl {
|
||||
/* Shared fields with common bufferevent implementation code.
|
||||
If we were set up with an underlying bufferevent, we use the
|
||||
events here as timers only. If we have an SSL, then we use
|
||||
the events as socket events.
|
||||
*/
|
||||
struct bufferevent_private bev;
|
||||
/* An underlying bufferevent that we're directing our output to.
|
||||
If it's NULL, then we're connected to an fd, not an evbuffer. */
|
||||
struct bufferevent *underlying;
|
||||
/* The SSL context doing our encryption. */
|
||||
void *ssl;
|
||||
/* The SSL operations doing on ssl. */
|
||||
struct le_ssl_ops *ssl_ops;
|
||||
|
||||
/* A callback that's invoked when data arrives on our outbuf so we
|
||||
know to write data to the SSL. */
|
||||
struct evbuffer_cb_entry *outbuf_cb;
|
||||
|
||||
/* A count of how much data the bios have read/written total. Used
|
||||
for rate-limiting. */
|
||||
struct bio_data_counts counts;
|
||||
|
||||
/* If this value is greater than 0, then the last SSL_write blocked,
|
||||
* and we need to try it again with this many bytes. */
|
||||
ev_ssize_t last_write;
|
||||
|
||||
#define NUM_ERRORS 3
|
||||
ev_uint32_t errors[NUM_ERRORS];
|
||||
|
||||
/* When we next get available space, we should say "read" instead of
|
||||
"write". This can happen if there's a renegotiation during a read
|
||||
operation. */
|
||||
unsigned read_blocked_on_write : 1;
|
||||
/* When we next get data, we should say "write" instead of "read". */
|
||||
unsigned write_blocked_on_read : 1;
|
||||
/* Treat TCP close before SSL close on SSL >= v3 as clean EOF. */
|
||||
unsigned allow_dirty_shutdown : 1;
|
||||
/* XXX */
|
||||
unsigned n_errors : 2;
|
||||
|
||||
/* Are we currently connecting, accepting, or doing IO? */
|
||||
unsigned state : 2;
|
||||
/* If we reset fd, we sould reset state too */
|
||||
unsigned old_state : 2;
|
||||
};
|
||||
|
||||
struct bufferevent *bufferevent_ssl_new_impl(struct event_base *base,
|
||||
struct bufferevent *underlying, evutil_socket_t fd, void *ssl,
|
||||
enum bufferevent_ssl_state state, int options, struct le_ssl_ops *ssl_ops);
|
||||
struct bufferevent_ssl *bufferevent_ssl_upcast(struct bufferevent *bev);
|
||||
void bufferevent_ssl_put_error(
|
||||
struct bufferevent_ssl *bev_ssl, unsigned long err);
|
||||
void bufferevent_ssl_stop_reading(struct bufferevent_ssl *bev_ssl);
|
||||
void bufferevent_ssl_stop_writing(struct bufferevent_ssl *bev_ssl);
|
||||
int bufferevent_ssl_renegotiate_impl(struct bufferevent *bev);
|
||||
unsigned long bufferevent_get_ssl_error(struct bufferevent *bev);
|
||||
int bufferevent_ssl_get_allow_dirty_shutdown(struct bufferevent *bev);
|
||||
void bufferevent_ssl_set_allow_dirty_shutdown(
|
||||
struct bufferevent *bev, int allow_dirty_shutdown);
|
||||
|
||||
#endif /* SSL_COMPACT_H */
|
@ -9,6 +9,9 @@
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <event2/bufferevent_ssl.h>
|
||||
#elif defined(EVENT_EXPORT_TEST_COMPONENT_MBEDTLS)
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <event2/bufferevent_ssl.h>
|
||||
#endif
|
||||
|
||||
#if defined(EVENT_EXPORT_TEST_COMPONENT_EXTRA)
|
||||
@ -90,6 +93,54 @@ error:
|
||||
SSL_free(ssl);
|
||||
return r;
|
||||
}
|
||||
#elif defined(EVENT_EXPORT_TEST_COMPONENT_MBEDTLS)
|
||||
static int
|
||||
test()
|
||||
{
|
||||
struct event_base *base = NULL;
|
||||
mbedtls_ssl_config *conf = NULL;
|
||||
mbedtls_ssl_context *ssl = NULL;
|
||||
struct bufferevent *bev;
|
||||
int r = 1;
|
||||
|
||||
base = event_base_new();
|
||||
if (!base) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
conf = malloc(sizeof(*conf));
|
||||
if (!conf) {
|
||||
goto error;
|
||||
}
|
||||
mbedtls_ssl_config_init(conf);
|
||||
|
||||
ssl = malloc(sizeof(*ssl));
|
||||
if (!ssl) {
|
||||
goto error;
|
||||
}
|
||||
mbedtls_ssl_init(ssl);
|
||||
mbedtls_ssl_setup(ssl, conf);
|
||||
|
||||
bev = bufferevent_mbedtls_socket_new(base, -1, ssl,
|
||||
BUFFEREVENT_SSL_CONNECTING,
|
||||
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
|
||||
if (bev == NULL) {
|
||||
goto error;
|
||||
}
|
||||
r = 0;
|
||||
error:
|
||||
if (base)
|
||||
event_base_free(base);
|
||||
if (ssl) {
|
||||
mbedtls_ssl_free(ssl);
|
||||
free(ssl);
|
||||
}
|
||||
if (conf) {
|
||||
mbedtls_ssl_config_free(conf);
|
||||
free(conf);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
test()
|
||||
|
@ -88,13 +88,18 @@ def test_group():
|
||||
testcase("core", "core", 0)
|
||||
testcase("extra", "extra", 0)
|
||||
testcase("openssl", "openssl", 0)
|
||||
testcase("mbedtls", "mbedtls", 0)
|
||||
testcase("", "", 0)
|
||||
testcase("extra", "core", 0)
|
||||
testcase("openssl", "core", 0)
|
||||
testcase("mbedtls", "core", 0)
|
||||
testcase("core", "extra", 1)
|
||||
testcase("core", "openssl", 1)
|
||||
testcase("extra", "openssl", 1)
|
||||
testcase("openssl", "extra", 1)
|
||||
testcase("core", "mbedtls", 1)
|
||||
testcase("extra", "mbedtls", 1)
|
||||
testcase("mbedtls", "extra", 1)
|
||||
if platform.system() != "Windows":
|
||||
testcase("pthreads", "pthreads", 0)
|
||||
testcase("pthreads", "core", 0)
|
||||
@ -103,6 +108,8 @@ def test_group():
|
||||
testcase("pthreads", "extra", 1)
|
||||
testcase("pthreads", "openssl", 1)
|
||||
testcase("openssl", "pthreads", 1)
|
||||
testcase("pthreads", "mbedtls", 1)
|
||||
testcase("mbedtls", "pthreads", 1)
|
||||
|
||||
|
||||
def config_restore():
|
||||
|
@ -149,11 +149,17 @@ test_regress_CPPFLAGS = $(AM_CPPFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS) -Itest
|
||||
test_regress_LDFLAGS = $(PTHREAD_CFLAGS)
|
||||
|
||||
if OPENSSL
|
||||
test_regress_SOURCES += test/regress_ssl.c
|
||||
test_regress_SOURCES += test/regress_openssl.c
|
||||
test_regress_CPPFLAGS += $(OPENSSL_INCS)
|
||||
test_regress_LDADD += libevent_openssl.la $(OPENSSL_LIBS) ${OPENSSL_LIBADD}
|
||||
endif
|
||||
|
||||
if MBEDTLS
|
||||
test_regress_SOURCES += test/regress_mbedtls.c
|
||||
test_regress_CPPFLAGS += $(MBEDTLS_INCS)
|
||||
test_regress_LDADD += libevent_mbedtls.la $(MBEDTLS_LIBS)
|
||||
endif
|
||||
|
||||
test_bench_SOURCES = test/bench.c
|
||||
test_bench_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la
|
||||
test_bench_cascade_SOURCES = test/bench_cascade.c
|
||||
|
@ -49,7 +49,8 @@ extern struct testcase_t rpc_testcases[];
|
||||
extern struct testcase_t edgetriggered_testcases[];
|
||||
extern struct testcase_t minheap_testcases[];
|
||||
extern struct testcase_t iocp_testcases[];
|
||||
extern struct testcase_t ssl_testcases[];
|
||||
extern struct testcase_t openssl_testcases[];
|
||||
extern struct testcase_t mbedtls_testcases[];
|
||||
extern struct testcase_t listener_testcases[];
|
||||
extern struct testcase_t listener_iocp_testcases[];
|
||||
extern struct testcase_t thread_testcases[];
|
||||
|
@ -451,7 +451,10 @@ struct testgroup_t testgroups[] = {
|
||||
{ "iocp/http/", http_iocp_testcases },
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_OPENSSL
|
||||
{ "ssl/", ssl_testcases },
|
||||
{ "openssl/", openssl_testcases },
|
||||
#endif
|
||||
#ifdef EVENT__HAVE_MBEDTLS
|
||||
{ "mbedtls/", mbedtls_testcases },
|
||||
#endif
|
||||
END_OF_GROUPS
|
||||
};
|
||||
|
335
test/regress_mbedtls.c
Normal file
335
test/regress_mbedtls.c
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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/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
|
||||
|
||||
#define SSL_renegotiate mbedtls_ssl_renegotiate
|
||||
#define SSL_get_peer_certificate mbedtls_ssl_get_peer_cert
|
||||
#define SSL_new mbedtls_ssl_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 mbedtls_ssl_config *get_mbedtls_config(int endpoint);
|
||||
static mbedtls_ssl_context *mbedtls_ssl_new(mbedtls_ssl_config *config);
|
||||
static void *mbedtls_test_setup(const struct testcase_t *testcase);
|
||||
static int mbedtls_test_cleanup(const struct testcase_t *testcase, void *ptr);
|
||||
static const struct testcase_setup_t ssl_setup = {
|
||||
mbedtls_test_setup, mbedtls_test_cleanup};
|
||||
#include "regress_ssl.c"
|
||||
static mbedtls_ssl_config *the_mbedtls_conf[2] = {NULL, NULL};
|
||||
static mbedtls_ssl_context *the_mbedtls_ctx[1024] = {NULL};
|
||||
static int the_mbedtls_ctx_count = 0;
|
||||
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 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);
|
||||
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;
|
||||
}
|
||||
|
||||
static 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 (disable_tls_11_and_12) {
|
||||
mbedtls_ssl_conf_max_version(the_mbedtls_conf[endpoint],
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1);
|
||||
}
|
||||
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 i;
|
||||
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);
|
||||
|
||||
for (i = 0; i < the_mbedtls_ctx_count; i++) {
|
||||
mbedtls_ssl_free(the_mbedtls_ctx[i]);
|
||||
}
|
||||
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 mbedtls_ssl_context *
|
||||
mbedtls_ssl_new(mbedtls_ssl_config *config)
|
||||
{
|
||||
mbedtls_ssl_context *ssl = malloc(sizeof(*ssl));
|
||||
mbedtls_ssl_init(ssl);
|
||||
mbedtls_ssl_setup(ssl, config);
|
||||
the_mbedtls_ctx[the_mbedtls_ctx_count++] = ssl;
|
||||
return ssl;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
311
test/regress_openssl.c
Normal file
311
test/regress_openssl.c
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include "event2/util.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include "openssl-compat.h"
|
||||
#include "regress.h"
|
||||
#include "tinytest.h"
|
||||
#define TESTCASES_NAME openssl_testcases
|
||||
static void *ssl_test_setup(const struct testcase_t *testcase);
|
||||
static int ssl_test_cleanup(const struct testcase_t *testcase, void *ptr);
|
||||
static const struct testcase_setup_t ssl_setup = {
|
||||
ssl_test_setup, ssl_test_cleanup};
|
||||
|
||||
static X509 *the_cert;
|
||||
EVP_PKEY *the_key;
|
||||
|
||||
#define SSL_IS_CLIENT
|
||||
#define SSL_IS_SERVER
|
||||
|
||||
#define bufferevent_ssl_get_ssl bufferevent_openssl_get_ssl
|
||||
#define bufferevent_ssl_set_allow_dirty_shutdown \
|
||||
bufferevent_openssl_set_allow_dirty_shutdown
|
||||
#define bufferevent_ssl_socket_new bufferevent_openssl_socket_new
|
||||
#define bufferevent_ssl_filter_new bufferevent_openssl_filter_new
|
||||
|
||||
struct rwcount;
|
||||
static void BIO_setup(SSL *ssl, struct rwcount *rw);
|
||||
#include "regress_ssl.c"
|
||||
|
||||
EVP_PKEY *
|
||||
ssl_getkey(void)
|
||||
{
|
||||
EVP_PKEY *key;
|
||||
BIO *bio;
|
||||
|
||||
/* new read-only BIO backed by KEY. */
|
||||
bio = BIO_new_mem_buf((char *)KEY, -1);
|
||||
tt_assert(bio);
|
||||
|
||||
key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
||||
BIO_free(bio);
|
||||
tt_assert(key);
|
||||
|
||||
return key;
|
||||
end:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
X509 *
|
||||
ssl_getcert(EVP_PKEY *key)
|
||||
{
|
||||
/* Dummy code to make a quick-and-dirty valid certificate with
|
||||
OpenSSL. Don't copy this code into your own program! It does a
|
||||
number of things in a stupid and insecure way. */
|
||||
X509 *x509 = NULL;
|
||||
X509_NAME *name = NULL;
|
||||
int nid;
|
||||
time_t now = time(NULL);
|
||||
|
||||
tt_assert(key);
|
||||
|
||||
x509 = X509_new();
|
||||
tt_assert(x509);
|
||||
tt_assert(0 != X509_set_version(x509, 2));
|
||||
tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)now));
|
||||
|
||||
name = X509_NAME_new();
|
||||
tt_assert(name);
|
||||
nid = OBJ_txt2nid("commonName");
|
||||
tt_assert(NID_undef != nid);
|
||||
tt_assert(0 != X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
|
||||
(unsigned char *)"example.com", -1, -1, 0));
|
||||
|
||||
X509_set_subject_name(x509, name);
|
||||
X509_set_issuer_name(x509, name);
|
||||
X509_NAME_free(name);
|
||||
|
||||
X509_time_adj(X509_getm_notBefore(x509), 0, &now);
|
||||
now += 3600;
|
||||
X509_time_adj(X509_getm_notAfter(x509), 0, &now);
|
||||
X509_set_pubkey(x509, key);
|
||||
tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
|
||||
|
||||
return x509;
|
||||
end:
|
||||
X509_free(x509);
|
||||
X509_NAME_free(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static SSL_CTX *the_ssl_ctx = NULL;
|
||||
|
||||
SSL_CTX *
|
||||
get_ssl_ctx(void)
|
||||
{
|
||||
if (the_ssl_ctx)
|
||||
return the_ssl_ctx;
|
||||
the_ssl_ctx = SSL_CTX_new(SSLv23_method());
|
||||
if (!the_ssl_ctx)
|
||||
return NULL;
|
||||
if (disable_tls_11_and_12) {
|
||||
#ifdef SSL_OP_NO_TLSv1_2
|
||||
SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2);
|
||||
#endif
|
||||
#ifdef SSL_OP_NO_TLSv1_1
|
||||
SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1);
|
||||
#endif
|
||||
}
|
||||
return the_ssl_ctx;
|
||||
}
|
||||
|
||||
void
|
||||
init_ssl(void)
|
||||
{
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && \
|
||||
LIBRESSL_VERSION_NUMBER < 0x20700000L)
|
||||
SSL_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
SSL_load_error_strings();
|
||||
OpenSSL_add_all_algorithms();
|
||||
if (SSLeay() != OPENSSL_VERSION_NUMBER) {
|
||||
TT_DECLARE("WARN", ("Version mismatch for openssl: compiled with %lx "
|
||||
"but running with %lx",
|
||||
(unsigned long)OPENSSL_VERSION_NUMBER,
|
||||
(unsigned long)SSLeay()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *
|
||||
ssl_test_setup(const struct testcase_t *testcase)
|
||||
{
|
||||
init_ssl();
|
||||
|
||||
the_key = ssl_getkey();
|
||||
EVUTIL_ASSERT(the_key);
|
||||
|
||||
the_cert = ssl_getcert(the_key);
|
||||
EVUTIL_ASSERT(the_cert);
|
||||
|
||||
disable_tls_11_and_12 = 0;
|
||||
|
||||
return basic_test_setup(testcase);
|
||||
}
|
||||
static int
|
||||
ssl_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;
|
||||
|
||||
X509_free(the_cert);
|
||||
EVP_PKEY_free(the_key);
|
||||
|
||||
SSL_CTX_free(the_ssl_ctx);
|
||||
the_ssl_ctx = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
bio_rwcount_new(BIO *b)
|
||||
{
|
||||
BIO_set_init(b, 0);
|
||||
BIO_set_data(b, NULL);
|
||||
return 1;
|
||||
}
|
||||
static int
|
||||
bio_rwcount_free(BIO *b)
|
||||
{
|
||||
TT_BLATHER(("bio_rwcount_free: %p", b));
|
||||
if (!b)
|
||||
return 0;
|
||||
if (BIO_get_shutdown(b)) {
|
||||
BIO_set_init(b, 0);
|
||||
BIO_set_data(b, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static int
|
||||
bio_rwcount_read(BIO *b, char *out, int outlen)
|
||||
{
|
||||
struct rwcount *rw = BIO_get_data(b);
|
||||
ev_ssize_t ret = recv(rw->fd, out, outlen, 0);
|
||||
++rw->read;
|
||||
if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int
|
||||
bio_rwcount_write(BIO *b, const char *in, int inlen)
|
||||
{
|
||||
struct rwcount *rw = BIO_get_data(b);
|
||||
ev_ssize_t ret = send(rw->fd, in, inlen, 0);
|
||||
++rw->write;
|
||||
if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static long
|
||||
bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
struct rwcount *rw = BIO_get_data(b);
|
||||
long ret = 0;
|
||||
switch (cmd) {
|
||||
case BIO_C_GET_FD:
|
||||
ret = rw->fd;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = BIO_get_shutdown(b);
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
BIO_set_shutdown(b, (int)num);
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int
|
||||
bio_rwcount_puts(BIO *b, const char *s)
|
||||
{
|
||||
return bio_rwcount_write(b, s, strlen(s));
|
||||
}
|
||||
#define BIO_TYPE_LIBEVENT_RWCOUNT 0xff1
|
||||
static BIO_METHOD *methods_rwcount;
|
||||
|
||||
static BIO_METHOD *
|
||||
BIO_s_rwcount(void)
|
||||
{
|
||||
if (methods_rwcount == NULL) {
|
||||
methods_rwcount = BIO_meth_new(BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount");
|
||||
if (methods_rwcount == NULL)
|
||||
return NULL;
|
||||
BIO_meth_set_write(methods_rwcount, bio_rwcount_write);
|
||||
BIO_meth_set_read(methods_rwcount, bio_rwcount_read);
|
||||
BIO_meth_set_puts(methods_rwcount, bio_rwcount_puts);
|
||||
BIO_meth_set_ctrl(methods_rwcount, bio_rwcount_ctrl);
|
||||
BIO_meth_set_create(methods_rwcount, bio_rwcount_new);
|
||||
BIO_meth_set_destroy(methods_rwcount, bio_rwcount_free);
|
||||
}
|
||||
return methods_rwcount;
|
||||
}
|
||||
static BIO *
|
||||
BIO_new_rwcount(int close_flag)
|
||||
{
|
||||
BIO *result;
|
||||
if (!(result = BIO_new(BIO_s_rwcount())))
|
||||
return NULL;
|
||||
BIO_set_init(result, 1);
|
||||
BIO_set_data(result, NULL);
|
||||
BIO_set_shutdown(result, !!close_flag);
|
||||
return result;
|
||||
}
|
||||
static void
|
||||
BIO_setup(SSL *ssl, struct rwcount *rw)
|
||||
{
|
||||
BIO *bio;
|
||||
bio = BIO_new_rwcount(0);
|
||||
tt_assert(bio);
|
||||
BIO_set_data(bio, rw);
|
||||
SSL_set_bio(ssl, bio, bio);
|
||||
end:
|
||||
return;
|
||||
}
|
@ -42,21 +42,15 @@
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include "event2/util.h"
|
||||
#include "event2/event.h"
|
||||
#include "event2/bufferevent_ssl.h"
|
||||
#include "event2/bufferevent_struct.h"
|
||||
#include "event2/buffer.h"
|
||||
#include "event2/listener.h"
|
||||
|
||||
#include "regress.h"
|
||||
#include "tinytest.h"
|
||||
#include "tinytest_macros.h"
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include "openssl-compat.h"
|
||||
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
@ -98,91 +92,7 @@ static const char KEY[] =
|
||||
"lhdEOj7mAgHwGwwVZWOgs9Lq6vfztnSuhqjha1daESY6kDscPIQ=\n"
|
||||
"-----END RSA PRIVATE KEY-----\n";
|
||||
|
||||
EVP_PKEY *
|
||||
ssl_getkey(void)
|
||||
{
|
||||
EVP_PKEY *key;
|
||||
BIO *bio;
|
||||
|
||||
/* new read-only BIO backed by KEY. */
|
||||
bio = BIO_new_mem_buf((char*)KEY, -1);
|
||||
tt_assert(bio);
|
||||
|
||||
key = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL);
|
||||
BIO_free(bio);
|
||||
tt_assert(key);
|
||||
|
||||
return key;
|
||||
end:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
X509 *
|
||||
ssl_getcert(EVP_PKEY *key)
|
||||
{
|
||||
/* Dummy code to make a quick-and-dirty valid certificate with
|
||||
OpenSSL. Don't copy this code into your own program! It does a
|
||||
number of things in a stupid and insecure way. */
|
||||
X509 *x509 = NULL;
|
||||
X509_NAME *name = NULL;
|
||||
int nid;
|
||||
time_t now = time(NULL);
|
||||
|
||||
tt_assert(key);
|
||||
|
||||
x509 = X509_new();
|
||||
tt_assert(x509);
|
||||
tt_assert(0 != X509_set_version(x509, 2));
|
||||
tt_assert(0 != ASN1_INTEGER_set(X509_get_serialNumber(x509),
|
||||
(long)now));
|
||||
|
||||
name = X509_NAME_new();
|
||||
tt_assert(name);
|
||||
nid = OBJ_txt2nid("commonName");
|
||||
tt_assert(NID_undef != nid);
|
||||
tt_assert(0 != X509_NAME_add_entry_by_NID(
|
||||
name, nid, MBSTRING_ASC, (unsigned char*)"example.com",
|
||||
-1, -1, 0));
|
||||
|
||||
X509_set_subject_name(x509, name);
|
||||
X509_set_issuer_name(x509, name);
|
||||
X509_NAME_free(name);
|
||||
|
||||
X509_time_adj(X509_getm_notBefore(x509), 0, &now);
|
||||
now += 3600;
|
||||
X509_time_adj(X509_getm_notAfter(x509), 0, &now);
|
||||
X509_set_pubkey(x509, key);
|
||||
tt_assert(0 != X509_sign(x509, key, EVP_sha1()));
|
||||
|
||||
return x509;
|
||||
end:
|
||||
X509_free(x509);
|
||||
X509_NAME_free(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int disable_tls_11_and_12 = 0;
|
||||
static SSL_CTX *the_ssl_ctx = NULL;
|
||||
|
||||
SSL_CTX *
|
||||
get_ssl_ctx(void)
|
||||
{
|
||||
if (the_ssl_ctx)
|
||||
return the_ssl_ctx;
|
||||
the_ssl_ctx = SSL_CTX_new(SSLv23_method());
|
||||
if (!the_ssl_ctx)
|
||||
return NULL;
|
||||
if (disable_tls_11_and_12) {
|
||||
#ifdef SSL_OP_NO_TLSv1_2
|
||||
SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_2);
|
||||
#endif
|
||||
#ifdef SSL_OP_NO_TLSv1_1
|
||||
SSL_CTX_set_options(the_ssl_ctx, SSL_OP_NO_TLSv1_1);
|
||||
#endif
|
||||
}
|
||||
return the_ssl_ctx;
|
||||
}
|
||||
|
||||
static int test_is_done;
|
||||
static int n_connected;
|
||||
static int got_close;
|
||||
@ -192,70 +102,6 @@ static int renegotiate_at = -1;
|
||||
static int stop_when_connected;
|
||||
static int pending_connect_events;
|
||||
static struct event_base *exit_base;
|
||||
static X509 *the_cert;
|
||||
EVP_PKEY *the_key;
|
||||
|
||||
void
|
||||
init_ssl(void)
|
||||
{
|
||||
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
|
||||
SSL_library_init();
|
||||
ERR_load_crypto_strings();
|
||||
SSL_load_error_strings();
|
||||
OpenSSL_add_all_algorithms();
|
||||
if (SSLeay() != OPENSSL_VERSION_NUMBER) {
|
||||
TT_DECLARE("WARN",
|
||||
("Version mismatch for openssl: compiled with %lx but running with %lx",
|
||||
(unsigned long)OPENSSL_VERSION_NUMBER, (unsigned long)SSLeay()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *
|
||||
ssl_test_setup(const struct testcase_t *testcase)
|
||||
{
|
||||
init_ssl();
|
||||
|
||||
the_key = ssl_getkey();
|
||||
EVUTIL_ASSERT(the_key);
|
||||
|
||||
the_cert = ssl_getcert(the_key);
|
||||
EVUTIL_ASSERT(the_cert);
|
||||
|
||||
disable_tls_11_and_12 = 0;
|
||||
|
||||
return basic_test_setup(testcase);
|
||||
}
|
||||
static int
|
||||
ssl_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;
|
||||
|
||||
X509_free(the_cert);
|
||||
EVP_PKEY_free(the_key);
|
||||
|
||||
SSL_CTX_free(the_ssl_ctx);
|
||||
the_ssl_ctx = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
const struct testcase_setup_t ssl_setup = {
|
||||
ssl_test_setup, ssl_test_cleanup
|
||||
};
|
||||
|
||||
|
||||
/* ====================
|
||||
@ -285,7 +131,7 @@ enum regress_openssl_type
|
||||
};
|
||||
|
||||
static void
|
||||
bufferevent_openssl_check_fd(struct bufferevent *bev, int filter)
|
||||
bufferevent_ssl_check_fd(struct bufferevent *bev, int filter)
|
||||
{
|
||||
tt_fd_op(bufferevent_getfd(bev), !=, EVUTIL_INVALID_SOCKET);
|
||||
tt_fd_op(bufferevent_setfd(bev, EVUTIL_INVALID_SOCKET), ==, 0);
|
||||
@ -299,7 +145,7 @@ end:
|
||||
;
|
||||
}
|
||||
static void
|
||||
bufferevent_openssl_check_freed(struct bufferevent *bev)
|
||||
bufferevent_ssl_check_freed(struct bufferevent *bev)
|
||||
{
|
||||
tt_int_op(event_pending(&bev->ev_read, EVLIST_ALL, NULL), ==, 0);
|
||||
tt_int_op(event_pending(&bev->ev_write, EVLIST_ALL, NULL), ==, 0);
|
||||
@ -339,14 +185,15 @@ respond_to_number(struct bufferevent *bev, void *ctx)
|
||||
return;
|
||||
}
|
||||
if ((type & REGRESS_OPENSSL_CLIENT) && n == renegotiate_at) {
|
||||
SSL_renegotiate(bufferevent_openssl_get_ssl(bev));
|
||||
SSL_renegotiate(bufferevent_ssl_get_ssl(bev));
|
||||
}
|
||||
++n;
|
||||
evbuffer_add_printf(bufferevent_get_output(bev),
|
||||
"%d\n", n);
|
||||
TT_BLATHER(("Done reading; now writing."));
|
||||
bufferevent_enable(bev, EV_WRITE);
|
||||
bufferevent_disable(bev, EV_READ);
|
||||
// we shouldn't disable EV_READ here, otherwise we wouldn't got close cb
|
||||
// bufferevent_disable(bev, EV_READ);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -372,7 +219,7 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
|
||||
if (what & BEV_EVENT_CONNECTED) {
|
||||
SSL *ssl;
|
||||
++n_connected;
|
||||
ssl = bufferevent_openssl_get_ssl(bev);
|
||||
ssl = bufferevent_ssl_get_ssl(bev);
|
||||
tt_assert(ssl);
|
||||
peer_cert = SSL_get_peer_certificate(ssl);
|
||||
if (type & REGRESS_OPENSSL_SERVER) {
|
||||
@ -391,30 +238,30 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
|
||||
TT_BLATHER(("Got a good EOF"));
|
||||
++got_close;
|
||||
if (type & REGRESS_OPENSSL_FD) {
|
||||
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||
bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||
}
|
||||
if (type & REGRESS_OPENSSL_FREED) {
|
||||
bufferevent_openssl_check_freed(bev);
|
||||
bufferevent_ssl_check_freed(bev);
|
||||
}
|
||||
bufferevent_free(bev);
|
||||
} else if (what & BEV_EVENT_ERROR) {
|
||||
TT_BLATHER(("Got an error."));
|
||||
++got_error;
|
||||
if (type & REGRESS_OPENSSL_FD) {
|
||||
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||
bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||
}
|
||||
if (type & REGRESS_OPENSSL_FREED) {
|
||||
bufferevent_openssl_check_freed(bev);
|
||||
bufferevent_ssl_check_freed(bev);
|
||||
}
|
||||
bufferevent_free(bev);
|
||||
} else if (what & BEV_EVENT_TIMEOUT) {
|
||||
TT_BLATHER(("Got timeout."));
|
||||
++got_timeout;
|
||||
if (type & REGRESS_OPENSSL_FD) {
|
||||
bufferevent_openssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||
bufferevent_ssl_check_fd(bev, type & REGRESS_OPENSSL_FILTER);
|
||||
}
|
||||
if (type & REGRESS_OPENSSL_FREED) {
|
||||
bufferevent_openssl_check_freed(bev);
|
||||
bufferevent_ssl_check_freed(bev);
|
||||
}
|
||||
bufferevent_free(bev);
|
||||
}
|
||||
@ -434,14 +281,14 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
|
||||
int state2 = is_open ? BUFFEREVENT_SSL_OPEN :BUFFEREVENT_SSL_ACCEPTING;
|
||||
int dirty_shutdown = type & REGRESS_OPENSSL_DIRTY_SHUTDOWN;
|
||||
if (fd_pair) {
|
||||
*bev1_out = bufferevent_openssl_socket_new(
|
||||
*bev1_out = bufferevent_ssl_socket_new(
|
||||
base, fd_pair[0], ssl1, state1, flags);
|
||||
*bev2_out = bufferevent_openssl_socket_new(
|
||||
*bev2_out = bufferevent_ssl_socket_new(
|
||||
base, fd_pair[1], ssl2, state2, flags);
|
||||
} else {
|
||||
*bev1_out = bufferevent_openssl_filter_new(
|
||||
*bev1_out = bufferevent_ssl_filter_new(
|
||||
base, underlying_pair[0], ssl1, state1, flags);
|
||||
*bev2_out = bufferevent_openssl_filter_new(
|
||||
*bev2_out = bufferevent_ssl_filter_new(
|
||||
base, underlying_pair[1], ssl2, state2, flags);
|
||||
|
||||
}
|
||||
@ -450,8 +297,8 @@ open_ssl_bufevs(struct bufferevent **bev1_out, struct bufferevent **bev2_out,
|
||||
bufferevent_setcb(*bev2_out, respond_to_number, done_writing_cb,
|
||||
eventcb, (void*)(REGRESS_OPENSSL_SERVER | (long)type));
|
||||
|
||||
bufferevent_openssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown);
|
||||
bufferevent_openssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown);
|
||||
bufferevent_ssl_set_allow_dirty_shutdown(*bev1_out, dirty_shutdown);
|
||||
bufferevent_ssl_set_allow_dirty_shutdown(*bev2_out, dirty_shutdown);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -478,8 +325,8 @@ regress_bufferevent_openssl(void *arg)
|
||||
renegotiate_at = 600;
|
||||
}
|
||||
|
||||
ssl1 = SSL_new(get_ssl_ctx());
|
||||
ssl2 = SSL_new(get_ssl_ctx());
|
||||
ssl1 = SSL_new(get_ssl_ctx(SSL_IS_CLIENT));
|
||||
ssl2 = SSL_new(get_ssl_ctx(SSL_IS_SERVER));
|
||||
|
||||
SSL_use_certificate(ssl2, the_cert);
|
||||
SSL_use_PrivateKey(ssl2, the_key);
|
||||
@ -581,14 +428,14 @@ acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
|
||||
struct basic_test_data *data = arg;
|
||||
struct bufferevent *bev;
|
||||
enum regress_openssl_type type;
|
||||
SSL *ssl = SSL_new(get_ssl_ctx());
|
||||
SSL *ssl = SSL_new(get_ssl_ctx(SSL_IS_SERVER));
|
||||
|
||||
type = (enum regress_openssl_type)data->setup_data;
|
||||
|
||||
SSL_use_certificate(ssl, the_cert);
|
||||
SSL_use_PrivateKey(ssl, the_key);
|
||||
|
||||
bev = bufferevent_openssl_socket_new(
|
||||
bev = bufferevent_ssl_socket_new(
|
||||
data->base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
|
||||
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||
tt_assert(bev);
|
||||
@ -618,110 +465,6 @@ struct rwcount
|
||||
size_t read;
|
||||
size_t write;
|
||||
};
|
||||
static int
|
||||
bio_rwcount_new(BIO *b)
|
||||
{
|
||||
BIO_set_init(b, 0);
|
||||
BIO_set_data(b, NULL);
|
||||
return 1;
|
||||
}
|
||||
static int
|
||||
bio_rwcount_free(BIO *b)
|
||||
{
|
||||
TT_BLATHER(("bio_rwcount_free: %p", b));
|
||||
if (!b)
|
||||
return 0;
|
||||
if (BIO_get_shutdown(b)) {
|
||||
BIO_set_init(b, 0);
|
||||
BIO_set_data(b, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static int
|
||||
bio_rwcount_read(BIO *b, char *out, int outlen)
|
||||
{
|
||||
struct rwcount *rw = BIO_get_data(b);
|
||||
ev_ssize_t ret = recv(rw->fd, out, outlen, 0);
|
||||
++rw->read;
|
||||
if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
|
||||
BIO_set_retry_read(b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int
|
||||
bio_rwcount_write(BIO *b, const char *in, int inlen)
|
||||
{
|
||||
struct rwcount *rw = BIO_get_data(b);
|
||||
ev_ssize_t ret = send(rw->fd, in, inlen, 0);
|
||||
++rw->write;
|
||||
if (ret == -1 && EVUTIL_ERR_RW_RETRIABLE(EVUTIL_SOCKET_ERROR())) {
|
||||
BIO_set_retry_write(b);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static long
|
||||
bio_rwcount_ctrl(BIO *b, int cmd, long num, void *ptr)
|
||||
{
|
||||
struct rwcount *rw = BIO_get_data(b);
|
||||
long ret = 0;
|
||||
switch (cmd) {
|
||||
case BIO_C_GET_FD:
|
||||
ret = rw->fd;
|
||||
break;
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = BIO_get_shutdown(b);
|
||||
break;
|
||||
case BIO_CTRL_SET_CLOSE:
|
||||
BIO_set_shutdown(b, (int)num);
|
||||
break;
|
||||
case BIO_CTRL_PENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_WPENDING:
|
||||
ret = 0;
|
||||
break;
|
||||
case BIO_CTRL_DUP:
|
||||
case BIO_CTRL_FLUSH:
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int
|
||||
bio_rwcount_puts(BIO *b, const char *s)
|
||||
{
|
||||
return bio_rwcount_write(b, s, strlen(s));
|
||||
}
|
||||
#define BIO_TYPE_LIBEVENT_RWCOUNT 0xff1
|
||||
static BIO_METHOD *methods_rwcount;
|
||||
|
||||
static BIO_METHOD *
|
||||
BIO_s_rwcount(void)
|
||||
{
|
||||
if (methods_rwcount == NULL) {
|
||||
methods_rwcount = BIO_meth_new(BIO_TYPE_LIBEVENT_RWCOUNT, "rwcount");
|
||||
if (methods_rwcount == NULL)
|
||||
return NULL;
|
||||
BIO_meth_set_write(methods_rwcount, bio_rwcount_write);
|
||||
BIO_meth_set_read(methods_rwcount, bio_rwcount_read);
|
||||
BIO_meth_set_puts(methods_rwcount, bio_rwcount_puts);
|
||||
BIO_meth_set_ctrl(methods_rwcount, bio_rwcount_ctrl);
|
||||
BIO_meth_set_create(methods_rwcount, bio_rwcount_new);
|
||||
BIO_meth_set_destroy(methods_rwcount, bio_rwcount_free);
|
||||
}
|
||||
return methods_rwcount;
|
||||
}
|
||||
static BIO *
|
||||
BIO_new_rwcount(int close_flag)
|
||||
{
|
||||
BIO *result;
|
||||
if (!(result = BIO_new(BIO_s_rwcount())))
|
||||
return NULL;
|
||||
BIO_set_init(result, 1);
|
||||
BIO_set_data(result, NULL);
|
||||
BIO_set_shutdown(result, !!close_flag);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
regress_bufferevent_openssl_connect(void *arg)
|
||||
@ -755,10 +498,10 @@ regress_bufferevent_openssl_connect(void *arg)
|
||||
tt_assert(listener);
|
||||
tt_assert(evconnlistener_get_fd(listener) >= 0);
|
||||
|
||||
ssl = SSL_new(get_ssl_ctx());
|
||||
ssl = SSL_new(get_ssl_ctx(SSL_IS_CLIENT));
|
||||
tt_assert(ssl);
|
||||
|
||||
bev = bufferevent_openssl_socket_new(
|
||||
bev = bufferevent_ssl_socket_new(
|
||||
data->base, -1, ssl,
|
||||
BUFFEREVENT_SSL_CONNECTING,
|
||||
BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
|
||||
@ -777,13 +520,8 @@ regress_bufferevent_openssl_connect(void *arg)
|
||||
/* Possible only when we have fd, since be_openssl can and will overwrite
|
||||
* bio otherwise before */
|
||||
if (type & REGRESS_OPENSSL_SLEEP) {
|
||||
BIO *bio;
|
||||
|
||||
rw.fd = bufferevent_getfd(bev);
|
||||
bio = BIO_new_rwcount(0);
|
||||
tt_assert(bio);
|
||||
BIO_set_data(bio, &rw);
|
||||
SSL_set_bio(ssl, bio, bio);
|
||||
BIO_setup(ssl, &rw);
|
||||
}
|
||||
evbuffer_add_printf(bufferevent_get_output(bev), "1\n");
|
||||
bufferevent_enable(bev, EV_READ|EV_WRITE);
|
||||
@ -859,12 +597,12 @@ wm_acceptcb(struct evconnlistener *listener, evutil_socket_t fd,
|
||||
struct wm_context *ctx = arg;
|
||||
struct bufferevent *bev;
|
||||
struct event_base *base = evconnlistener_get_base(listener);
|
||||
SSL *ssl = SSL_new(get_ssl_ctx());
|
||||
SSL *ssl = SSL_new(get_ssl_ctx(SSL_IS_SERVER));
|
||||
|
||||
SSL_use_certificate(ssl, the_cert);
|
||||
SSL_use_PrivateKey(ssl, the_key);
|
||||
|
||||
bev = bufferevent_openssl_socket_new(
|
||||
bev = bufferevent_ssl_socket_new(
|
||||
base, fd, ssl, BUFFEREVENT_SSL_ACCEPTING, ctx->flags);
|
||||
|
||||
TT_BLATHER(("wm_transfer-%s(%p): accept",
|
||||
@ -940,16 +678,16 @@ regress_bufferevent_openssl_wm(void *arg)
|
||||
tt_assert(listener);
|
||||
tt_assert(evconnlistener_get_fd(listener) >= 0);
|
||||
|
||||
ssl = SSL_new(get_ssl_ctx());
|
||||
ssl = SSL_new(get_ssl_ctx(SSL_IS_CLIENT));
|
||||
tt_assert(ssl);
|
||||
|
||||
if (type & REGRESS_OPENSSL_FILTER) {
|
||||
bev = bufferevent_socket_new(data->base, -1, client.flags);
|
||||
tt_assert(bev);
|
||||
bev = bufferevent_openssl_filter_new(
|
||||
bev = bufferevent_ssl_filter_new(
|
||||
base, bev, ssl, BUFFEREVENT_SSL_CONNECTING, client.flags);
|
||||
} else {
|
||||
bev = bufferevent_openssl_socket_new(
|
||||
bev = bufferevent_ssl_socket_new(
|
||||
data->base, -1, ssl,
|
||||
BUFFEREVENT_SSL_CONNECTING,
|
||||
client.flags);
|
||||
@ -988,7 +726,7 @@ end:
|
||||
event_base_loop(base, EVLOOP_ONCE);
|
||||
}
|
||||
|
||||
struct testcase_t ssl_testcases[] = {
|
||||
struct testcase_t TESTCASES_NAME[] = {
|
||||
#define T(a) ((void *)(a))
|
||||
{ "bufferevent_socketpair", regress_bufferevent_openssl,
|
||||
TT_ISOLATED, &ssl_setup, T(REGRESS_OPENSSL_SOCKETPAIR) },
|
||||
@ -1057,12 +795,10 @@ struct testcase_t ssl_testcases[] = {
|
||||
{ "bufferevent_socketpair_timeout_freed_fd", regress_bufferevent_openssl,
|
||||
TT_ISOLATED, &ssl_setup,
|
||||
T(REGRESS_OPENSSL_SOCKETPAIR | REGRESS_OPENSSL_TIMEOUT | REGRESS_OPENSSL_FREED | REGRESS_OPENSSL_FD) },
|
||||
|
||||
{ "bufferevent_connect", regress_bufferevent_openssl_connect,
|
||||
TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
|
||||
{ "bufferevent_connect_sleep", regress_bufferevent_openssl_connect,
|
||||
TT_FORK|TT_NEED_BASE, &ssl_setup, T(REGRESS_OPENSSL_SLEEP) },
|
||||
|
||||
{ "bufferevent_wm", regress_bufferevent_openssl_wm,
|
||||
TT_FORK|TT_NEED_BASE, &ssl_setup, NULL },
|
||||
{ "bufferevent_wm_filter", regress_bufferevent_openssl_wm,
|
||||
|
Loading…
x
Reference in New Issue
Block a user