1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00
Files
wolfssl/.github
Juliusz Sosinowicz 797e34a271 Add WOLFSSL_CHAIN_VERIFY_CB to replace peer chain verification
Adds an opt-in callback that takes over the peer certificate trust
decision. wolfSSL builds no chain, verifies no signature and checks no
date, revocation status, key usage or host name; the verify callback is
not called either. The callback gets only the DER certificates from the
Certificate message as WOLFSSL_BUFFER_INFO entries, certs[0] first. It
is consulted even under WOLFSSL_VERIFY_NONE, and its rejection fails the
handshake either way.

wolfSSL still decodes every certificate with ParseCert(NO_VERIFY) before
the callback runs, so malformed DER fails the handshake and the callback
is never handed it. Content wolfSSL does not understand - an unknown
critical extension, an unsupported key or signature algorithm, a
signature algorithm mismatch - is not a decoding failure and is left for
the callback to judge. The check runs once, not again on re-entry after
a deferred verdict.

The callback may return CHAIN_VERIFY_WANT_E to suspend the handshake and
be asked again with the same certificates when the application re-enters
wolfSSL_connect(), wolfSSL_accept(), wolfSSL_read() or wolfSSL_write().
A certificate received after the handshake (TLS 1.3 post-handshake
authentication) arrives inside wolfSSL_read() and is resumed by reading
again: ReceiveData() re-enters on any handshake-suspend error, and the
ticket-sent accept state leaves a suspended message alone. Rejection
fails with CHAIN_VERIFY_CB_E and one bad_certificate alert, and sets
peerVerifyRet so wolfSSL_get_verify_result() does not report X509_V_OK.

Still applied: an empty Certificate message keeps the existing
mutual-auth policy (the callback is not called for it), and the minimum
peer key sizes still gate the peer's own key, which the handshake uses
directly.

DTLS, raw public keys and OCSP stapling are not supported with the
callback. wolfSSL_CTX_SetChainVerifyCb() and wolfSSL_SetChainVerifyCb()
refuse with CHAIN_VERIFY_UNSUPPORTED_E when the context or object is
already configured for one of them, and a connection that uses one of
them anyway fails with the same error and an internal_error alert before
the callback is called. The DTLS paths are otherwise untouched.

The callback and its user context can be set on the context or on the
SSL object, the object's taking precedence. The feature is part of
--enable-all, has a CMake option and Doxygen entries.

The suspend machinery is shared with WOLFSSL_NONBLOCK_OCSP and
WOLFSSL_ASYNC_CRYPT. The open-coded pairs of comparisons against
WC_PENDING_E and OCSP_WANT_READ are replaced by IsHsSuspendErr(), and the
matching build guards by WOLFSSL_HAVE_HS_SUSPEND. That also closes three
holes which affected WOLFSSL_NONBLOCK_OCSP builds:

 - DoHandShakeMsg() freed ssl->pendingMsg on a non-WC_PENDING_E suspend
   while ProcPeerCertArgs still pointed into it.
 - wolfSSL_connect()/wolfSSL_accept() and their TLS 1.3 counterparts
   called FreeAsyncCtx() when buffered output flushed, discarding the
   saved certificate state.
 - ProcessPeerCerts() XFREE'd args in WOLFSSL_SMALL_STACK builds without
   WOLFSSL_ASYNC_CRYPT, where args points inside ssl->async.
2026-10-13 05:24:59 +00:00
..
2026-09-18 12:58:30 +00:00
2025-02-13 14:50:32 -05:00