| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  |  * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: Apache-2.0 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  | #include <mbedtls/timing.h>
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  | #include "mbedtls/ctr_drbg.h"
 | 
					
						
							|  |  |  | #include "mbedtls/ssl.h"
 | 
					
						
							|  |  |  | #include "mbedtls_wrap.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  | using namespace idf::mbedtls_cxx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Tls::init(is_server server, do_verify verify, TlsConfig *config) | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     const char pers[] = "mbedtls_wrapper"; | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  |     is_server_ = server == is_server{true}; | 
					
						
							|  |  |  |     is_dtls_ = config ? config->is_dtls : false; | 
					
						
							|  |  |  |     uint32_t timeout = config ? config->timeout : 0; | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     mbedtls_entropy_init(&entropy_); | 
					
						
							|  |  |  |     mbedtls_ctr_drbg_seed(&ctr_drbg_, mbedtls_entropy_func, &entropy_, (const unsigned char *)pers, sizeof(pers)); | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  |     int endpoint = server == is_server{true} ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT; | 
					
						
							|  |  |  |     int transport = is_dtls_ ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM; | 
					
						
							|  |  |  |     int ret = mbedtls_ssl_config_defaults(&conf_, endpoint, transport, MBEDTLS_SSL_PRESET_DEFAULT); | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     if (ret) { | 
					
						
							|  |  |  |         print_error("mbedtls_ssl_config_defaults", ret); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mbedtls_ssl_conf_rng(&conf_, mbedtls_ctr_drbg_random, &ctr_drbg_); | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  |     if (timeout) { | 
					
						
							|  |  |  |         mbedtls_ssl_conf_read_timeout(&conf_, timeout); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-28 21:42:27 +02:00
										 |  |  |     mbedtls_ssl_conf_authmode(&conf_, verify == do_verify{true} ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE); | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     ret = mbedtls_ssl_conf_own_cert(&conf_, &public_cert_, &pk_key_); | 
					
						
							|  |  |  |     if (ret) { | 
					
						
							|  |  |  |         print_error("mbedtls_ssl_conf_own_cert", ret); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-28 21:42:27 +02:00
										 |  |  |     if (verify == do_verify{true}) { | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |         mbedtls_ssl_conf_ca_chain(&conf_, &ca_cert_, nullptr); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if CONFIG_MBEDTLS_SSL_PROTO_DTLS
 | 
					
						
							|  |  |  |     if (is_server_ && is_dtls_) { | 
					
						
							|  |  |  |         if (!init_dtls_cookies()) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif // MBEDTLS_SSL_PROTO_DTLS
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     ret = mbedtls_ssl_setup(&ssl_, &conf_); | 
					
						
							|  |  |  |     if (ret) { | 
					
						
							|  |  |  |         print_error("mbedtls_ssl_setup", ret); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (timeout) { | 
					
						
							|  |  |  |         mbedtls_ssl_set_timer_cb(&ssl_, &timer_, mbedtls_timing_set_delay, mbedtls_timing_get_delay); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if CONFIG_MBEDTLS_SSL_PROTO_DTLS
 | 
					
						
							|  |  |  |     if (is_server_ && is_dtls_ && config && config->client_id != const_buf {}) { | 
					
						
							|  |  |  |         client_id_ = config->client_id; | 
					
						
							|  |  |  |         if (!set_client_id()) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif // MBEDTLS_SSL_PROTO_DTLS
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-20 09:13:39 +02:00
										 |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  | 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); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-06-28 21:42:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  | int Tls::handshake() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret = 0; | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  |     mbedtls_ssl_set_bio(&ssl_, this, bio_write, bio_read, is_dtls_ ? bio_read_tout : nullptr); | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while ( ( ret = mbedtls_ssl_handshake( &ssl_ ) ) != 0 ) { | 
					
						
							|  |  |  |         if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  | #if CONFIG_MBEDTLS_SSL_PROTO_DTLS
 | 
					
						
							|  |  |  |             if (is_server_ && is_dtls_ && ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) { | 
					
						
							|  |  |  |                 // hello verification requested -> restart the session with this client_id
 | 
					
						
							|  |  |  |                 if (!set_client_id()) { | 
					
						
							|  |  |  |                     return -1; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | #endif // MBEDTLS_SSL_PROTO_DTLS
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |             print_error( "mbedtls_ssl_handshake returned", ret ); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-06-28 21:42:27 +02:00
										 |  |  |         delay(); | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  | int Tls::bio_read_tout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto s = static_cast<Tls *>(ctx); | 
					
						
							|  |  |  |     return s->recv_timeout(buf, len, timeout); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  | 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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  |     int ret = mbedtls_x509_crt_parse(&public_cert_, crt.first, crt.second); | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     if (ret < 0) { | 
					
						
							|  |  |  |         print_error("mbedtls_x509_crt_parse", ret); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  |     ret = mbedtls_pk_parse_key(&pk_key_, key.first, key.second, nullptr, 0); | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     if (ret < 0) { | 
					
						
							|  |  |  |         print_error("mbedtls_pk_parse_keyfile", ret); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Tls::set_ca_cert(const_buf crt) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  |     int ret = mbedtls_x509_crt_parse(&ca_cert_, crt.first, crt.second); | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  |     if (ret < 0) { | 
					
						
							|  |  |  |         print_error("mbedtls_x509_crt_parse", ret); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-27 20:04:04 +01:00
										 |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-19 23:28:17 +02:00
										 |  |  | 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_); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-06-28 21:42:27 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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_); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-09-20 09:13:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-02-08 20:11:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if CONFIG_MBEDTLS_SSL_PROTO_DTLS
 | 
					
						
							|  |  |  | bool Tls::init_dtls_cookies() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret = mbedtls_ssl_cookie_setup(&cookie_, mbedtls_ctr_drbg_random, &ctr_drbg_); | 
					
						
							|  |  |  |     if (ret != 0) { | 
					
						
							|  |  |  |         print_error("mbedtls_ssl_cookie_setup() failed", ret); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mbedtls_ssl_conf_dtls_cookies(&conf_, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &cookie_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Tls::set_client_id() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     if (client_id_ == const_buf{}) { | 
					
						
							|  |  |  |         printf("client_id is not set"); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mbedtls_ssl_session_reset(&ssl_); | 
					
						
							|  |  |  |     if ((ret = mbedtls_ssl_set_client_transport_id(&ssl_, client_id_.first, client_id_.second)) != 0) { | 
					
						
							|  |  |  |         print_error("mbedtls_ssl_set_client_transport_id()", ret); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 |