wolfSSL_X509_STORE_CTX_set_verify_cb stored the application callback in
ctx->verify_cb, but every verification site read ctx->store->verify_cb
instead, so the field was never consulted. An application installing a
restrictive callback on the store context, which is the OpenSSL
documented way to enforce extra policy during verification, had it
silently ignored, and wolfSSL_X509_verify_cert could report success on a
chain the callback would have rejected.
Add X509StoreGetVerifyCb, which prefers the context callback and falls
back to the store one, and use it at all four call sites in
X509StoreVerifyCert, X509StoreCheckPathLen and wolfSSL_X509_verify_cert.
The store fallback keeps its OPENSSL_ALL or WOLFSSL_QT guard because the
store field only exists there, while the call sites now follow the
OPENSSL_EXTRA guard of the setter. Clear ctx->verify_cb in
wolfSSL_X509_STORE_CTX_init along with the other per-verification state
so a reused context does not carry a stale callback.
A rejection also has to be reportable. When the certificate manager
accepts a chain, ctx->error is X509_V_OK, so a callback that rejects it
without recording an error of its own left wolfSSL_X509_verify_cert
returning failure while X509_STORE_CTX_get_error still said the chain
was fine. Record WOLFSSL_X509_V_ERR_UNSPECIFIED in that case, matching
what OpenSSL reports, and only when the callback set no error itself.
Add that value to the X509 error enum, where the openssl compatibility
header already had the define.
Feeding the rejection marker to SetupStoreCtxError is not an option
there, since GetX509Error has no X509_V_ error for it and would pass the
negative value through as the reported error. The OPENSSL_ALL date
recheck did exactly that after a rejection, so skip that block once the
callback has rejected, which also stops it from consulting the callback
a second time.
Add a regression test that verifies a good chain twice, once bare and
once with a rejecting context callback, requires the second attempt to
fail, and checks the reported error both when the callback records one
and when it does not.
Fixes F-7341.