mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-18 13:02:21 +02:00
feat(tls_cxx): Publish mbedtls component
Adds examples and tests. Also supports DTLS now.
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
idf_component_register(SRCS mbedtls_wrap.cpp
|
||||
tls_transport.cpp
|
||||
idf_component_register(SRCS tls_transport.cpp
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES tcp_transport)
|
||||
REQUIRES tcp_transport
|
||||
PRIV_REQUIRES mbedtls_cxx)
|
||||
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
using const_buf = std::span<const unsigned char>;
|
||||
|
||||
class Tls {
|
||||
public:
|
||||
enum class is_server : bool {};
|
||||
enum class do_verify : bool {};
|
||||
|
||||
Tls();
|
||||
virtual ~Tls();
|
||||
bool init(is_server server, do_verify verify);
|
||||
bool deinit();
|
||||
int handshake();
|
||||
int write(const unsigned char *buf, size_t len);
|
||||
int read(unsigned char *buf, size_t len);
|
||||
[[nodiscard]] bool set_own_cert(const_buf crt, const_buf key);
|
||||
[[nodiscard]] bool set_ca_cert(const_buf crt);
|
||||
bool set_hostname(const char *name);
|
||||
virtual int send(const unsigned char *buf, size_t len) = 0;
|
||||
virtual int recv(unsigned char *buf, size_t len) = 0;
|
||||
size_t get_available_bytes();
|
||||
|
||||
protected:
|
||||
mbedtls_ssl_context ssl_{};
|
||||
mbedtls_x509_crt public_cert_{};
|
||||
mbedtls_pk_context pk_key_{};
|
||||
mbedtls_x509_crt ca_cert_{};
|
||||
mbedtls_ssl_config conf_{};
|
||||
mbedtls_ctr_drbg_context ctr_drbg_{};
|
||||
mbedtls_entropy_context entropy_{};
|
||||
virtual void delay() {}
|
||||
|
||||
bool set_session();
|
||||
bool get_session();
|
||||
void reset_session();
|
||||
bool is_session_loaded();
|
||||
|
||||
private:
|
||||
static void print_error(const char *function, int error_code);
|
||||
static int bio_write(void *ctx, const unsigned char *buf, size_t len);
|
||||
static int bio_read(void *ctx, unsigned char *buf, size_t len);
|
||||
int mbedtls_pk_parse_key( mbedtls_pk_context *ctx,
|
||||
const unsigned char *key, size_t keylen,
|
||||
const unsigned char *pwd, size_t pwdlen);
|
||||
struct unique_session {
|
||||
unique_session()
|
||||
{
|
||||
::mbedtls_ssl_session_init(&s);
|
||||
}
|
||||
~unique_session()
|
||||
{
|
||||
::mbedtls_ssl_session_free(&s);
|
||||
}
|
||||
mbedtls_ssl_session *ptr()
|
||||
{
|
||||
return &s;
|
||||
}
|
||||
mbedtls_ssl_session s;
|
||||
};
|
||||
std::unique_ptr<unique_session> session_;
|
||||
|
||||
};
|
@ -1,190 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls_wrap.hpp"
|
||||
|
||||
bool Tls::init(is_server server, do_verify verify)
|
||||
{
|
||||
const char pers[] = "mbedtls_wrapper";
|
||||
mbedtls_entropy_init(&entropy_);
|
||||
mbedtls_ctr_drbg_seed(&ctr_drbg_, mbedtls_entropy_func, &entropy_, (const unsigned char *)pers, sizeof(pers));
|
||||
int ret = mbedtls_ssl_config_defaults(&conf_, server == is_server{true} ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, 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_, verify == do_verify{true} ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE);
|
||||
ret = mbedtls_ssl_conf_own_cert(&conf_, &public_cert_, &pk_key_);
|
||||
if (ret) {
|
||||
print_error("mbedtls_ssl_conf_own_cert", ret);
|
||||
return false;
|
||||
}
|
||||
if (verify == do_verify{true}) {
|
||||
mbedtls_ssl_conf_ca_chain(&conf_, &ca_cert_, nullptr);
|
||||
}
|
||||
ret = mbedtls_ssl_setup(&ssl_, &conf_);
|
||||
if (ret) {
|
||||
print_error("mbedtls_ssl_setup", ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tls::deinit()
|
||||
{
|
||||
::mbedtls_ssl_config_free(&conf_);
|
||||
::mbedtls_ssl_free(&ssl_);
|
||||
::mbedtls_pk_free(&pk_key_);
|
||||
::mbedtls_x509_crt_free(&public_cert_);
|
||||
::mbedtls_x509_crt_free(&ca_cert_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tls::print_error(const char *function, int error_code)
|
||||
{
|
||||
static char error_buf[100];
|
||||
mbedtls_strerror(error_code, error_buf, sizeof(error_buf));
|
||||
|
||||
printf("%s() returned -0x%04X\n", function, -error_code);
|
||||
printf("-0x%04X: %s\n", -error_code, error_buf);
|
||||
}
|
||||
|
||||
int Tls::handshake()
|
||||
{
|
||||
int ret = 0;
|
||||
mbedtls_ssl_set_bio(&ssl_, this, bio_write, bio_read, nullptr);
|
||||
|
||||
while ( ( ret = mbedtls_ssl_handshake( &ssl_ ) ) != 0 ) {
|
||||
if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) {
|
||||
print_error( "mbedtls_ssl_handshake returned", ret );
|
||||
return -1;
|
||||
}
|
||||
delay();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Tls::bio_write(void *ctx, const unsigned char *buf, size_t len)
|
||||
{
|
||||
auto s = static_cast<Tls *>(ctx);
|
||||
return s->send(buf, len);
|
||||
}
|
||||
|
||||
int Tls::bio_read(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
auto s = static_cast<Tls *>(ctx);
|
||||
return s->recv(buf, len);
|
||||
}
|
||||
|
||||
int Tls::write(const unsigned char *buf, size_t len)
|
||||
{
|
||||
return mbedtls_ssl_write( &ssl_, buf, len );
|
||||
}
|
||||
|
||||
int Tls::read(unsigned char *buf, size_t len)
|
||||
{
|
||||
return mbedtls_ssl_read( &ssl_, buf, len );
|
||||
}
|
||||
|
||||
bool Tls::set_own_cert(const_buf crt, const_buf key)
|
||||
{
|
||||
int ret = mbedtls_x509_crt_parse(&public_cert_, crt.data(), crt.size());
|
||||
if (ret < 0) {
|
||||
print_error("mbedtls_x509_crt_parse", ret);
|
||||
return false;
|
||||
}
|
||||
ret = mbedtls_pk_parse_key(&pk_key_, key.data(), key.size(), nullptr, 0);
|
||||
if (ret < 0) {
|
||||
print_error("mbedtls_pk_parse_keyfile", ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tls::set_ca_cert(const_buf crt)
|
||||
{
|
||||
int ret = mbedtls_x509_crt_parse(&ca_cert_, crt.data(), crt.size());
|
||||
if (ret < 0) {
|
||||
print_error("mbedtls_x509_crt_parse", ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tls::set_hostname(const char *name)
|
||||
{
|
||||
int ret = mbedtls_ssl_set_hostname(&ssl_, name);
|
||||
if (ret < 0) {
|
||||
print_error("mbedtls_ssl_set_hostname", ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Tls::Tls()
|
||||
{
|
||||
mbedtls_x509_crt_init(&public_cert_);
|
||||
mbedtls_pk_init(&pk_key_);
|
||||
mbedtls_x509_crt_init(&ca_cert_);
|
||||
}
|
||||
|
||||
int Tls::mbedtls_pk_parse_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen)
|
||||
{
|
||||
|
||||
return ::mbedtls_pk_parse_key(ctx, key, keylen, pwd, pwdlen, nullptr, nullptr);
|
||||
}
|
||||
|
||||
size_t Tls::get_available_bytes()
|
||||
{
|
||||
return ::mbedtls_ssl_get_bytes_avail(&ssl_);
|
||||
}
|
||||
|
||||
Tls::~Tls()
|
||||
{
|
||||
::mbedtls_ssl_config_free(&conf_);
|
||||
::mbedtls_ssl_free(&ssl_);
|
||||
::mbedtls_pk_free(&pk_key_);
|
||||
::mbedtls_x509_crt_free(&public_cert_);
|
||||
::mbedtls_x509_crt_free(&ca_cert_);
|
||||
}
|
||||
|
||||
bool Tls::get_session()
|
||||
{
|
||||
if (session_ == nullptr) {
|
||||
session_ = std::make_unique<unique_session>();
|
||||
}
|
||||
int ret = ::mbedtls_ssl_get_session(&ssl_, session_->ptr());
|
||||
if (ret != 0) {
|
||||
print_error("mbedtls_ssl_get_session() failed", ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tls::set_session()
|
||||
{
|
||||
if (session_ == nullptr) {
|
||||
printf("session hasn't been initialized");
|
||||
return false;
|
||||
}
|
||||
int ret = mbedtls_ssl_set_session(&ssl_, session_->ptr());
|
||||
if (ret != 0) {
|
||||
print_error("mbedtls_ssl_set_session() failed", ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tls::reset_session()
|
||||
{
|
||||
session_.reset(nullptr);
|
||||
}
|
||||
bool Tls::is_session_loaded()
|
||||
{
|
||||
return session_ != nullptr;
|
||||
}
|
@ -11,6 +11,8 @@
|
||||
|
||||
static const char *TAG = "tls_transport";
|
||||
|
||||
using namespace idf::mbedtls_cxx;
|
||||
|
||||
class TlsTransport: public Tls {
|
||||
public:
|
||||
explicit TlsTransport(esp_transport_handle_t parent) : Tls(), transport_(parent) {}
|
||||
|
@ -2,3 +2,6 @@ dependencies:
|
||||
espressif/esp_modem:
|
||||
version: "^1.0.1"
|
||||
override_path: "../../../"
|
||||
espressif/mbedtls_cxx:
|
||||
version: "*"
|
||||
override_path: "../../../../mbedtls_cxx"
|
||||
|
Reference in New Issue
Block a user