From 214e307486fc554e54f457b696075ce2eb53a00b Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Tue, 17 Jun 2025 16:45:29 +0200 Subject: [PATCH] mbedtls: add Signed-off-by: Simon Rozman --- include/stdex/mbedtls.hpp | 219 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 include/stdex/mbedtls.hpp diff --git a/include/stdex/mbedtls.hpp b/include/stdex/mbedtls.hpp new file mode 100644 index 000000000..9b1c238ab --- /dev/null +++ b/include/stdex/mbedtls.hpp @@ -0,0 +1,219 @@ +/* + SPDX-License-Identifier: MIT + Copyright © 2016-2025 Amebis +*/ + +#pragma once + +#include "compat.hpp" +#include "exception.hpp" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdocumentation-deprecated-sync" +#endif +#include +#include +#include +#include +#include +#include +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#ifdef MBEDTLS_USE_PSA_CRYPTO +#include +#endif +#if !defined(_WIN32) +#include +#include +#endif +#include + +namespace stdex +{ + namespace mbedtls + { + /// + /// MbedTLS runtime error + /// + class runtime_error : public stdex::num_runtime_error + { + public: + /// + /// Constructs an exception + /// + /// \param[in] num MbedTLS error code + /// + runtime_error(error_type num) : stdex::num_runtime_error(num, message(num)) + { + } + + /// + /// Constructs an exception + /// + /// \param[in] num MbedTLS error code + /// \param[in] msg Error message + /// + runtime_error(error_type num, const std::string &msg) : stdex::num_runtime_error(num, msg + ": " + message(num)) + { + } + + /// + /// Constructs an exception + /// + /// \param[in] num MbedTLS error code + /// \param[in] msg Error message + /// + runtime_error(error_type num, const char *msg) : stdex::num_runtime_error(num, std::string(msg) + ": " + message(num)) + { + } + + protected: + /// + /// Returns a string explaining the meaning of a security result code + /// + /// \sa [mbedtls_strerror function](https://mbed-ce.github.io/mbed-os/group__mbedtls__errors.html#ga8c41c149b77a4807115b19c2af858558) + /// + static std::string message(error_type num) + { + char buf[1024]; + memset(buf, 0, sizeof(buf)); + mbedtls_strerror(num, buf, sizeof(buf)); + return buf; + } + }; + + /// + /// MbedTLS entropy context + /// + class entropy_context : public mbedtls_entropy_context + { + public: + /// + /// Initializes MbedTLS entropy context + /// + /// \sa [mbedtls_entropy_init](https://mbed-ce.github.io/mbed-os/group__mbedtls__entropy__module.html#gaa901e027093c6fe65dee5760db78aced) + /// + entropy_context() + { + mbedtls_entropy_init(this); + #if !defined(_WIN32) && defined(MBEDTLS_FS_IO) + int ret = mbedtls_entropy_add_source(this, dev_random_entropy_poll, NULL, 32, MBEDTLS_ENTROPY_SOURCE_STRONG); + if (ret != 0) + throw runtime_error(ret, "mbedtls_entropy_add_source failed"); + #endif + } + + /// + /// Frees MbedTLS entropy context + /// + /// \sa [mbedtls_entropy_free](https://mbed-ce.github.io/mbed-os/group__mbedtls__entropy__module.html#ga06778439f8a0e2daa2d3b444e06ad8dd) + /// + ~entropy_context() + { + mbedtls_entropy_free(this); + } + + protected: + #if !defined(_WIN32) && defined(MBEDTLS_FS_IO) + static int dev_random_entropy_poll(void* data, unsigned char* output, size_t len, size_t* olen) + { + _Unreferenced_(data); + *olen = 0; + FILE* file = fopen("/dev/random", "rb"); + if (file == NULL) + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + size_t left = len; + unsigned char* p = output; + while (left) { + // /dev/random can return much less than requested. If so, try again. + size_t ret = fread(p, 1, left, file); + if (ret == 0 && ferror(file)) { + fclose(file); + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + } + p += ret; + left -= ret; + if (!left) + break; + sleep(1); + } + fclose(file); + *olen = len; + return 0; + } + #endif + }; + + /// + /// The MbedTLS CTR_DRBG context structure + /// + struct ctr_drbg_context : public mbedtls_ctr_drbg_context + { + ctr_drbg_context() { mbedtls_ctr_drbg_init(this); } + ~ctr_drbg_context() { mbedtls_ctr_drbg_free(this); } + }; + + /// + /// MbedTLS MPI + /// + struct mpi : public mbedtls_mpi + { + mpi() { mbedtls_mpi_init(this); } + ~mpi() { mbedtls_mpi_free(this); } + }; + + /// + /// MbedTLS public key container + /// + struct pk_context : public mbedtls_pk_context + { + pk_context() { mbedtls_pk_init(this); } + ~pk_context() { mbedtls_pk_free(this); } + }; + + /// + /// MbedTLS container for an X.509 certificate + /// + struct x509_crt : public mbedtls_x509_crt + { + x509_crt() { mbedtls_x509_crt_init(this); } + ~x509_crt() { mbedtls_x509_crt_free(this); } + }; + + /// + /// MbedTLS Container for writing a certificate (CRT) + /// + struct x509write_cert : public mbedtls_x509write_cert + { + x509write_cert() { mbedtls_x509write_crt_init(this); } + ~x509write_cert() { mbedtls_x509write_crt_free(this); } + }; + + /// + /// MbedTLS global initializer + /// + class initializer + { + public: + /// + /// Initializes MbedTLS library + /// + initializer() + { +#ifdef MBEDTLS_USE_PSA_CRYPTO + auto status = psa_crypto_init(); + if (status != PSA_SUCCESS) + throw runtime_error("Failed to initialize PSA Crypto implementation"); +#endif + } + + ~initializer() + { +#ifdef MBEDTLS_USE_PSA_CRYPTO + mbedtls_psa_crypto_free(); +#endif + } + }; + } +}