mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-01 05:02:29 +07:00
Add Mbed TLS 4.x support (PSA Crypto) (#2502)
* Add Mbed TLS 4.x support (PSA Crypto) for macOS Auto-detect Mbed TLS 4.x via MBEDTLS_VERSION_MAJOR and adapt the backend: - Include psa/crypto.h and drop the headers removed in 4.x (ctr_drbg, entropy, md5, sha*), gated behind the version macro. - Compute MD5/SHA-256/SHA-512 via PSA (psa_hash_compute) and initialize PSA Crypto once with std::call_once. - Drop the explicit entropy/CTR-DRBG RNG (PSA provides the TLS RNG) and skip the RNG-callback overloads of pk_parse_key/pk_check_pair on 4.x. - Retry on a TLS 1.3 NewSessionTicket (the 4.x default) in connect, read, write and is_peer_closed via a single mbedtls_is_session_ticket() helper, so online HTTPS works, including large redirected downloads where the ticket arrives mid-write. Note V4 implies V3, so 3.x-only paths now check V3 && !V4. Build systems (macOS): the CMake config and pkg-config shipped by Homebrew resolve 4.x transitively, so CMakeLists.txt and meson.build need no change for linking; the Makefile links libtfpsacrypto when present, else libmbedcrypto. Tests: generate the encrypted client key as both PBES2-AES (3.6+/4.x, OpenSSL, wolfSSL) and PBES1-3DES (Mbed TLS 2.28) and pick by version, since 4.x dropped DES and 2.28 lacks PBES2. Also generate the IP-host certs in test/meson.build to match gen-certs.sh and CMakeLists.txt. * CI: test Mbed TLS 4.x on macOS, 3.x on Ubuntu 26.04 Homebrew's default mbedtls is now 4.x, so switch the macOS build and CI job to it (drop the mbedtls@3 pin). That leaves 3.x (Ubuntu 24.04 apt ships 2.28, macOS now 4.x) uncovered, so add an ubuntu-26.04 job whose apt provides Mbed TLS 3.6. Net coverage: 2.28 (ubuntu-latest), 3.6 (ubuntu-26.04), 4.2 (macOS). ubuntu-26.04 is a public-preview runner image; fold it into the main ubuntu matrix once ubuntu-latest moves to 26.04. * Document Mbed TLS 4.x support and libtfpsacrypto rename Update README.md and the tour's TLS setup pages (en/ja) to note that Mbed TLS 4.x is now auto-detected and that it renames libmbedcrypto to libtfpsacrypto.
This commit is contained in:
@@ -120,6 +120,33 @@ jobs:
|
|||||||
- name: build and run ThreadPool test
|
- name: build and run ThreadPool test
|
||||||
run: cd test && make test_thread_pool && ./test_thread_pool
|
run: cd test && make test_thread_pool && ./test_thread_pool
|
||||||
|
|
||||||
|
# Ubuntu 26.04's apt ships Mbed TLS 3.6, giving 3.x coverage that
|
||||||
|
# ubuntu-latest (24.04 = 2.28) and macOS (Homebrew = 4.x) no longer provide.
|
||||||
|
# Uses the 26.04 public-preview image; fold into the main ubuntu matrix once
|
||||||
|
# ubuntu-latest moves to 26.04.
|
||||||
|
ubuntu-2604-mbedtls:
|
||||||
|
runs-on: ubuntu-26.04
|
||||||
|
if: >
|
||||||
|
(github.event_name == 'push') ||
|
||||||
|
(github.event_name == 'pull_request' &&
|
||||||
|
github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) ||
|
||||||
|
(github.event_name == 'workflow_dispatch' && github.event.inputs.test_linux == 'true')
|
||||||
|
name: ubuntu-26.04 (mbedtls 3.x)
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: install common libraries
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libcurl4-openssl-dev zlib1g-dev libbrotli-dev libzstd-dev
|
||||||
|
- name: install Mbed TLS
|
||||||
|
run: sudo apt-get install -y libmbedtls-dev
|
||||||
|
- name: build and run tests (Mbed TLS)
|
||||||
|
# Run mbedTLS shards with reduced parallelism — under ASAN+mbedTLS the
|
||||||
|
# default 4 shards overload CI runners enough that timing-sensitive
|
||||||
|
# ServerTest cases flake on first-request keep-alive reuse.
|
||||||
|
run: cd test && make test_split_mbedtls && SHARDS=2 make test_mbedtls_parallel
|
||||||
|
|
||||||
# BoringSSL is Google's fork of OpenSSL. It has no API stability guarantee
|
# BoringSSL is Google's fork of OpenSSL. It has no API stability guarantee
|
||||||
# and is not packaged by distros, so we build it from source. cpp-httplib
|
# and is not packaged by distros, so we build it from source. cpp-httplib
|
||||||
# treats it as an OpenSSL backend variant via the OPENSSL_IS_BORINGSSL
|
# treats it as an OpenSSL backend variant via the OPENSSL_IS_BORINGSSL
|
||||||
@@ -372,7 +399,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: install Mbed TLS
|
- name: install Mbed TLS
|
||||||
if: matrix.tls_backend == 'mbedtls'
|
if: matrix.tls_backend == 'mbedtls'
|
||||||
run: brew install mbedtls@3
|
run: brew install mbedtls
|
||||||
- name: install wolfSSL
|
- name: install wolfSSL
|
||||||
if: matrix.tls_backend == 'wolfssl'
|
if: matrix.tls_backend == 'wolfssl'
|
||||||
run: brew install wolfssl
|
run: brew install wolfssl
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ cpp-httplib supports multiple TLS backends through an abstraction layer:
|
|||||||
| Backend | Define | Libraries | Notes |
|
| Backend | Define | Libraries | Notes |
|
||||||
| :------ | :----- | :-------- | :---- |
|
| :------ | :----- | :-------- | :---- |
|
||||||
| OpenSSL | `CPPHTTPLIB_OPENSSL_SUPPORT` | `libssl`, `libcrypto` | [3.0 or later](https://www.openssl.org/policies/releasestrat.html) required |
|
| OpenSSL | `CPPHTTPLIB_OPENSSL_SUPPORT` | `libssl`, `libcrypto` | [3.0 or later](https://www.openssl.org/policies/releasestrat.html) required |
|
||||||
| Mbed TLS | `CPPHTTPLIB_MBEDTLS_SUPPORT` | `libmbedtls`, `libmbedx509`, `libmbedcrypto` | 2.x and 3.x supported (auto-detected) |
|
| Mbed TLS | `CPPHTTPLIB_MBEDTLS_SUPPORT` | `libmbedtls`, `libmbedx509`, `libmbedcrypto` | 2.x, 3.x, and 4.x supported (auto-detected); 4.x renames `libmbedcrypto` to `libtfpsacrypto` |
|
||||||
| wolfSSL | `CPPHTTPLIB_WOLFSSL_SUPPORT` | `libwolfssl` | 5.x supported; must build with `--enable-opensslall` |
|
| wolfSSL | `CPPHTTPLIB_WOLFSSL_SUPPORT` | `libwolfssl` | 5.x supported; must build with `--enable-opensslall` |
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ cpp-httplib also supports Mbed TLS and wolfSSL in addition to OpenSSL. You can s
|
|||||||
| Mbed TLS | `CPPHTTPLIB_MBEDTLS_SUPPORT` | `libmbedtls`, `libmbedx509`, `libmbedcrypto` |
|
| Mbed TLS | `CPPHTTPLIB_MBEDTLS_SUPPORT` | `libmbedtls`, `libmbedx509`, `libmbedcrypto` |
|
||||||
| wolfSSL | `CPPHTTPLIB_WOLFSSL_SUPPORT` | `libwolfssl` |
|
| wolfSSL | `CPPHTTPLIB_WOLFSSL_SUPPORT` | `libwolfssl` |
|
||||||
|
|
||||||
|
Mbed TLS 2.x, 3.x, and 4.x are all supported and auto-detected. Note that Mbed TLS 4.x renames `libmbedcrypto` to `libtfpsacrypto`, so link against that instead.
|
||||||
|
|
||||||
This tour assumes OpenSSL, but the API is the same regardless of which backend you choose.
|
This tour assumes OpenSSL, but the API is the same regardless of which backend you choose.
|
||||||
|
|
||||||
## Next Step
|
## Next Step
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ cpp-httplibはOpenSSL以外にも、Mbed TLSとwolfSSLに対応しています
|
|||||||
| Mbed TLS | `CPPHTTPLIB_MBEDTLS_SUPPORT` | `libmbedtls`, `libmbedx509`, `libmbedcrypto` |
|
| Mbed TLS | `CPPHTTPLIB_MBEDTLS_SUPPORT` | `libmbedtls`, `libmbedx509`, `libmbedcrypto` |
|
||||||
| wolfSSL | `CPPHTTPLIB_WOLFSSL_SUPPORT` | `libwolfssl` |
|
| wolfSSL | `CPPHTTPLIB_WOLFSSL_SUPPORT` | `libwolfssl` |
|
||||||
|
|
||||||
|
Mbed TLSは2.x、3.x、4.xいずれも対応していて、自動判定されます。4.xでは`libmbedcrypto`が`libtfpsacrypto`という名前に変わっているので、リンクするライブラリはそちらに読み替えてください。
|
||||||
|
|
||||||
このTourではOpenSSLを前提に進めますが、APIはどのバックエンドでも共通です。
|
このTourではOpenSSLを前提に進めますが、APIはどのバックエンドでも共通です。
|
||||||
|
|
||||||
## 次のステップ
|
## 次のステップ
|
||||||
|
|||||||
@@ -420,18 +420,26 @@ using socket_t = int;
|
|||||||
#endif // CPPHTTPLIB_OPENSSL_SUPPORT
|
#endif // CPPHTTPLIB_OPENSSL_SUPPORT
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
|
#ifdef CPPHTTPLIB_MBEDTLS_SUPPORT
|
||||||
#include <mbedtls/ctr_drbg.h>
|
// version.h defines MBEDTLS_VERSION_MAJOR (on 2.x/3.x/4.x alike); it is pulled
|
||||||
#include <mbedtls/entropy.h>
|
// in with this first include group so the version gating below can use it.
|
||||||
#include <mbedtls/error.h>
|
#include <mbedtls/error.h>
|
||||||
#include <mbedtls/md5.h>
|
|
||||||
#include <mbedtls/net_sockets.h>
|
#include <mbedtls/net_sockets.h>
|
||||||
#include <mbedtls/oid.h>
|
#include <mbedtls/oid.h>
|
||||||
#include <mbedtls/pk.h>
|
#include <mbedtls/pk.h>
|
||||||
|
#include <mbedtls/ssl.h>
|
||||||
|
#include <mbedtls/version.h>
|
||||||
|
#include <mbedtls/x509_crt.h>
|
||||||
|
#if MBEDTLS_VERSION_MAJOR >= 4
|
||||||
|
// Mbed TLS 4.x moved hashing/RNG to PSA Crypto and removed these headers.
|
||||||
|
#include <psa/crypto.h>
|
||||||
|
#else
|
||||||
|
#include <mbedtls/ctr_drbg.h>
|
||||||
|
#include <mbedtls/entropy.h>
|
||||||
|
#include <mbedtls/md5.h>
|
||||||
#include <mbedtls/sha1.h>
|
#include <mbedtls/sha1.h>
|
||||||
#include <mbedtls/sha256.h>
|
#include <mbedtls/sha256.h>
|
||||||
#include <mbedtls/sha512.h>
|
#include <mbedtls/sha512.h>
|
||||||
#include <mbedtls/ssl.h>
|
#endif
|
||||||
#include <mbedtls/x509_crt.h>
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <wincrypt.h>
|
#include <wincrypt.h>
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -444,7 +452,11 @@ using socket_t = int;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Mbed TLS 3.x API compatibility
|
// Mbed TLS version API compatibility. Note: V4 implies V3 (both defined on
|
||||||
|
// 4.x), so version-specific 3.x-only code must check V3 && !V4.
|
||||||
|
#if MBEDTLS_VERSION_MAJOR >= 4
|
||||||
|
#define CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
#endif
|
||||||
#if MBEDTLS_VERSION_MAJOR >= 3
|
#if MBEDTLS_VERSION_MAJOR >= 3
|
||||||
#define CPPHTTPLIB_MBEDTLS_V3
|
#define CPPHTTPLIB_MBEDTLS_V3
|
||||||
#endif
|
#endif
|
||||||
@@ -3433,8 +3445,11 @@ namespace impl {
|
|||||||
// setup callbacks (cast ctx_t to tls::impl::MbedTlsContext*).
|
// setup callbacks (cast ctx_t to tls::impl::MbedTlsContext*).
|
||||||
struct MbedTlsContext {
|
struct MbedTlsContext {
|
||||||
mbedtls_ssl_config conf;
|
mbedtls_ssl_config conf;
|
||||||
|
#ifndef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
// Mbed TLS 4.x uses PSA Crypto's internal RNG; no explicit entropy/DRBG.
|
||||||
mbedtls_entropy_context entropy;
|
mbedtls_entropy_context entropy;
|
||||||
mbedtls_ctr_drbg_context ctr_drbg;
|
mbedtls_ctr_drbg_context ctr_drbg;
|
||||||
|
#endif
|
||||||
mbedtls_x509_crt ca_chain;
|
mbedtls_x509_crt ca_chain;
|
||||||
mbedtls_x509_crt own_cert;
|
mbedtls_x509_crt own_cert;
|
||||||
mbedtls_pk_context own_key;
|
mbedtls_pk_context own_key;
|
||||||
@@ -9114,9 +9129,31 @@ inline std::string hash_to_hex(const unsigned char (&hash)[N]) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
#ifdef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
// Mbed TLS 4.x provides hashing (and TLS RNG) via PSA Crypto, which must be
|
||||||
|
// initialized once. PSA state is process-global; do not free it.
|
||||||
|
inline bool ensure_mbedtls_psa_crypto() {
|
||||||
|
static std::once_flag once;
|
||||||
|
static bool ok = false;
|
||||||
|
std::call_once(once, []() { ok = (psa_crypto_init() == PSA_SUCCESS); });
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool psa_hash(psa_algorithm_t alg, const std::string &s,
|
||||||
|
unsigned char *out, size_t out_size) {
|
||||||
|
if (!ensure_mbedtls_psa_crypto()) { return false; }
|
||||||
|
size_t olen = 0;
|
||||||
|
return psa_hash_compute(alg, reinterpret_cast<const uint8_t *>(s.data()),
|
||||||
|
s.size(), out, out_size, &olen) == PSA_SUCCESS &&
|
||||||
|
olen == out_size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inline std::string MD5(const std::string &s) {
|
inline std::string MD5(const std::string &s) {
|
||||||
unsigned char hash[16];
|
unsigned char hash[16];
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
#ifdef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
if (!psa_hash(PSA_ALG_MD5, s, hash, sizeof(hash))) { return {}; }
|
||||||
|
#elif defined(CPPHTTPLIB_MBEDTLS_V3)
|
||||||
mbedtls_md5(reinterpret_cast<const unsigned char *>(s.c_str()), s.size(),
|
mbedtls_md5(reinterpret_cast<const unsigned char *>(s.c_str()), s.size(),
|
||||||
hash);
|
hash);
|
||||||
#else
|
#else
|
||||||
@@ -9128,7 +9165,9 @@ inline std::string MD5(const std::string &s) {
|
|||||||
|
|
||||||
inline std::string SHA_256(const std::string &s) {
|
inline std::string SHA_256(const std::string &s) {
|
||||||
unsigned char hash[32];
|
unsigned char hash[32];
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
#ifdef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
if (!psa_hash(PSA_ALG_SHA_256, s, hash, sizeof(hash))) { return {}; }
|
||||||
|
#elif defined(CPPHTTPLIB_MBEDTLS_V3)
|
||||||
mbedtls_sha256(reinterpret_cast<const unsigned char *>(s.c_str()), s.size(),
|
mbedtls_sha256(reinterpret_cast<const unsigned char *>(s.c_str()), s.size(),
|
||||||
hash, 0);
|
hash, 0);
|
||||||
#else
|
#else
|
||||||
@@ -9140,7 +9179,9 @@ inline std::string SHA_256(const std::string &s) {
|
|||||||
|
|
||||||
inline std::string SHA_512(const std::string &s) {
|
inline std::string SHA_512(const std::string &s) {
|
||||||
unsigned char hash[64];
|
unsigned char hash[64];
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
#ifdef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
if (!psa_hash(PSA_ALG_SHA_512, s, hash, sizeof(hash))) { return {}; }
|
||||||
|
#elif defined(CPPHTTPLIB_MBEDTLS_V3)
|
||||||
mbedtls_sha512(reinterpret_cast<const unsigned char *>(s.c_str()), s.size(),
|
mbedtls_sha512(reinterpret_cast<const unsigned char *>(s.c_str()), s.size(),
|
||||||
hash, 0);
|
hash, 0);
|
||||||
#else
|
#else
|
||||||
@@ -18005,6 +18046,20 @@ inline ErrorCode map_mbedtls_error(int ret, int &out_errno) {
|
|||||||
return ErrorCode::Fatal;
|
return ErrorCode::Fatal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A TLS 1.3 NewSessionTicket (signaled by default on Mbed TLS 4.x) is a
|
||||||
|
// non-fatal notification delivered between records, not an error and not
|
||||||
|
// application data, so I/O calls that see it should just be retried. Kept in
|
||||||
|
// one helper so the retry loops keep an intact "do { } while (...)" instead of
|
||||||
|
// splitting the closing brace across an #if.
|
||||||
|
inline bool mbedtls_is_session_ticket(int ret) {
|
||||||
|
#if defined(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
|
||||||
|
return ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;
|
||||||
|
#else
|
||||||
|
(void)ret;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// BIO-like send callback for Mbed TLS
|
// BIO-like send callback for Mbed TLS
|
||||||
inline int mbedtls_net_send_cb(void *ctx, const unsigned char *buf,
|
inline int mbedtls_net_send_cb(void *ctx, const unsigned char *buf,
|
||||||
size_t len) {
|
size_t len) {
|
||||||
@@ -18056,8 +18111,10 @@ inline int mbedtls_net_recv_cb(void *ctx, unsigned char *buf, size_t len) {
|
|||||||
// MbedTlsContext constructor/destructor implementations
|
// MbedTlsContext constructor/destructor implementations
|
||||||
inline MbedTlsContext::MbedTlsContext() {
|
inline MbedTlsContext::MbedTlsContext() {
|
||||||
mbedtls_ssl_config_init(&conf);
|
mbedtls_ssl_config_init(&conf);
|
||||||
|
#ifndef CPPHTTPLIB_MBEDTLS_V4
|
||||||
mbedtls_entropy_init(&entropy);
|
mbedtls_entropy_init(&entropy);
|
||||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||||
|
#endif
|
||||||
mbedtls_x509_crt_init(&ca_chain);
|
mbedtls_x509_crt_init(&ca_chain);
|
||||||
mbedtls_x509_crt_init(&own_cert);
|
mbedtls_x509_crt_init(&own_cert);
|
||||||
mbedtls_pk_init(&own_key);
|
mbedtls_pk_init(&own_key);
|
||||||
@@ -18067,8 +18124,10 @@ inline MbedTlsContext::~MbedTlsContext() {
|
|||||||
mbedtls_pk_free(&own_key);
|
mbedtls_pk_free(&own_key);
|
||||||
mbedtls_x509_crt_free(&own_cert);
|
mbedtls_x509_crt_free(&own_cert);
|
||||||
mbedtls_x509_crt_free(&ca_chain);
|
mbedtls_x509_crt_free(&ca_chain);
|
||||||
|
#ifndef CPPHTTPLIB_MBEDTLS_V4
|
||||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||||
mbedtls_entropy_free(&entropy);
|
mbedtls_entropy_free(&entropy);
|
||||||
|
#endif
|
||||||
mbedtls_ssl_config_free(&conf);
|
mbedtls_ssl_config_free(&conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18142,6 +18201,14 @@ inline ctx_t create_client_context() {
|
|||||||
|
|
||||||
ctx->is_server = false;
|
ctx->is_server = false;
|
||||||
|
|
||||||
|
#ifdef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
// Mbed TLS 4.x draws randomness from PSA Crypto; just ensure it is ready.
|
||||||
|
if (!detail::ensure_mbedtls_psa_crypto()) {
|
||||||
|
delete ctx;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
int ret;
|
||||||
|
#else
|
||||||
// Seed the random number generator
|
// Seed the random number generator
|
||||||
const char *pers = "httplib_client";
|
const char *pers = "httplib_client";
|
||||||
int ret = mbedtls_ctr_drbg_seed(
|
int ret = mbedtls_ctr_drbg_seed(
|
||||||
@@ -18152,6 +18219,7 @@ inline ctx_t create_client_context() {
|
|||||||
delete ctx;
|
delete ctx;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set up SSL config for client
|
// Set up SSL config for client
|
||||||
ret = mbedtls_ssl_config_defaults(&ctx->conf, MBEDTLS_SSL_IS_CLIENT,
|
ret = mbedtls_ssl_config_defaults(&ctx->conf, MBEDTLS_SSL_IS_CLIENT,
|
||||||
@@ -18163,8 +18231,10 @@ inline ctx_t create_client_context() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set random number generator
|
#ifndef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
// Set random number generator (Mbed TLS 4.x uses the PSA RNG implicitly)
|
||||||
mbedtls_ssl_conf_rng(&ctx->conf, mbedtls_ctr_drbg_random, &ctx->ctr_drbg);
|
mbedtls_ssl_conf_rng(&ctx->conf, mbedtls_ctr_drbg_random, &ctx->ctr_drbg);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Default: verify peer certificate
|
// Default: verify peer certificate
|
||||||
mbedtls_ssl_conf_authmode(&ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
mbedtls_ssl_conf_authmode(&ctx->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||||
@@ -18186,6 +18256,14 @@ inline ctx_t create_server_context() {
|
|||||||
|
|
||||||
ctx->is_server = true;
|
ctx->is_server = true;
|
||||||
|
|
||||||
|
#ifdef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
// Mbed TLS 4.x draws randomness from PSA Crypto; just ensure it is ready.
|
||||||
|
if (!detail::ensure_mbedtls_psa_crypto()) {
|
||||||
|
delete ctx;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
int ret;
|
||||||
|
#else
|
||||||
// Seed the random number generator
|
// Seed the random number generator
|
||||||
const char *pers = "httplib_server";
|
const char *pers = "httplib_server";
|
||||||
int ret = mbedtls_ctr_drbg_seed(
|
int ret = mbedtls_ctr_drbg_seed(
|
||||||
@@ -18196,6 +18274,7 @@ inline ctx_t create_server_context() {
|
|||||||
delete ctx;
|
delete ctx;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set up SSL config for server
|
// Set up SSL config for server
|
||||||
ret = mbedtls_ssl_config_defaults(&ctx->conf, MBEDTLS_SSL_IS_SERVER,
|
ret = mbedtls_ssl_config_defaults(&ctx->conf, MBEDTLS_SSL_IS_SERVER,
|
||||||
@@ -18207,8 +18286,10 @@ inline ctx_t create_server_context() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set random number generator
|
#ifndef CPPHTTPLIB_MBEDTLS_V4
|
||||||
|
// Set random number generator (Mbed TLS 4.x uses the PSA RNG implicitly)
|
||||||
mbedtls_ssl_conf_rng(&ctx->conf, mbedtls_ctr_drbg_random, &ctx->ctr_drbg);
|
mbedtls_ssl_conf_rng(&ctx->conf, mbedtls_ctr_drbg_random, &ctx->ctr_drbg);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Default: don't verify client
|
// Default: don't verify client
|
||||||
mbedtls_ssl_conf_authmode(&ctx->conf, MBEDTLS_SSL_VERIFY_NONE);
|
mbedtls_ssl_conf_authmode(&ctx->conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||||
@@ -18368,7 +18449,7 @@ inline bool set_client_cert_pem(ctx_t ctx, const char *cert, const char *key,
|
|||||||
password ? reinterpret_cast<const unsigned char *>(password) : nullptr;
|
password ? reinterpret_cast<const unsigned char *>(password) : nullptr;
|
||||||
size_t pwd_len = password ? strlen(password) : 0;
|
size_t pwd_len = password ? strlen(password) : 0;
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
#if defined(CPPHTTPLIB_MBEDTLS_V3) && !defined(CPPHTTPLIB_MBEDTLS_V4)
|
||||||
ret = mbedtls_pk_parse_key(
|
ret = mbedtls_pk_parse_key(
|
||||||
&mctx->own_key, reinterpret_cast<const unsigned char *>(key_str.c_str()),
|
&mctx->own_key, reinterpret_cast<const unsigned char *>(key_str.c_str()),
|
||||||
key_str.size() + 1, pwd, pwd_len, mbedtls_ctr_drbg_random,
|
key_str.size() + 1, pwd, pwd_len, mbedtls_ctr_drbg_random,
|
||||||
@@ -18383,7 +18464,10 @@ inline bool set_client_cert_pem(ctx_t ctx, const char *cert, const char *key,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the certificate and private key match
|
// Verify that the certificate and private key match.
|
||||||
|
// Mbed TLS 4.x: mbedtls_pk_check_pair() reports a spurious mismatch for
|
||||||
|
// PSA-backed keys, so skip it and let the handshake surface a real mismatch.
|
||||||
|
#ifndef CPPHTTPLIB_MBEDTLS_V4
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
||||||
ret = mbedtls_pk_check_pair(&mctx->own_cert.pk, &mctx->own_key,
|
ret = mbedtls_pk_check_pair(&mctx->own_cert.pk, &mctx->own_key,
|
||||||
mbedtls_ctr_drbg_random, &mctx->ctr_drbg);
|
mbedtls_ctr_drbg_random, &mctx->ctr_drbg);
|
||||||
@@ -18394,6 +18478,7 @@ inline bool set_client_cert_pem(ctx_t ctx, const char *cert, const char *key,
|
|||||||
impl::mbedtls_last_error() = ret;
|
impl::mbedtls_last_error() = ret;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = mbedtls_ssl_conf_own_cert(&mctx->conf, &mctx->own_cert, &mctx->own_key);
|
ret = mbedtls_ssl_conf_own_cert(&mctx->conf, &mctx->own_cert, &mctx->own_key);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@@ -18417,7 +18502,7 @@ inline bool set_client_cert_file(ctx_t ctx, const char *cert_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse private key file
|
// Parse private key file
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
#if defined(CPPHTTPLIB_MBEDTLS_V3) && !defined(CPPHTTPLIB_MBEDTLS_V4)
|
||||||
ret = mbedtls_pk_parse_keyfile(&mctx->own_key, key_path, password,
|
ret = mbedtls_pk_parse_keyfile(&mctx->own_key, key_path, password,
|
||||||
mbedtls_ctr_drbg_random, &mctx->ctr_drbg);
|
mbedtls_ctr_drbg_random, &mctx->ctr_drbg);
|
||||||
#else
|
#else
|
||||||
@@ -18428,7 +18513,9 @@ inline bool set_client_cert_file(ctx_t ctx, const char *cert_path,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the certificate and private key match
|
// Verify that the certificate and private key match.
|
||||||
|
// Mbed TLS 4.x: see set_client_cert() — skip the spurious check_pair.
|
||||||
|
#ifndef CPPHTTPLIB_MBEDTLS_V4
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
||||||
ret = mbedtls_pk_check_pair(&mctx->own_cert.pk, &mctx->own_key,
|
ret = mbedtls_pk_check_pair(&mctx->own_cert.pk, &mctx->own_key,
|
||||||
mbedtls_ctr_drbg_random, &mctx->ctr_drbg);
|
mbedtls_ctr_drbg_random, &mctx->ctr_drbg);
|
||||||
@@ -18439,6 +18526,7 @@ inline bool set_client_cert_file(ctx_t ctx, const char *cert_path,
|
|||||||
impl::mbedtls_last_error() = ret;
|
impl::mbedtls_last_error() = ret;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = mbedtls_ssl_conf_own_cert(&mctx->conf, &mctx->own_cert, &mctx->own_key);
|
ret = mbedtls_ssl_conf_own_cert(&mctx->conf, &mctx->own_cert, &mctx->own_key);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@@ -18533,7 +18621,10 @@ inline TlsError connect(session_t session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto msession = static_cast<impl::MbedTlsSession *>(session);
|
auto msession = static_cast<impl::MbedTlsSession *>(session);
|
||||||
int ret = mbedtls_ssl_handshake(&msession->ssl);
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = mbedtls_ssl_handshake(&msession->ssl);
|
||||||
|
} while (impl::mbedtls_is_session_ticket(ret));
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
err.code = ErrorCode::Success;
|
err.code = ErrorCode::Success;
|
||||||
@@ -18577,6 +18668,8 @@ inline bool connect_nonblocking(session_t session, socket_t sock,
|
|||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
while ((ret = mbedtls_ssl_handshake(&msession->ssl)) != 0) {
|
while ((ret = mbedtls_ssl_handshake(&msession->ssl)) != 0) {
|
||||||
|
// Non-fatal TLS 1.3 ticket; retry immediately.
|
||||||
|
if (impl::mbedtls_is_session_ticket(ret)) { continue; }
|
||||||
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
|
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
|
||||||
if (detail::select_read(sock, timeout_sec, timeout_usec) > 0) {
|
if (detail::select_read(sock, timeout_sec, timeout_usec) > 0) {
|
||||||
continue;
|
continue;
|
||||||
@@ -18624,8 +18717,11 @@ inline ssize_t read(session_t session, void *buf, size_t len, TlsError &err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto msession = static_cast<impl::MbedTlsSession *>(session);
|
auto msession = static_cast<impl::MbedTlsSession *>(session);
|
||||||
int ret =
|
int ret;
|
||||||
mbedtls_ssl_read(&msession->ssl, static_cast<unsigned char *>(buf), len);
|
do {
|
||||||
|
ret = mbedtls_ssl_read(&msession->ssl, static_cast<unsigned char *>(buf),
|
||||||
|
len);
|
||||||
|
} while (impl::mbedtls_is_session_ticket(ret));
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
err.code = ErrorCode::Success;
|
err.code = ErrorCode::Success;
|
||||||
@@ -18654,8 +18750,11 @@ inline ssize_t write(session_t session, const void *buf, size_t len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto msession = static_cast<impl::MbedTlsSession *>(session);
|
auto msession = static_cast<impl::MbedTlsSession *>(session);
|
||||||
int ret = mbedtls_ssl_write(&msession->ssl,
|
int ret;
|
||||||
static_cast<const unsigned char *>(buf), len);
|
do {
|
||||||
|
ret = mbedtls_ssl_write(&msession->ssl,
|
||||||
|
static_cast<const unsigned char *>(buf), len);
|
||||||
|
} while (impl::mbedtls_is_session_ticket(ret));
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
err.code = ErrorCode::Success;
|
err.code = ErrorCode::Success;
|
||||||
@@ -18717,7 +18816,10 @@ inline bool is_peer_closed(session_t session, socket_t sock) {
|
|||||||
// purpose of checking if peer is closed, this should be acceptable
|
// purpose of checking if peer is closed, this should be acceptable
|
||||||
// since we're only called when we expect the connection might be closing
|
// since we're only called when we expect the connection might be closing
|
||||||
unsigned char buf;
|
unsigned char buf;
|
||||||
int ret = mbedtls_ssl_read(&msession->ssl, &buf, 1);
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = mbedtls_ssl_read(&msession->ssl, &buf, 1);
|
||||||
|
} while (impl::mbedtls_is_session_ticket(ret));
|
||||||
|
|
||||||
// If we got data or WANT_READ (would block), connection is alive
|
// If we got data or WANT_READ (would block), connection is alive
|
||||||
if (ret > 0 || ret == MBEDTLS_ERR_SSL_WANT_READ) { return false; }
|
if (ret > 0 || ret == MBEDTLS_ERR_SSL_WANT_READ) { return false; }
|
||||||
@@ -19127,7 +19229,7 @@ inline bool update_server_cert(ctx_t ctx, const char *cert_pem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse private key PEM
|
// Parse private key PEM
|
||||||
#ifdef CPPHTTPLIB_MBEDTLS_V3
|
#if defined(CPPHTTPLIB_MBEDTLS_V3) && !defined(CPPHTTPLIB_MBEDTLS_V4)
|
||||||
ret = mbedtls_pk_parse_key(
|
ret = mbedtls_pk_parse_key(
|
||||||
&mbed_ctx->own_key, reinterpret_cast<const unsigned char *>(key_pem),
|
&mbed_ctx->own_key, reinterpret_cast<const unsigned char *>(key_pem),
|
||||||
strlen(key_pem) + 1,
|
strlen(key_pem) + 1,
|
||||||
|
|||||||
+16
-3
@@ -103,19 +103,32 @@ if(HTTPLIB_IS_USING_OPENSSL)
|
|||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMAND_ERROR_IS_FATAL ANY
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
)
|
)
|
||||||
|
# Encrypted client key: make an unencrypted key + cert first, then wrap the
|
||||||
|
# same key two ways. Mbed TLS 4.x dropped DES/PBES1, while Ubuntu's Mbed TLS
|
||||||
|
# 2.28 has no PBES2-AES, so ship both and let test.cc pick by version.
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${OPENSSL_COMMAND} genrsa -aes256 -passout pass:test012! 2048
|
COMMAND ${OPENSSL_COMMAND} genrsa -out client_encrypted.tmp.key.pem 2048
|
||||||
OUTPUT_FILE client_encrypted.key.pem
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMAND_ERROR_IS_FATAL ANY
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
)
|
)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${OPENSSL_COMMAND} req -new -batch -config ${CMAKE_CURRENT_LIST_DIR}/test.conf -key client_encrypted.key.pem -passin pass:test012!
|
COMMAND ${OPENSSL_COMMAND} req -new -batch -config ${CMAKE_CURRENT_LIST_DIR}/test.conf -key client_encrypted.tmp.key.pem
|
||||||
COMMAND ${OPENSSL_COMMAND} x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial
|
COMMAND ${OPENSSL_COMMAND} x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial
|
||||||
OUTPUT_FILE client_encrypted.cert.pem
|
OUTPUT_FILE client_encrypted.cert.pem
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMAND_ERROR_IS_FATAL ANY
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
)
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${OPENSSL_COMMAND} pkcs8 -topk8 -v2 aes-256-cbc -in client_encrypted.tmp.key.pem -passout pass:test012! -out client_encrypted.key.pem
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${OPENSSL_COMMAND} pkcs8 -topk8 -v1 PBE-SHA1-3DES -in client_encrypted.tmp.key.pem -passout pass:test012! -out client_encrypted_pbes1.key.pem
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
COMMAND_ERROR_IS_FATAL ANY
|
||||||
|
)
|
||||||
|
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/client_encrypted.tmp.key.pem)
|
||||||
# Certificates for IP-host hostname verification regression tests.
|
# Certificates for IP-host hostname verification regression tests.
|
||||||
# cert_ip_cn.pem: CN is an IPv4 literal with NO subjectAltName. An IP host
|
# cert_ip_cn.pem: CN is an IPv4 literal with NO subjectAltName. An IP host
|
||||||
# must NOT be authenticated via the CN, so verifying it
|
# must NOT be authenticated via the CN, so verifying it
|
||||||
|
|||||||
+5
-2
@@ -8,8 +8,11 @@ ifneq ($(OS), Windows_NT)
|
|||||||
OPENSSL_DIR = $(PREFIX)/opt/openssl@3
|
OPENSSL_DIR = $(PREFIX)/opt/openssl@3
|
||||||
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto
|
||||||
OPENSSL_SUPPORT += -framework CoreFoundation -framework Security
|
OPENSSL_SUPPORT += -framework CoreFoundation -framework Security
|
||||||
MBEDTLS_DIR ?= $(shell brew --prefix mbedtls@3)
|
# Homebrew's default mbedtls is 4.x; override MBEDTLS_DIR for other versions.
|
||||||
MBEDTLS_SUPPORT = -DCPPHTTPLIB_MBEDTLS_SUPPORT -I$(MBEDTLS_DIR)/include -L$(MBEDTLS_DIR)/lib -lmbedtls -lmbedx509 -lmbedcrypto
|
MBEDTLS_DIR ?= $(shell brew --prefix mbedtls)
|
||||||
|
# Mbed TLS 4.x renamed libmbedcrypto to libtfpsacrypto; pick whichever exists.
|
||||||
|
MBEDTLS_CRYPTO_LIB ?= $(shell test -f "$(MBEDTLS_DIR)/lib/libtfpsacrypto.dylib" -o -f "$(MBEDTLS_DIR)/lib/libtfpsacrypto.a" && echo tfpsacrypto || echo mbedcrypto)
|
||||||
|
MBEDTLS_SUPPORT = -DCPPHTTPLIB_MBEDTLS_SUPPORT -I$(MBEDTLS_DIR)/include -L$(MBEDTLS_DIR)/lib -lmbedtls -lmbedx509 -l$(MBEDTLS_CRYPTO_LIB)
|
||||||
MBEDTLS_SUPPORT += -framework CoreFoundation -framework Security
|
MBEDTLS_SUPPORT += -framework CoreFoundation -framework Security
|
||||||
WOLFSSL_DIR ?= $(shell brew --prefix wolfssl)
|
WOLFSSL_DIR ?= $(shell brew --prefix wolfssl)
|
||||||
WOLFSSL_SUPPORT = -DCPPHTTPLIB_WOLFSSL_SUPPORT -I$(WOLFSSL_DIR)/include -I$(WOLFSSL_DIR)/include/wolfssl -L$(WOLFSSL_DIR)/lib -lwolfssl
|
WOLFSSL_SUPPORT = -DCPPHTTPLIB_WOLFSSL_SUPPORT -I$(WOLFSSL_DIR)/include -I$(WOLFSSL_DIR)/include/wolfssl -L$(WOLFSSL_DIR)/lib -lwolfssl
|
||||||
|
|||||||
+8
-2
@@ -14,8 +14,14 @@ openssl genrsa 2048 > client.key.pem
|
|||||||
openssl req -new -batch -config test.conf -key client.key.pem | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client.cert.pem
|
openssl req -new -batch -config test.conf -key client.key.pem | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client.cert.pem
|
||||||
openssl genrsa -passout pass:test123! 2048 > key_encrypted.pem
|
openssl genrsa -passout pass:test123! 2048 > key_encrypted.pem
|
||||||
openssl req -new -batch -config test.conf -key key_encrypted.pem | openssl x509 -days 3650 -req -signkey key_encrypted.pem > cert_encrypted.pem
|
openssl req -new -batch -config test.conf -key key_encrypted.pem | openssl x509 -days 3650 -req -signkey key_encrypted.pem > cert_encrypted.pem
|
||||||
openssl genrsa 2048 | openssl pkcs8 -topk8 -v1 PBE-SHA1-3DES -passout pass:test012! -out client_encrypted.key.pem
|
# Encrypted client key: make an unencrypted key + cert first, then wrap the same
|
||||||
openssl req -new -batch -config test.conf -key client_encrypted.key.pem -passin pass:test012! | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client_encrypted.cert.pem
|
# key two ways. Mbed TLS 4.x dropped DES/PBES1, while Ubuntu's Mbed TLS 2.28 has
|
||||||
|
# no PBES2-AES, so ship both and let test.cc pick by version.
|
||||||
|
openssl genrsa 2048 > client_encrypted.tmp.key.pem
|
||||||
|
openssl req -new -batch -config test.conf -key client_encrypted.tmp.key.pem | openssl x509 -days 370 -req -CA rootCA.cert.pem -CAkey rootCA.key.pem -CAcreateserial > client_encrypted.cert.pem
|
||||||
|
openssl pkcs8 -topk8 -v2 aes-256-cbc -in client_encrypted.tmp.key.pem -passout pass:test012! -out client_encrypted.key.pem
|
||||||
|
openssl pkcs8 -topk8 -v1 PBE-SHA1-3DES -in client_encrypted.tmp.key.pem -passout pass:test012! -out client_encrypted_pbes1.key.pem
|
||||||
|
rm -f client_encrypted.tmp.key.pem
|
||||||
|
|
||||||
# Certificates for IP-host hostname verification regression tests.
|
# Certificates for IP-host hostname verification regression tests.
|
||||||
# cert_ip_cn.pem: CN is an IPv4 literal with NO subjectAltName. An IP host must
|
# cert_ip_cn.pem: CN is an IPv4 literal with NO subjectAltName. An IP host must
|
||||||
|
|||||||
+46
-7
@@ -81,17 +81,20 @@ client_cert_pem = custom_target(
|
|||||||
command: [openssl, 'x509', '-in', '@INPUT0@', '-days', '370', '-req', '-CA', '@INPUT1@', '-CAkey', '@INPUT2@', '-CAcreateserial', '-out', '@OUTPUT@']
|
command: [openssl, 'x509', '-in', '@INPUT0@', '-days', '370', '-req', '-CA', '@INPUT1@', '-CAkey', '@INPUT2@', '-CAcreateserial', '-out', '@OUTPUT@']
|
||||||
)
|
)
|
||||||
|
|
||||||
client_encrypted_key_pem = custom_target(
|
# Encrypted client key: make an unencrypted key + cert first, then wrap the same
|
||||||
'client_encrypted_key_pem',
|
# key two ways. Mbed TLS 4.x dropped DES/PBES1, while Ubuntu's Mbed TLS 2.28 has
|
||||||
output: 'client_encrypted.key.pem',
|
# no PBES2-AES, so ship both and let test.cc pick by version.
|
||||||
command: [openssl, 'genrsa', '-aes256', '-passout', 'pass:test012!', '-out', '@OUTPUT@', '2048']
|
client_encrypted_tmp_key_pem = custom_target(
|
||||||
|
'client_encrypted_tmp_key_pem',
|
||||||
|
output: 'client_encrypted.tmp.key.pem',
|
||||||
|
command: [openssl, 'genrsa', '-out', '@OUTPUT@', '2048']
|
||||||
)
|
)
|
||||||
|
|
||||||
client_encrypted_temp_req = custom_target(
|
client_encrypted_temp_req = custom_target(
|
||||||
'client_encrypted_temp_req',
|
'client_encrypted_temp_req',
|
||||||
input: client_encrypted_key_pem,
|
input: client_encrypted_tmp_key_pem,
|
||||||
output: 'client_encrypted_temp_req',
|
output: 'client_encrypted_temp_req',
|
||||||
command: [openssl, 'req', '-new', '-batch', '-config', test_conf, '-key', '@INPUT@', '-passin', 'pass:test012!', '-out', '@OUTPUT@']
|
command: [openssl, 'req', '-new', '-batch', '-config', test_conf, '-key', '@INPUT@', '-out', '@OUTPUT@']
|
||||||
)
|
)
|
||||||
|
|
||||||
client_encrypted_cert_pem = custom_target(
|
client_encrypted_cert_pem = custom_target(
|
||||||
@@ -101,6 +104,39 @@ client_encrypted_cert_pem = custom_target(
|
|||||||
command: [openssl, 'x509', '-in', '@INPUT0@', '-days', '370', '-req', '-CA', '@INPUT1@', '-CAkey', '@INPUT2@', '-CAcreateserial', '-out', '@OUTPUT@']
|
command: [openssl, 'x509', '-in', '@INPUT0@', '-days', '370', '-req', '-CA', '@INPUT1@', '-CAkey', '@INPUT2@', '-CAcreateserial', '-out', '@OUTPUT@']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
client_encrypted_key_pem = custom_target(
|
||||||
|
'client_encrypted_key_pem',
|
||||||
|
input: client_encrypted_tmp_key_pem,
|
||||||
|
output: 'client_encrypted.key.pem',
|
||||||
|
command: [openssl, 'pkcs8', '-topk8', '-v2', 'aes-256-cbc', '-in', '@INPUT@', '-passout', 'pass:test012!', '-out', '@OUTPUT@']
|
||||||
|
)
|
||||||
|
|
||||||
|
client_encrypted_pbes1_key_pem = custom_target(
|
||||||
|
'client_encrypted_pbes1_key_pem',
|
||||||
|
input: client_encrypted_tmp_key_pem,
|
||||||
|
output: 'client_encrypted_pbes1.key.pem',
|
||||||
|
command: [openssl, 'pkcs8', '-topk8', '-v1', 'PBE-SHA1-3DES', '-in', '@INPUT@', '-passout', 'pass:test012!', '-out', '@OUTPUT@']
|
||||||
|
)
|
||||||
|
|
||||||
|
# Certificates for IP-host hostname verification regression tests.
|
||||||
|
# cert_ip_cn.pem: CN is an IPv4 literal with NO subjectAltName, so verifying an
|
||||||
|
# IP host against it must fail (an IP is never matched via the CN).
|
||||||
|
cert_ip_cn_pem = custom_target(
|
||||||
|
'cert_ip_cn_pem',
|
||||||
|
input: key_pem,
|
||||||
|
output: 'cert_ip_cn.pem',
|
||||||
|
command: [openssl, 'req', '-x509', '-key', '@INPUT@', '-sha256', '-days', '3650', '-nodes', '-subj', '/CN=127.0.0.1', '-out', '@OUTPUT@']
|
||||||
|
)
|
||||||
|
|
||||||
|
# cert_ipv6.pem: CN is an IPv6 literal plus a different IPv6 iPAddress SAN; the
|
||||||
|
# SAN address must match and the CN address must be ignored.
|
||||||
|
cert_ipv6_pem = custom_target(
|
||||||
|
'cert_ipv6_pem',
|
||||||
|
input: key_pem,
|
||||||
|
output: 'cert_ipv6.pem',
|
||||||
|
command: [openssl, 'req', '-x509', '-key', '@INPUT@', '-sha256', '-days', '3650', '-nodes', '-subj', '/CN=::1', '-addext', 'subjectAltName=IP:2001:db8::1', '-out', '@OUTPUT@']
|
||||||
|
)
|
||||||
|
|
||||||
# Copy test files to the build directory
|
# Copy test files to the build directory
|
||||||
configure_file(input: 'ca-bundle.crt', output: 'ca-bundle.crt', copy: true)
|
configure_file(input: 'ca-bundle.crt', output: 'ca-bundle.crt', copy: true)
|
||||||
configure_file(input: 'image.jpg', output: 'image.jpg', copy: true)
|
configure_file(input: 'image.jpg', output: 'image.jpg', copy: true)
|
||||||
@@ -139,7 +175,10 @@ test(
|
|||||||
client_key_pem,
|
client_key_pem,
|
||||||
client_cert_pem,
|
client_cert_pem,
|
||||||
client_encrypted_key_pem,
|
client_encrypted_key_pem,
|
||||||
client_encrypted_cert_pem
|
client_encrypted_pbes1_key_pem,
|
||||||
|
client_encrypted_cert_pem,
|
||||||
|
cert_ip_cn_pem,
|
||||||
|
cert_ipv6_pem
|
||||||
],
|
],
|
||||||
workdir: meson.current_build_dir(),
|
workdir: meson.current_build_dir(),
|
||||||
timeout: 300
|
timeout: 300
|
||||||
|
|||||||
+9
-2
@@ -47,7 +47,13 @@ inline std::string u8_to_string(const char8_t *s) {
|
|||||||
#define CLIENT_CERT_FILE "./client.cert.pem"
|
#define CLIENT_CERT_FILE "./client.cert.pem"
|
||||||
#define CLIENT_PRIVATE_KEY_FILE "./client.key.pem"
|
#define CLIENT_PRIVATE_KEY_FILE "./client.key.pem"
|
||||||
#define CLIENT_ENCRYPTED_CERT_FILE "./client_encrypted.cert.pem"
|
#define CLIENT_ENCRYPTED_CERT_FILE "./client_encrypted.cert.pem"
|
||||||
|
// Mbed TLS < 3.6 (e.g. Ubuntu's 2.28) has no PBES2-AES and needs the PBES1-3DES
|
||||||
|
// key; 3.6+/4.x (4.x dropped DES) and OpenSSL/wolfSSL use the PBES2 AES key.
|
||||||
|
#if defined(CPPHTTPLIB_MBEDTLS_SUPPORT) && (MBEDTLS_VERSION_NUMBER < 0x03060000)
|
||||||
|
#define CLIENT_ENCRYPTED_PRIVATE_KEY_FILE "./client_encrypted_pbes1.key.pem"
|
||||||
|
#else
|
||||||
#define CLIENT_ENCRYPTED_PRIVATE_KEY_FILE "./client_encrypted.key.pem"
|
#define CLIENT_ENCRYPTED_PRIVATE_KEY_FILE "./client_encrypted.key.pem"
|
||||||
|
#endif
|
||||||
#define CLIENT_ENCRYPTED_PRIVATE_KEY_PASS "test012!"
|
#define CLIENT_ENCRYPTED_PRIVATE_KEY_PASS "test012!"
|
||||||
#define SERVER_ENCRYPTED_CERT_FILE "./cert_encrypted.pem"
|
#define SERVER_ENCRYPTED_CERT_FILE "./cert_encrypted.pem"
|
||||||
#define SERVER_ENCRYPTED_PRIVATE_KEY_FILE "./key_encrypted.pem"
|
#define SERVER_ENCRYPTED_PRIVATE_KEY_FILE "./key_encrypted.pem"
|
||||||
@@ -18505,9 +18511,10 @@ TEST(SSLClientServerTest, CustomizeServerSSLCtxMbedTLS) {
|
|||||||
if (mbedtls_x509_crt_parse_file(&own_cert, SERVER_CERT_FILE) != 0) {
|
if (mbedtls_x509_crt_parse_file(&own_cert, SERVER_CERT_FILE) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Load server private key
|
// Load server private key.
|
||||||
|
// Mbed TLS 3.x takes an RNG callback here; 2.x and 4.x do not.
|
||||||
if (mbedtls_pk_parse_keyfile(&own_key, SERVER_PRIVATE_KEY_FILE, nullptr
|
if (mbedtls_pk_parse_keyfile(&own_key, SERVER_PRIVATE_KEY_FILE, nullptr
|
||||||
#if MBEDTLS_VERSION_MAJOR >= 3
|
#if MBEDTLS_VERSION_MAJOR == 3
|
||||||
,
|
,
|
||||||
mbedtls_ctr_drbg_random, nullptr
|
mbedtls_ctr_drbg_random, nullptr
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user