mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/asio_ssl_esp' into 'master'
asio: Use internal ssl context and engine impl Closes IDF-3432 See merge request espressif/esp-idf!15523
This commit is contained in:
commit
13978c9556
@ -11,8 +11,10 @@ set(asio_sources "asio/asio/src/asio.cpp")
|
||||
if(CONFIG_ASIO_SSL_SUPPORT)
|
||||
if(CONFIG_ASIO_USE_ESP_OPENSSL)
|
||||
list(APPEND asio_sources
|
||||
"asio/asio/src/asio_ssl.cpp"
|
||||
"port/src/esp_asio_openssl_stubs.c")
|
||||
"port/src/asio_ssl_impl.cpp"
|
||||
"port/mbedtls/src/mbedtls_context.cpp"
|
||||
"port/mbedtls/src/mbedtls_engine.cpp")
|
||||
set(asio_priv_includes "port/mbedtls/include")
|
||||
endif()
|
||||
|
||||
if(CONFIG_ASIO_USE_ESP_WOLFSSL)
|
||||
@ -23,6 +25,7 @@ endif()
|
||||
|
||||
idf_component_register(SRCS ${asio_sources}
|
||||
INCLUDE_DIRS "asio/asio/include" "port/include"
|
||||
PRIV_INCLUDE_DIRS ${asio_priv_includes}
|
||||
REQUIRES lwip)
|
||||
|
||||
if(CONFIG_ASIO_SSL_SUPPORT)
|
||||
@ -35,7 +38,7 @@ if(CONFIG_ASIO_SSL_SUPPORT)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ASIO_USE_ESP_OPENSSL)
|
||||
idf_component_get_property(esp_openssl openssl COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC ${esp_openssl})
|
||||
idf_component_get_property(mbedtls mbedtls COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC ${mbedtls})
|
||||
endif()
|
||||
endif()
|
||||
|
@ -24,4 +24,13 @@ menu "ESP-ASIO"
|
||||
bool "wolfSSL (License info in wolfSSL directory README)"
|
||||
endchoice
|
||||
|
||||
config ASIO_SSL_BIO_SIZE
|
||||
int "Size of BIO object"
|
||||
default 1024
|
||||
depends on ASIO_SSL_SUPPORT
|
||||
help
|
||||
Size in bytes of SSL-BIO implementation.
|
||||
Reducing the BIO size saves more RAM, but may slow down input output operations due to
|
||||
fragmentation.
|
||||
|
||||
endmenu
|
||||
|
@ -18,11 +18,6 @@
|
||||
# define ASIO_NO_TYPEID
|
||||
# endif // CONFIG_COMPILER_RTTI
|
||||
|
||||
//
|
||||
// Supress OpenSSL deprecation warning, when building ASIO
|
||||
//
|
||||
#define ESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
|
||||
//
|
||||
// LWIP compatibility inet and address macros/functions
|
||||
//
|
||||
@ -40,6 +35,9 @@
|
||||
# ifdef CONFIG_ASIO_USE_ESP_OPENSSL
|
||||
# define ASIO_USE_ESP_OPENSSL
|
||||
# define OPENSSL_NO_ENGINE
|
||||
# define ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
|
||||
# include "openssl_stub.hpp"
|
||||
|
||||
# elif CONFIG_ASIO_USE_ESP_WOLFSSL
|
||||
# define ASIO_USE_WOLFSSL
|
||||
# endif // CONFIG_ASIO_USE_ESP_OPENSSL
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _ESP_ASIO_OPENSSL_CONF_H
|
||||
#define _ESP_ASIO_OPENSSL_CONF_H
|
||||
#include "esp_asio_config.h"
|
||||
#include "openssl/esp_asio_openssl_stubs.h"
|
||||
|
||||
#if defined(ASIO_USE_WOLFSSL)
|
||||
// SSLv3 Methods not present in current wolfSSL library
|
||||
#define OPENSSL_NO_SSL3
|
||||
#include_next "openssl/conf.h"
|
||||
#endif // ASIO_USE_WOLFSSL
|
||||
|
||||
#endif // _ESP_ASIO_OPENSSL_CONF_H
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _ESP_ASIO_OPENSSL_DH_STUB_H
|
||||
#define _ESP_ASIO_OPENSSL_DH_STUB_H
|
||||
// Dummy header needed for ASIO compilation with esp-openssl
|
||||
|
||||
#if defined(ASIO_USE_WOLFSSL)
|
||||
#include_next "openssl/dh.h"
|
||||
#endif // ASIO_USE_WOLFSSL
|
||||
|
||||
#endif // _ESP_ASIO_OPENSSL_DH_STUB_H
|
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _ESP_ASIO_OPENSSL_STUBS_H
|
||||
#define _ESP_ASIO_OPENSSL_STUBS_H
|
||||
|
||||
/**
|
||||
* @note This header contains openssl API which are NOT implemented, and are only provided
|
||||
* as stubs or no-operations to get the ASIO library compiled and working with most
|
||||
* practical use cases as an embedded application on ESP platform
|
||||
*/
|
||||
|
||||
#if defined(ASIO_USE_WOLFSSL)
|
||||
|
||||
#include "wolfssl/ssl.h"
|
||||
// esp-wolfssl disables filesystem by default, but the ssl filesystem functions are needed for the ASIO to compile
|
||||
// - so we could either configure wolfSSL to use filesystem
|
||||
// - or use the default wolfSSL and declare the filesystem functions -- preferred option, as whenever
|
||||
// the filesystem functions are used from app code (potential security impact if private keys in a filesystem)
|
||||
// compilation fails with linking errors.
|
||||
|
||||
#if defined(NO_FILESYSTEM)
|
||||
// WolfSSL methods that are not included in standard esp-wolfssl config, must be defined here
|
||||
// as function stubs, so ASIO compiles, but would get link errors, if these functions were used.
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct WOLFSSL_CTX WOLFSSL_CTX;
|
||||
|
||||
void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth);
|
||||
int SSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, const char*);
|
||||
int SSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int);
|
||||
int SSL_CTX_use_certificate_chain_file(WOLFSSL_CTX*, const char*);
|
||||
int SSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int);
|
||||
int SSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif // NO_FILESYSTEM
|
||||
|
||||
#elif defined(ASIO_USE_ESP_OPENSSL)
|
||||
|
||||
#include "internal/ssl_x509.h"
|
||||
#include "internal/ssl_pkey.h"
|
||||
#include "mbedtls/pem.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// The most applicable OpenSSL version wrtt ASIO usage
|
||||
#define OPENSSL_VERSION_NUMBER 0x10100001L
|
||||
// SSLv2 methods not supported
|
||||
// OpenSSL port supports: TLS_ANY, TLS_1, TLS_1_1, TLS_1_2, SSL_3
|
||||
#define OPENSSL_NO_SSL2
|
||||
#define SSL2_VERSION 0x0002
|
||||
|
||||
#define SSL_R_SHORT_READ 219
|
||||
#define SSL_OP_ALL 0
|
||||
#define SSL_OP_SINGLE_DH_USE 0
|
||||
#define SSL_OP_NO_COMPRESSION 0
|
||||
// Translates mbedTLS PEM parse error, used by ASIO
|
||||
#define PEM_R_NO_START_LINE -MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT
|
||||
|
||||
#define SSL_OP_NO_SSLv2 0x01000000L
|
||||
#define SSL_OP_NO_SSLv3 0x02000000L
|
||||
#define SSL_OP_NO_TLSv1 0x04000000L
|
||||
|
||||
#define X509_FILETYPE_PEM 1
|
||||
#define X509_FILETYPE_ASN1 2
|
||||
#define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1
|
||||
#define SSL_FILETYPE_PEM X509_FILETYPE_PEM
|
||||
|
||||
#define NID_subject_alt_name 85
|
||||
|
||||
|
||||
#define GEN_DNS 2
|
||||
#define GEN_IPADD 7
|
||||
#define V_ASN1_OCTET_STRING 4
|
||||
#define V_ASN1_IA5STRING 22
|
||||
#define NID_commonName 13
|
||||
|
||||
#define SSL_CTX_get_app_data(ctx) ((void*)SSL_CTX_get_ex_data(ctx, 0))
|
||||
|
||||
/**
|
||||
* @brief Frees DH object -- not implemented
|
||||
*
|
||||
* Current implementation calls SSL_ASSERT
|
||||
*
|
||||
* @param r DH object
|
||||
*/
|
||||
void DH_free(DH *r);
|
||||
|
||||
/**
|
||||
* @brief Frees GENERAL_NAMES -- not implemented
|
||||
*
|
||||
* Current implementation calls SSL_ASSERT
|
||||
*
|
||||
* @param r GENERAL_NAMES object
|
||||
*/
|
||||
void GENERAL_NAMES_free(GENERAL_NAMES * gens);
|
||||
|
||||
/**
|
||||
* @brief Returns subject name from X509 -- not implemented
|
||||
*
|
||||
* Current implementation calls SSL_ASSERT
|
||||
*
|
||||
* @param r X509 object
|
||||
*/
|
||||
X509_NAME *X509_get_subject_name(X509 *a);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
|
||||
|
||||
/**
|
||||
* @brief Reads DH params from a bio object -- not implemented
|
||||
*
|
||||
* Current implementation calls SSL_ASSERT
|
||||
*/
|
||||
DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx);
|
||||
|
||||
/**
|
||||
* @brief Sets DH params to ssl ctx -- not implemented
|
||||
*
|
||||
* Current implementation calls SSL_ASSERT
|
||||
*/
|
||||
int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data);
|
||||
|
||||
/**
|
||||
* @brief API provaded as declaration only
|
||||
*
|
||||
*/
|
||||
void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
|
||||
|
||||
/**
|
||||
* @brief Clears any existing chain associated with the current certificate of ctx.
|
||||
*
|
||||
*/
|
||||
int SSL_CTX_clear_chain_certs(SSL_CTX *ctx);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* ASIO_USE_ESP_OPENSSL, ASIO_USE_WOLFSSL */
|
||||
#endif /* _ESP_ASIO_OPENSSL_STUBS_H */
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _ESP_ASIO_OPENSSL_RSA_STUB_H
|
||||
#define _ESP_ASIO_OPENSSL_RSA_STUB_H
|
||||
// Dummy header needed for ASIO compilation with esp-openssl
|
||||
|
||||
#if defined(ASIO_USE_WOLFSSL)
|
||||
#include_next "openssl/rsa.h"
|
||||
#endif // ASIO_USE_WOLFSSL
|
||||
|
||||
#endif // _ESP_ASIO_OPENSSL_RSA_STUB_H
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _ESP_ASIO_OPENSSL_X509V3_STUB_H
|
||||
#define _ESP_ASIO_OPENSSL_X509V3_STUB_H
|
||||
// Dummy header needed for ASIO compilation with esp-openssl
|
||||
|
||||
#if defined(ASIO_USE_WOLFSSL)
|
||||
#include_next "openssl/x509v3.h"
|
||||
#endif // ASIO_USE_WOLFSSL
|
||||
|
||||
#endif // _ESP_ASIO_OPENSSL_X509V3_STUB_H
|
46
components/asio/port/include/openssl_stub.hpp
Normal file
46
components/asio/port/include/openssl_stub.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Supply OpenSSL macros and flags for asio-ssl header files
|
||||
//
|
||||
#define OPENSSL_VERSION_NUMBER 0x10100001L
|
||||
|
||||
#define SSL_R_SHORT_READ 219
|
||||
#define SSL_OP_ALL 0
|
||||
#define SSL_OP_SINGLE_DH_USE 0
|
||||
#define SSL_OP_NO_COMPRESSION 0
|
||||
|
||||
#define SSL_OP_NO_SSLv2 0x01000000L
|
||||
#define SSL_OP_NO_SSLv3 0x02000000L
|
||||
#define SSL_OP_NO_TLSv1 0x04000000L
|
||||
|
||||
#define SSL_VERIFY_NONE 0x00
|
||||
#define SSL_VERIFY_PEER 0x01
|
||||
#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
|
||||
#define SSL_VERIFY_CLIENT_ONCE 0x04
|
||||
|
||||
//
|
||||
// Implement asio-ssl layer with these three classes in asio::ssl::mbedtls
|
||||
//
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
namespace mbedtls {
|
||||
|
||||
class engine;
|
||||
class bio;
|
||||
class shared_ctx;
|
||||
} } } // namespace asio::ssl::mbedtls
|
||||
|
||||
//
|
||||
// Supply OpenSSL types as aliases to mbedtls classes
|
||||
//
|
||||
using X509_STORE_CTX=void;
|
||||
using BIO=asio::ssl::mbedtls::bio;
|
||||
using SSL_CTX=asio::ssl::mbedtls::shared_ctx;
|
||||
using SSL=asio::ssl::mbedtls::engine;
|
113
components/asio/port/mbedtls/include/mbedtls_bio.hpp
Normal file
113
components/asio/port/mbedtls/include/mbedtls_bio.hpp
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "asio/ssl/context_base.hpp"
|
||||
#include "asio/ssl/context.hpp"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
namespace mbedtls {
|
||||
|
||||
class bio {
|
||||
static constexpr int BIO_SIZE = CONFIG_ASIO_SSL_BIO_SIZE;
|
||||
static constexpr int BIO_FLAGS_READ = 1;
|
||||
static constexpr int BIO_FLAGS_WRITE = 2;
|
||||
|
||||
public:
|
||||
int write(const void *buf, int len)
|
||||
{
|
||||
if (buf == nullptr || len <= 0) {
|
||||
// not an error, just empty operation (as in openssl/bio)
|
||||
return 0;
|
||||
}
|
||||
int remaining = size_ - offset_;
|
||||
if (remaining <= 0) {
|
||||
flags_ |= BIO_FLAGS_WRITE;
|
||||
return -1;
|
||||
}
|
||||
int len_to_write = len > remaining ? remaining : len;
|
||||
std::memcpy(&data_[offset_], buf, len_to_write);
|
||||
offset_ += len_to_write;
|
||||
dlen_ = offset_;
|
||||
if (len_to_write == len) {
|
||||
flags_ &= ~BIO_FLAGS_WRITE;
|
||||
}
|
||||
return len_to_write;
|
||||
}
|
||||
|
||||
int read(void *buf, int len)
|
||||
{
|
||||
if (buf == nullptr || len <= 0) {
|
||||
// not an error, just empty operation (as in openssl/bio)
|
||||
return 0;
|
||||
}
|
||||
int remaining = peer_->dlen_ - peer_->roffset_;
|
||||
if (remaining <= 0) {
|
||||
flags_ |= BIO_FLAGS_READ;
|
||||
return -1;
|
||||
}
|
||||
int len_to_read = remaining > len ? len : remaining;
|
||||
std::memcpy(buf, &peer_->data_[peer_->roffset_], len_to_read);
|
||||
peer_->roffset_ += len_to_read;
|
||||
if (len_to_read == len) {
|
||||
flags_ &= ~BIO_FLAGS_READ;
|
||||
}
|
||||
if (peer_->offset_) {
|
||||
// shift data back to the beginning of the buffer
|
||||
std::memmove(&peer_->data_[0], &peer_->data_[peer_->roffset_], peer_->offset_ - peer_->roffset_);
|
||||
peer_->offset_ -= peer_->roffset_;
|
||||
peer_->roffset_ = 0;
|
||||
peer_->dlen_ = peer_->offset_;
|
||||
}
|
||||
return len_to_read;
|
||||
}
|
||||
|
||||
size_t wpending() const
|
||||
{
|
||||
return dlen_ - roffset_;
|
||||
}
|
||||
|
||||
size_t ctrl_pending()
|
||||
{
|
||||
return peer_->dlen_ - peer_->roffset_;
|
||||
}
|
||||
|
||||
bool should_write() const
|
||||
{
|
||||
return flags_ & BIO_FLAGS_WRITE;
|
||||
}
|
||||
|
||||
bool should_read() const
|
||||
{
|
||||
return flags_ & BIO_FLAGS_READ;
|
||||
}
|
||||
|
||||
static std::pair<std::shared_ptr<bio>, std::shared_ptr<bio>> new_pair(const char* error_location)
|
||||
{
|
||||
auto b1 = std::shared_ptr<bio>(new (std::nothrow) bio);
|
||||
auto b2 = std::shared_ptr<bio>(new (std::nothrow) bio);
|
||||
if (b1 == nullptr || b2 == nullptr) {
|
||||
throw_alloc_failure(error_location);
|
||||
} else {
|
||||
b1->peer_ = b2;
|
||||
b2->peer_ = b1;
|
||||
}
|
||||
return std::make_pair(b1, b2);
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<uint8_t, BIO_SIZE> data_ {};
|
||||
size_t size_ {BIO_SIZE};
|
||||
std::shared_ptr<bio> peer_ {nullptr};
|
||||
int dlen_ {0};
|
||||
size_t offset_ {0};
|
||||
size_t roffset_ {0};
|
||||
size_t flags_ {0};
|
||||
};
|
||||
|
||||
} } } // namespace asio::ssl::mbedtls
|
105
components/asio/port/mbedtls/include/mbedtls_context.hpp
Normal file
105
components/asio/port/mbedtls/include/mbedtls_context.hpp
Normal file
@ -0,0 +1,105 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "asio/ssl/context_base.hpp"
|
||||
#include "asio/ssl/context.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace error {
|
||||
|
||||
const asio::error_category& get_mbedtls_category();
|
||||
} // namespace error
|
||||
|
||||
namespace ssl {
|
||||
namespace mbedtls {
|
||||
|
||||
void throw_alloc_failure(const char* location);
|
||||
|
||||
const char *error_message(int error_code);
|
||||
|
||||
enum class container {
|
||||
CERT, CA_CERT, PRIVKEY
|
||||
};
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline T* create(const char * location, Args &&... args)
|
||||
{
|
||||
T* t = new (std::nothrow) T(std::forward<Args>(args)...);
|
||||
if (t == nullptr)
|
||||
{
|
||||
throw_alloc_failure(location);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
class context {
|
||||
public:
|
||||
explicit context(context_base::method m): method_(m), options_(0) {}
|
||||
|
||||
const unsigned char *data(container c) const
|
||||
{
|
||||
switch (c) {
|
||||
case container::CERT:
|
||||
return static_cast<const unsigned char *>(cert_chain_.data());
|
||||
case container::CA_CERT:
|
||||
return static_cast<const unsigned char *>(ca_cert_.data());
|
||||
case container::PRIVKEY:
|
||||
return static_cast<const unsigned char *>(private_key_.data());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::size_t size(container c) const
|
||||
{
|
||||
switch (c) {
|
||||
case container::CERT:
|
||||
return cert_chain_.size();
|
||||
case container::CA_CERT:
|
||||
return ca_cert_.size();
|
||||
case container::PRIVKEY:
|
||||
return private_key_.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
context_base::method method_;
|
||||
asio::ssl::context::options options_;
|
||||
const_buffer cert_chain_;
|
||||
const_buffer private_key_;
|
||||
const_buffer ca_cert_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Wrapper class around SSL_CTX so we can easily create
|
||||
* a shared pointer to the context without throwing the default exception.
|
||||
* This is useful, as we can use asio::detail::throw_error for allocation errors.
|
||||
*/
|
||||
class shared_ctx {
|
||||
public:
|
||||
static SSL_CTX *create(const char* location, context_base::method m)
|
||||
{
|
||||
auto wrapped = asio::ssl::mbedtls::create<shared_ctx>(location, m);
|
||||
if (wrapped->ctx_ == nullptr)
|
||||
{
|
||||
throw_alloc_failure(location);
|
||||
}
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
std::shared_ptr<mbedtls::context> get() const
|
||||
{
|
||||
return ctx_;
|
||||
}
|
||||
|
||||
explicit shared_ctx(context_base::method m)
|
||||
:ctx_(std::shared_ptr<context>(new (std::nothrow) context(m))) { }
|
||||
|
||||
private:
|
||||
std::shared_ptr<mbedtls::context> ctx_;
|
||||
};
|
||||
|
||||
} } } // namespace asio::ssl::mbedtls
|
294
components/asio/port/mbedtls/include/mbedtls_engine.hpp
Normal file
294
components/asio/port/mbedtls/include/mbedtls_engine.hpp
Normal file
@ -0,0 +1,294 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/certs.h"
|
||||
#include "mbedtls/esp_debug.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
namespace mbedtls {
|
||||
|
||||
const char *error_message(int error_code)
|
||||
{
|
||||
static char error_buf[100];
|
||||
mbedtls_strerror(error_code, error_buf, sizeof(error_buf));
|
||||
return error_buf;
|
||||
}
|
||||
|
||||
void throw_alloc_failure(const char* location)
|
||||
{
|
||||
asio::error_code ec( MBEDTLS_ERR_SSL_ALLOC_FAILED, asio::error::get_mbedtls_category());
|
||||
asio::detail::throw_error(ec, location);
|
||||
}
|
||||
|
||||
namespace error_codes {
|
||||
|
||||
bool is_error(int ret)
|
||||
{
|
||||
return ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
}
|
||||
|
||||
static bool want_write(int ret)
|
||||
{
|
||||
return ret == MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
}
|
||||
|
||||
static bool want_read(int ret)
|
||||
{
|
||||
return ret == MBEDTLS_ERR_SSL_WANT_READ;
|
||||
}
|
||||
|
||||
} // namespace error_codes
|
||||
|
||||
enum rw_state {
|
||||
IDLE, READING, WRITING, CLOSED
|
||||
};
|
||||
|
||||
class engine {
|
||||
public:
|
||||
explicit engine(std::shared_ptr<context> ctx): ctx_(std::move(ctx)),
|
||||
bio_(bio::new_pair("mbedtls-engine")), state_(IDLE), verify_mode_(0) {}
|
||||
|
||||
void set_verify_mode(asio::ssl::verify_mode mode)
|
||||
{
|
||||
verify_mode_ = mode;
|
||||
}
|
||||
|
||||
bio* ext_bio() const
|
||||
{
|
||||
return bio_.second.get();
|
||||
}
|
||||
|
||||
rw_state get_state() const
|
||||
{
|
||||
return state_;
|
||||
}
|
||||
|
||||
int shutdown()
|
||||
{
|
||||
int ret = mbedtls_ssl_close_notify(&impl_.ssl_);
|
||||
if (ret) {
|
||||
impl::print_error("mbedtls_ssl_close_notify", ret);
|
||||
}
|
||||
state_ = CLOSED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int connect()
|
||||
{
|
||||
return handshake(true);
|
||||
}
|
||||
|
||||
int accept()
|
||||
{
|
||||
return handshake(false);
|
||||
}
|
||||
|
||||
int write(const void *buffer, int len)
|
||||
{
|
||||
int ret = impl_.write(buffer, len);
|
||||
state_ = ret == len ? IDLE: WRITING;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read(void *buffer, int len)
|
||||
{
|
||||
int ret = impl_.read(buffer, len);
|
||||
state_ = ret == len ? IDLE: READING;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
int handshake(bool is_client_not_server)
|
||||
{
|
||||
if (impl_.before_handshake()) {
|
||||
impl_.configure(ctx_.get(), is_client_not_server, impl_verify_mode(is_client_not_server));
|
||||
}
|
||||
return do_handshake();
|
||||
}
|
||||
|
||||
static int bio_read(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
auto bio = static_cast<BIO*>(ctx);
|
||||
int read = bio->read(buf, len);
|
||||
if (read <= 0 && bio->should_read()) {
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
static int bio_write(void *ctx, const unsigned char *buf, size_t len)
|
||||
{
|
||||
auto bio = static_cast<BIO*>(ctx);
|
||||
int written = bio->write(buf, len);
|
||||
if (written <= 0 && bio->should_write()) {
|
||||
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
int do_handshake()
|
||||
{
|
||||
int ret = 0;
|
||||
mbedtls_ssl_set_bio(&impl_.ssl_, bio_.first.get(), bio_write, bio_read, nullptr);
|
||||
|
||||
while (impl_.ssl_.state != MBEDTLS_SSL_HANDSHAKE_OVER) {
|
||||
ret = mbedtls_ssl_handshake_step(&impl_.ssl_);
|
||||
|
||||
if (ret != 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
impl::print_error("mbedtls_ssl_handshake_step", ret);
|
||||
}
|
||||
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
|
||||
state_ = READING;
|
||||
} else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
state_ = WRITING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Converts OpenSSL verification mode to mbedtls enum
|
||||
int impl_verify_mode(bool is_client_not_server) const
|
||||
{
|
||||
int mode = MBEDTLS_SSL_VERIFY_UNSET;
|
||||
if (is_client_not_server) {
|
||||
if (verify_mode_ & SSL_VERIFY_PEER)
|
||||
mode = MBEDTLS_SSL_VERIFY_REQUIRED;
|
||||
else if (verify_mode_ == SSL_VERIFY_NONE)
|
||||
mode = MBEDTLS_SSL_VERIFY_NONE;
|
||||
} else {
|
||||
if (verify_mode_ & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
|
||||
mode = MBEDTLS_SSL_VERIFY_REQUIRED;
|
||||
else if (verify_mode_ & SSL_VERIFY_PEER)
|
||||
mode = MBEDTLS_SSL_VERIFY_OPTIONAL;
|
||||
else if (verify_mode_ == SSL_VERIFY_NONE)
|
||||
mode = MBEDTLS_SSL_VERIFY_NONE;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
struct impl {
|
||||
static void print_error(const char* function, int error_code)
|
||||
{
|
||||
constexpr const char *TAG="mbedtls-engine-impl";
|
||||
ESP_LOGE(TAG, "%s() returned -0x%04X", function, -error_code);
|
||||
ESP_LOGI(TAG, "-0x%04X: %s", -error_code, error_message(error_code));
|
||||
}
|
||||
|
||||
bool before_handshake() const
|
||||
{
|
||||
return ssl_.state == 0;
|
||||
}
|
||||
|
||||
int write(const void *buffer, int len)
|
||||
{
|
||||
int ret = mbedtls_ssl_write(&ssl_, static_cast<const unsigned char *>(buffer), len);
|
||||
if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
print_error("mbedtls_ssl_write", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read(void *buffer, int len)
|
||||
{
|
||||
int ret = mbedtls_ssl_read(&ssl_, static_cast<unsigned char *>(buffer), len);
|
||||
if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ) {
|
||||
print_error("mbedtls_ssl_read", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
impl()
|
||||
{
|
||||
const unsigned char pers[] = "asio ssl";
|
||||
mbedtls_ssl_init(&ssl_);
|
||||
mbedtls_ssl_config_init(&conf_);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg_);
|
||||
#ifdef CONFIG_MBEDTLS_DEBUG
|
||||
mbedtls_esp_enable_debug_log(&conf_, CONFIG_MBEDTLS_DEBUG_LEVEL);
|
||||
#endif
|
||||
mbedtls_entropy_init(&entropy_);
|
||||
mbedtls_ctr_drbg_seed(&ctr_drbg_, mbedtls_entropy_func, &entropy_, pers, sizeof(pers));
|
||||
mbedtls_x509_crt_init(&public_cert_);
|
||||
mbedtls_pk_init(&pk_key_);
|
||||
mbedtls_x509_crt_init(&ca_cert_);
|
||||
}
|
||||
|
||||
bool configure(context *ctx, bool is_client_not_server, int mbedtls_verify_mode)
|
||||
{
|
||||
mbedtls_x509_crt_init(&public_cert_);
|
||||
mbedtls_pk_init(&pk_key_);
|
||||
mbedtls_x509_crt_init(&ca_cert_);
|
||||
int ret = mbedtls_ssl_config_defaults(&conf_, is_client_not_server ? MBEDTLS_SSL_IS_CLIENT: MBEDTLS_SSL_IS_SERVER,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
if (ret) {
|
||||
print_error("mbedtls_ssl_config_defaults", ret);
|
||||
return false;
|
||||
}
|
||||
mbedtls_ssl_conf_rng(&conf_, mbedtls_ctr_drbg_random, &ctr_drbg_);
|
||||
mbedtls_ssl_conf_authmode(&conf_, mbedtls_verify_mode);
|
||||
if (ctx->cert_chain_.size() > 0 && ctx->private_key_.size() > 0) {
|
||||
ret = mbedtls_x509_crt_parse(&public_cert_, ctx->data(container::CERT), ctx->size(container::CERT));
|
||||
if (ret < 0) {
|
||||
print_error("mbedtls_x509_crt_parse", ret);
|
||||
return false;
|
||||
}
|
||||
ret = mbedtls_pk_parse_key(&pk_key_, ctx->data(container::PRIVKEY), ctx->size(container::PRIVKEY),
|
||||
nullptr, 0);
|
||||
if (ret < 0) {
|
||||
print_error("mbedtls_pk_parse_keyfile", ret);
|
||||
return false;
|
||||
}
|
||||
ret = mbedtls_ssl_conf_own_cert(&conf_, &public_cert_, &pk_key_);
|
||||
if (ret) {
|
||||
print_error("mbedtls_ssl_conf_own_cert", ret);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->ca_cert_.size() > 0) {
|
||||
ret = mbedtls_x509_crt_parse(&ca_cert_, ctx->data(container::CA_CERT), ctx->size(container::CA_CERT));
|
||||
if (ret < 0) {
|
||||
print_error("mbedtls_x509_crt_parse", ret);
|
||||
return false;
|
||||
}
|
||||
mbedtls_ssl_conf_ca_chain(&conf_, &ca_cert_, nullptr);
|
||||
} else {
|
||||
mbedtls_ssl_conf_ca_chain(&conf_, nullptr, nullptr);
|
||||
}
|
||||
ret = mbedtls_ssl_setup(&ssl_, &conf_);
|
||||
if (ret) {
|
||||
print_error("mbedtls_ssl_setup", ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
mbedtls_ssl_context ssl_{};
|
||||
mbedtls_entropy_context entropy_{};
|
||||
mbedtls_ctr_drbg_context ctr_drbg_{};
|
||||
mbedtls_ssl_config conf_{};
|
||||
mbedtls_x509_crt public_cert_{};
|
||||
mbedtls_pk_context pk_key_{};
|
||||
mbedtls_x509_crt ca_cert_{};
|
||||
};
|
||||
|
||||
impl impl_{};
|
||||
std::shared_ptr<context> ctx_;
|
||||
std::pair<std::shared_ptr<bio>, std::shared_ptr<bio>> bio_;
|
||||
enum rw_state state_;
|
||||
asio::ssl::verify_mode verify_mode_;
|
||||
};
|
||||
|
||||
} } } // namespace asio::ssl::mbedtls
|
55
components/asio/port/mbedtls/include/mbedtls_error.hpp
Normal file
55
components/asio/port/mbedtls/include/mbedtls_error.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/ssl/error.hpp"
|
||||
#include "asio/ssl/detail/openssl_init.hpp"
|
||||
#include "mbedtls_context.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace error {
|
||||
namespace detail {
|
||||
|
||||
class mbedtls_category : public asio::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT
|
||||
{
|
||||
return "asio.ssl";
|
||||
}
|
||||
|
||||
std::string message(int value) const
|
||||
{
|
||||
const char* s = asio::ssl::mbedtls::error_message(value);
|
||||
return s ? s : "asio.mbedtls error";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
const asio::error_category& get_mbedtls_category()
|
||||
{
|
||||
static detail::mbedtls_category instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
const asio::error_category& get_ssl_category()
|
||||
{
|
||||
return asio::error::get_mbedtls_category();
|
||||
}
|
||||
|
||||
} // namespace error
|
||||
|
||||
namespace ssl {
|
||||
namespace error {
|
||||
|
||||
const asio::error_category& get_stream_category()
|
||||
{
|
||||
return asio::error::get_mbedtls_category();
|
||||
}
|
||||
|
||||
} } } // namespace asio::ssl::error
|
6
components/asio/port/mbedtls/include/openssl/conf.h
Normal file
6
components/asio/port/mbedtls/include/openssl/conf.h
Normal file
@ -0,0 +1,6 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
6
components/asio/port/mbedtls/include/openssl/dh.h
Normal file
6
components/asio/port/mbedtls/include/openssl/dh.h
Normal file
@ -0,0 +1,6 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
6
components/asio/port/mbedtls/include/openssl/err.h
Normal file
6
components/asio/port/mbedtls/include/openssl/err.h
Normal file
@ -0,0 +1,6 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
6
components/asio/port/mbedtls/include/openssl/rsa.h
Normal file
6
components/asio/port/mbedtls/include/openssl/rsa.h
Normal file
@ -0,0 +1,6 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
8
components/asio/port/mbedtls/include/openssl/ssl.h
Normal file
8
components/asio/port/mbedtls/include/openssl/ssl.h
Normal file
@ -0,0 +1,8 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "openssl_stub.hpp"
|
6
components/asio/port/mbedtls/include/openssl/x509v3.h
Normal file
6
components/asio/port/mbedtls/include/openssl/x509v3.h
Normal file
@ -0,0 +1,6 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
#pragma once
|
115
components/asio/port/mbedtls/src/mbedtls_context.cpp
Normal file
115
components/asio/port/mbedtls/src/mbedtls_context.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2005 Voipster / Indrek dot Juhani at voipster dot com
|
||||
// SPDX-FileCopyrightText: 2005-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// SPDX-FileContributor: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "openssl_stub.hpp"
|
||||
#include <cstring>
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/ssl/context.hpp"
|
||||
#include "asio/ssl/error.hpp"
|
||||
#include "mbedtls_context.hpp"
|
||||
|
||||
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
|
||||
|
||||
context::context(context::method m)
|
||||
: handle_(0)
|
||||
{
|
||||
handle_ = mbedtls::shared_ctx::create("mbedtls-context", m);
|
||||
set_options(no_compression);
|
||||
}
|
||||
|
||||
context::context(context&& other)
|
||||
{
|
||||
handle_ = other.handle_;
|
||||
other.handle_ = 0;
|
||||
}
|
||||
|
||||
context& context::operator=(context&& other)
|
||||
{
|
||||
context tmp(ASIO_MOVE_CAST(context)(*this));
|
||||
handle_ = other.handle_;
|
||||
other.handle_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
context::~context()
|
||||
{
|
||||
delete handle_;
|
||||
}
|
||||
|
||||
context::native_handle_type context::native_handle()
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
void context::set_options(context::options o)
|
||||
{
|
||||
asio::error_code ec;
|
||||
set_options(o, ec);
|
||||
asio::detail::throw_error(ec, "set_options");
|
||||
}
|
||||
|
||||
ASIO_SYNC_OP_VOID context::set_options(
|
||||
context::options o, asio::error_code& ec)
|
||||
{
|
||||
handle_->get()->options_ = o;
|
||||
ec = asio::error_code();
|
||||
ASIO_SYNC_OP_VOID_RETURN(ec);
|
||||
}
|
||||
|
||||
void context::add_certificate_authority(const const_buffer& ca)
|
||||
{
|
||||
asio::error_code ec;
|
||||
add_certificate_authority(ca, ec);
|
||||
asio::detail::throw_error(ec, "add_certificate_authority");
|
||||
}
|
||||
|
||||
ASIO_SYNC_OP_VOID context::add_certificate_authority(
|
||||
const const_buffer& ca, asio::error_code& ec)
|
||||
{
|
||||
handle_->get()->ca_cert_ = ca;
|
||||
ASIO_SYNC_OP_VOID_RETURN(asio::error_code());
|
||||
}
|
||||
|
||||
void context::use_certificate_chain(const const_buffer& chain)
|
||||
{
|
||||
asio::error_code ec;
|
||||
use_certificate_chain(chain, ec);
|
||||
asio::detail::throw_error(ec, "use_certificate_chain");
|
||||
}
|
||||
|
||||
ASIO_SYNC_OP_VOID context::use_certificate_chain(
|
||||
const const_buffer& chain, asio::error_code& ec)
|
||||
{
|
||||
handle_->get()->cert_chain_ = chain;
|
||||
ASIO_SYNC_OP_VOID_RETURN(asio::error_code());
|
||||
}
|
||||
|
||||
void context::use_private_key(
|
||||
const const_buffer& private_key, context::file_format format)
|
||||
{
|
||||
asio::error_code ec;
|
||||
use_private_key(private_key, format, ec);
|
||||
asio::detail::throw_error(ec, "use_private_key");
|
||||
}
|
||||
|
||||
ASIO_SYNC_OP_VOID context::use_private_key(
|
||||
const const_buffer& private_key, context::file_format format,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
handle_->get()->private_key_ = private_key;
|
||||
ASIO_SYNC_OP_VOID_RETURN(asio::error_code());
|
||||
}
|
||||
|
||||
} // namespace ssl
|
||||
} // namespace asio
|
208
components/asio/port/mbedtls/src/mbedtls_engine.cpp
Normal file
208
components/asio/port/mbedtls/src/mbedtls_engine.cpp
Normal file
@ -0,0 +1,208 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
// SPDX-FileContributor: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "openssl_stub.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/ssl/detail/engine.hpp"
|
||||
#include "asio/ssl/error.hpp"
|
||||
#include "asio/ssl/verify_context.hpp"
|
||||
#include "mbedtls_context.hpp"
|
||||
#include "mbedtls_bio.hpp"
|
||||
#include "mbedtls_error.hpp"
|
||||
#include "mbedtls_engine.hpp"
|
||||
|
||||
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
namespace detail {
|
||||
|
||||
|
||||
engine::engine(SSL_CTX* context)
|
||||
: ssl_(nullptr)
|
||||
{
|
||||
ssl_ = mbedtls::create<mbedtls::engine>("mbedtls-engine", context->get());
|
||||
}
|
||||
|
||||
engine::~engine()
|
||||
{
|
||||
delete ssl_;
|
||||
}
|
||||
|
||||
SSL* engine::native_handle()
|
||||
{
|
||||
return ssl_;
|
||||
}
|
||||
|
||||
asio::error_code engine::set_verify_mode(
|
||||
verify_mode v, asio::error_code& ec)
|
||||
{
|
||||
ssl_->set_verify_mode(v);
|
||||
return {};
|
||||
}
|
||||
|
||||
engine::want engine::handshake(
|
||||
stream_base::handshake_type type, asio::error_code& ec)
|
||||
{
|
||||
return perform((type == asio::ssl::stream_base::client)
|
||||
? &engine::do_connect : &engine::do_accept, 0, 0, ec, 0);
|
||||
}
|
||||
|
||||
engine::want engine::shutdown(asio::error_code& ec)
|
||||
{
|
||||
return perform(&engine::do_shutdown, 0, 0, ec, 0);
|
||||
}
|
||||
|
||||
engine::want engine::write(const asio::const_buffer& data,
|
||||
asio::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
if (data.size() == 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return engine::want_nothing;
|
||||
}
|
||||
|
||||
return perform(&engine::do_write,
|
||||
const_cast<void*>(data.data()),
|
||||
data.size(), ec, &bytes_transferred);
|
||||
}
|
||||
|
||||
engine::want engine::read(const asio::mutable_buffer& data,
|
||||
asio::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
if (data.size() == 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return engine::want_nothing;
|
||||
}
|
||||
|
||||
return perform(&engine::do_read, data.data(),
|
||||
data.size(), ec, &bytes_transferred);
|
||||
}
|
||||
|
||||
asio::mutable_buffer engine::get_output(
|
||||
const asio::mutable_buffer& data)
|
||||
{
|
||||
int length = ssl_->ext_bio()->read(data.data(), static_cast<int>(data.size()));
|
||||
|
||||
return asio::buffer(data,
|
||||
length > 0 ? static_cast<std::size_t>(length) : 0);
|
||||
}
|
||||
|
||||
asio::const_buffer engine::put_input(
|
||||
const asio::const_buffer& data)
|
||||
{
|
||||
int length = ssl_->ext_bio()->write(data.data(), static_cast<int>(data.size()));
|
||||
|
||||
return asio::buffer(data +
|
||||
(length > 0 ? static_cast<std::size_t>(length) : 0));
|
||||
}
|
||||
|
||||
const asio::error_code& engine::map_error_code(
|
||||
asio::error_code& ec) const
|
||||
{
|
||||
// We only want to map the error::eof code.
|
||||
if (ec != asio::error::eof)
|
||||
return ec;
|
||||
|
||||
// If there's data yet to be read, it's an error.
|
||||
if (ssl_->ext_bio()->wpending())
|
||||
{
|
||||
ec = asio::ssl::error::stream_truncated;
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Otherwise, the peer should have negotiated a proper shutdown.
|
||||
if (ssl_->shutdown() != 0)
|
||||
{
|
||||
ec = asio::ssl::error::stream_truncated;
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
// This is a simplified implementation of a generic ssl io operation
|
||||
// original implementation using openssl's SSL object is in asio/include/asio/ssl/detail/impl/engine.ipp
|
||||
engine::want engine::perform(int (engine::* op)(void*, std::size_t),
|
||||
void* data, std::size_t length, asio::error_code& ec,
|
||||
std::size_t* bytes_transferred)
|
||||
{
|
||||
std::size_t pending_output_before = ssl_->ext_bio()->ctrl_pending();
|
||||
int result = (this->*op)(data, length);
|
||||
|
||||
std::size_t pending_output_after = ssl_->ext_bio()->ctrl_pending();
|
||||
|
||||
if (mbedtls::error_codes::is_error(result))
|
||||
{
|
||||
ec = asio::error_code(result, asio::error::get_mbedtls_category());
|
||||
return pending_output_after > pending_output_before ? want_output : want_nothing;
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
return pending_output_after > pending_output_before
|
||||
? want_output : want_nothing;
|
||||
}
|
||||
|
||||
if (result > 0 && bytes_transferred)
|
||||
*bytes_transferred = static_cast<std::size_t>(result);
|
||||
|
||||
if (mbedtls::error_codes::want_write(result))
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return want_output_and_retry;
|
||||
}
|
||||
else if (pending_output_after > pending_output_before)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return result > 0 ? want_output : want_output_and_retry;
|
||||
}
|
||||
else if (mbedtls::error_codes::want_read(result))
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return want_input_and_retry;
|
||||
}
|
||||
else if (ssl_->get_state() == mbedtls::CLOSED)
|
||||
{
|
||||
ec = asio::error::eof;
|
||||
return want_nothing;
|
||||
}
|
||||
|
||||
ec = asio::error_code();
|
||||
return want_nothing;
|
||||
}
|
||||
|
||||
int engine::do_accept(void*, std::size_t)
|
||||
{
|
||||
return ssl_->accept();
|
||||
}
|
||||
|
||||
int engine::do_connect(void*, std::size_t)
|
||||
{
|
||||
return ssl_->connect();
|
||||
}
|
||||
|
||||
int engine::do_shutdown(void*, std::size_t)
|
||||
{
|
||||
return ssl_->shutdown();
|
||||
}
|
||||
|
||||
int engine::do_read(void* data, std::size_t length)
|
||||
{
|
||||
return ssl_->read(data, length < INT_MAX ? static_cast<int>(length) : INT_MAX);
|
||||
}
|
||||
|
||||
int engine::do_write(void* data, std::size_t length)
|
||||
{
|
||||
return ssl_->write(data, length < INT_MAX ? static_cast<int>(length) : INT_MAX);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace ssl
|
||||
} // namespace asio
|
20
components/asio/port/src/asio_ssl_impl.cpp
Normal file
20
components/asio/port/src/asio_ssl_impl.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/ssl/detail/openssl_init.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace ssl {
|
||||
namespace detail {
|
||||
|
||||
// No OpenSSL in this implementation, instance is nullptr
|
||||
asio::detail::shared_ptr<openssl_init_base::do_init> openssl_init_base::instance()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} } } // namespace asio::ssl::detail
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
//
|
||||
|
||||
#include "esp_asio_config.h"
|
||||
#include "internal/ssl_dbg.h"
|
||||
#include "openssl/esp_asio_openssl_stubs.h"
|
||||
|
||||
// Unsupported features as macros to make the assertions more readable
|
||||
#define ESP_OPENSSL_DH_IS_SUPPORTED 0
|
||||
#define ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED 0
|
||||
|
||||
void DH_free (DH *r)
|
||||
{
|
||||
SSL_ASSERT3(ESP_OPENSSL_DH_IS_SUPPORTED);
|
||||
}
|
||||
|
||||
DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
|
||||
{
|
||||
SSL_ASSERT2(ESP_OPENSSL_DH_IS_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh)
|
||||
{
|
||||
SSL_ASSERT1(ESP_OPENSSL_DH_IS_SUPPORTED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GENERAL_NAMES_free(GENERAL_NAMES * gens)
|
||||
{
|
||||
SSL_ASSERT3(ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED);
|
||||
}
|
||||
|
||||
X509_NAME *X509_get_subject_name(X509 *a)
|
||||
{
|
||||
SSL_ASSERT2(ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SSL_CTX_clear_chain_certs(SSL_CTX *ctx)
|
||||
{
|
||||
return 1;
|
||||
}
|
@ -5,6 +5,7 @@ cmake_minimum_required(VERSION 3.5)
|
||||
# (Not part of the boilerplate)
|
||||
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
|
||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
||||
set(EXCLUDE_COMPONENTS openssl)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(asio_ssl_client_server)
|
||||
|
Loading…
Reference in New Issue
Block a user