Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/configs/os-check-linux.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@
{"name": "dtls13-ocspstapling-cert-cb", "minutes": 3.1,
"configure": ["--enable-dtls", "--enable-dtls13", "--enable-ocspstapling",
"--enable-ocspstapling2", "--enable-cert-setup-cb", "--enable-sessioncerts"]},
{"name": "chain-verify-cb", "minutes": 3.1,
"comment": "postauth, stapling and rpk exercise the callback's resume-from-read and fail-hard paths.",
"configure": ["--enable-chain-verify-cb", "--enable-opensslextra",
"--enable-sessioncerts", "--enable-smallstack", "--enable-postauth",
"--enable-ocspstapling", "--enable-rpk"]},
{"name": "chain-verify-cb-nonblock-ocsp", "minutes": 3.1,
"comment": "chain verify callback alongside the other handshake-suspend feature, and DTLS.",
"configure": ["--enable-chain-verify-cb", "--enable-ocsp", "--enable-crl",
"--enable-dtls", "CPPFLAGS=-DWOLFSSL_NONBLOCK_OCSP"]},
{"name": "tsp-verifier", "minutes": 3,
"comment": "Time-Stamp Protocol Verifier",
"configure": ["--enable-tsp", "--enable-opensslall",
Expand Down
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,11 @@ add_option("WOLFSSL_CERTGENCACHE"
"Enable decoded cert caching (default: disabled)"
"no" "yes;no")

# Chain verify callback
add_option("WOLFSSL_CHAIN_VERIFY_CB"
"Enable replacing peer certificate verification with a user callback (default: disabled)"
"no" "yes;no")

# HKDF
add_option("WOLFSSL_HKDF"
"Enable HKDF (HMAC-KDF) support (default: disabled)"
Expand Down Expand Up @@ -3118,6 +3123,10 @@ if(WOLFSSL_CERTGENCACHE)
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_CERT_GEN_CACHE")
endif()

if(WOLFSSL_CHAIN_VERIFY_CB)
list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_CHAIN_VERIFY_CB")
endif()

if(WOLFSSL_CRYPTOCB)
list(APPEND WOLFSSL_DEFINITIONS "-DWOLF_CRYPTO_CB")
endif()
Expand Down
3 changes: 3 additions & 0 deletions cmake/options.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,9 @@ extern "C" {
#cmakedefine WOLFSSL_ALWAYS_VERIFY_CB
#undef WOLFSSL_CERT_SETUP_CB
#cmakedefine WOLFSSL_CERT_SETUP_CB

#undef WOLFSSL_CHAIN_VERIFY_CB
#cmakedefine WOLFSSL_CHAIN_VERIFY_CB
#undef WOLFSSL_CIPHER_INTERNALNAME
#cmakedefine WOLFSSL_CIPHER_INTERNALNAME
#undef WOLFSSL_DER_LOAD
Expand Down
11 changes: 11 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,7 @@ then
test "$enable_savesession" = "" && enable_savesession=yes
test "$enable_savecert" = "" && enable_savecert=yes
test "$enable_postauth" = "" && enable_postauth=yes
test "$enable_chain_verify_cb" = "" && enable_chain_verify_cb=yes
test "$enable_hrrcookie" = "" && enable_hrrcookie=yes
test "$enable_crl_monitor" = "" && enable_crl_monitor=yes
test "$enable_sni" = "" && enable_sni=yes
Expand Down Expand Up @@ -12206,6 +12207,13 @@ AC_ARG_ENABLE([cert-setup-cb],
[ ENABLED_CERT_SETUP_CB=no ]
)

# Replaces peer certificate chain verification with an application callback
AC_ARG_ENABLE([chain-verify-cb],
[AS_HELP_STRING([--enable-chain-verify-cb],[Enable replacing peer certificate verification with a user callback (default: disabled)])],
[ ENABLED_CHAIN_VERIFY_CB=$enableval ],
[ ENABLED_CHAIN_VERIFY_CB=no ]
)

# check if should run the trusted peer certs test
# (for now checking both C_FLAGS and C_EXTRA_FLAGS)
AS_CASE(["$CFLAGS $CPPFLAGS"],[*'WOLFSSL_TRUST_PEER_CERT'*],[ENABLED_TRUSTED_PEER_CERT=yes])
Expand Down Expand Up @@ -12715,6 +12723,9 @@ AS_IF([test "x$ENABLED_RPK" = "xyes"],
AS_IF([test "x$ENABLED_CERT_SETUP_CB" = "xyes"],
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_SETUP_CB"])

AS_IF([test "x$ENABLED_CHAIN_VERIFY_CB" = "xyes"],
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CHAIN_VERIFY_CB"])

AS_IF([test "x$ENABLED_ALTNAMES" = "xyes"],
[AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALT_NAMES"])

Expand Down
153 changes: 153 additions & 0 deletions doc/dox_comments/header_files/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3187,6 +3187,159 @@ void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx);
*/
void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx);

/*!
\ingroup CertsKeys

\brief Replaces wolfSSL's verification of the peer's certificate chain with
an application callback, for every SSL/TLS object created from the context.
When a callback is set, wolfSSL decodes the certificates from the
Certificate message and hands them to the callback as raw DER, the peer's
own certificate first. It builds no chain, verifies no signature and checks
no date, revocation status, key usage or host name, and the verify callback
set with wolfSSL_CTX_set_verify() is not called; the callback is consulted
even under WOLFSSL_VERIFY_NONE. Malformed DER, or a certificate the parser
refuses regardless of the verify mode such as one with a zero serial
number, still fails the handshake before the callback is called. The
callback returns 0 to accept, CHAIN_VERIFY_WANT_E to suspend the handshake
until the application re-enters wolfSSL_connect(), wolfSSL_accept(),
wolfSSL_read() or wolfSSL_write() (a certificate received after the
handshake is resumed by wolfSSL_read() only, and wolfSSL_write() fails with
CHAIN_VERIFY_WANT_E until then), or any other value to reject with
CHAIN_VERIFY_CB_E and a fatal bad_certificate alert. DTLS, raw public keys
and OCSP stapling are not supported with the callback: setting it on a
context configured for one of them fails, and so does the handshake of a
connection using one of them, with CHAIN_VERIFY_UNSUPPORTED_E. Requires
WOLFSSL_CHAIN_VERIFY_CB (--enable-chain-verify-cb).

\return WOLFSSL_SUCCESS on success.
\return BAD_FUNC_ARG when ctx is NULL.
\return CHAIN_VERIFY_UNSUPPORTED_E when the context uses a DTLS method,
raw public keys or OCSP stapling.

\param ctx pointer to the SSL context, created with wolfSSL_CTX_new().
\param cb the callback, or NULL to clear it.

_Example_
\code
static int myChainVerify(WOLFSSL* ssl, const WOLFSSL_BUFFER_INFO* certs,
int certsSz, void* ctx)
{
// certs[0] is the peer's certificate, the rest is the chain it sent
if (!hsmVerifyStarted(certs, certsSz))
return CHAIN_VERIFY_WANT_E; // ask again later
return hsmVerifyPassed() ? 0 : -1;
}
...
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(method);
if (wolfSSL_CTX_SetChainVerifyCb(ctx, myChainVerify) != WOLFSSL_SUCCESS) {
// context uses DTLS, raw public keys or OCSP stapling
}
\endcode

\sa wolfSSL_SetChainVerifyCb
\sa wolfSSL_CTX_SetChainVerifyCtx
\sa wolfSSL_SetChainVerifyCtx
\sa wolfSSL_GetChainVerifyCtx
*/
int wolfSSL_CTX_SetChainVerifyCb(WOLFSSL_CTX* ctx, ChainVerifyCb cb);

/*!
\ingroup CertsKeys

\brief Sets the chain verification callback for one SSL/TLS object. It
takes precedence over the callback set on the context with
wolfSSL_CTX_SetChainVerifyCb(), which documents the callback's contract.

\return WOLFSSL_SUCCESS on success.
\return BAD_FUNC_ARG when ssl is NULL.
\return CHAIN_VERIFY_UNSUPPORTED_E when the object uses DTLS, raw public
keys or OCSP stapling.

\param ssl pointer to the SSL session, created with wolfSSL_new().
\param cb the callback, or NULL to fall back to the context's.

_Example_
\code
WOLFSSL* ssl = wolfSSL_new(ctx);
if (wolfSSL_SetChainVerifyCb(ssl, myChainVerify) != WOLFSSL_SUCCESS) {
// object uses DTLS, raw public keys or OCSP stapling
}
\endcode

\sa wolfSSL_CTX_SetChainVerifyCb
\sa wolfSSL_SetChainVerifyCtx
*/
int wolfSSL_SetChainVerifyCb(WOLFSSL* ssl, ChainVerifyCb cb);

/*!
\ingroup CertsKeys

\brief Sets the user context passed to the chain verification callback
for every SSL/TLS object created from the context.

\return none No return.

\param ctx pointer to the SSL context, created with wolfSSL_CTX_new().
\param userCtx the value the callback receives as its ctx argument.

_Example_
\code
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(method);
wolfSSL_CTX_SetChainVerifyCb(ctx, myChainVerify);
wolfSSL_CTX_SetChainVerifyCtx(ctx, &myHsm);
\endcode

\sa wolfSSL_CTX_SetChainVerifyCb
\sa wolfSSL_SetChainVerifyCtx
\sa wolfSSL_GetChainVerifyCtx
*/
void wolfSSL_CTX_SetChainVerifyCtx(WOLFSSL_CTX* ctx, void* userCtx);

/*!
\ingroup CertsKeys

\brief Sets the user context passed to the chain verification callback
for one SSL/TLS object. It takes precedence over the value set on the
context with wolfSSL_CTX_SetChainVerifyCtx().

\return none No return.

\param ssl pointer to the SSL session, created with wolfSSL_new().
\param ctx the value the callback receives as its ctx argument, or NULL
to fall back to the context's.

_Example_
\code
WOLFSSL* ssl = wolfSSL_new(ctx);
wolfSSL_SetChainVerifyCtx(ssl, &myConnectionState);
\endcode

\sa wolfSSL_CTX_SetChainVerifyCtx
\sa wolfSSL_GetChainVerifyCtx
*/
void wolfSSL_SetChainVerifyCtx(WOLFSSL* ssl, void* ctx);

/*!
\ingroup CertsKeys

\brief Returns the user context the chain verification callback is
called with for this SSL/TLS object: the value set with
wolfSSL_SetChainVerifyCtx() when there is one, otherwise the context's.

\return void* the user context, or NULL when none is set or ssl is NULL.

\param ssl pointer to the SSL session, created with wolfSSL_new().

_Example_
\code
struct myState* st = (struct myState*)wolfSSL_GetChainVerifyCtx(ssl);
\endcode

\sa wolfSSL_SetChainVerifyCtx
\sa wolfSSL_CTX_SetChainVerifyCtx
*/
void* wolfSSL_GetChainVerifyCtx(const WOLFSSL* ssl);

/*!
\ingroup IO

Expand Down
2 changes: 2 additions & 0 deletions examples/configs/user_settings_all.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ extern "C" {
#define HAVE_OID_ENCODING
#define WOLFSSL_ASN_TEMPLATE
#define WOLFSSL_ALT_NAMES /* Support subject alternative names extension */
/* Replace peer chain verification with an application callback */
#define WOLFSSL_CHAIN_VERIFY_CB

/* Certificate Revocation */
#define HAVE_OCSP
Expand Down
Loading
Loading