LIBRESSL-X509_STORE_CTX_SET_VERIFY(3)
β¨ X509_STORE_CTX_SET_VERIFY(3) β¨
okay so this is a page from the libcrypto fam (hi bestie π), and it's literally all about plugging in your own certificate chain verification function. you can also swap out the check-issued one. it's giving DIY energy and honestly? iconic.
πΈ NAME πΈ
X509_STORE_CTX_verify_fn, X509_STORE_CTX_set_verify, X509_STORE_CTX_get_verify, X509_STORE_set_verify, X509_STORE_set_verify_func, X509_STORE_get_verify, X509_STORE_CTX_check_issued_fn, X509_STORE_set_check_issued, X509_STORE_get_check_issued, X509_STORE_CTX_get_check_issued β user-defined certificate chain verification function π
π¦ SYNOPSIS π¦
the library is libcrypto, and you're gonna want this include:
#include <openssl/x509_vfy.h>
then the function-pointer type for verify:
typedef int
(*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *ctx);
setting it on a ctx:
void
X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx,
X509_STORE_CTX_verify_fn verify);
getting it back off a ctx:
X509_STORE_CTX_verify_fn
X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx);
setting it on a store:
void
X509_STORE_set_verify(X509_STORE *store,
X509_STORE_CTX_verify_fn verify);
the alias version (same vibes, macro flavored):
void
X509_STORE_set_verify_func(X509_STORE *store,
X509_STORE_CTX_verify_fn verify);
getting it off a store β yes, the prototype here really does take an X509_STORE_CTX *, no cap, that's what the page says:
X509_STORE_CTX_verify_fn
X509_STORE_get_verify(X509_STORE_CTX *ctx);
now the check-issued pointer type:
typedef int
(*X509_STORE_CTX_check_issued_fn)(X509_STORE_CTX *ctx, X509 *subject,
X509 *issuer);
setting it on a store:
void
X509_STORE_set_check_issued(X509_STORE *store,
X509_STORE_CTX_check_issued_fn check_issued);
getting it off a store:
X509_STORE_CTX_check_issued_fn
X509_STORE_get_check_issued(X509_STORE *store);
getting it off a ctx:
X509_STORE_CTX_check_issued_fn
X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx);
π DESCRIPTION π
X509_STORE_CTX_set_verify() is the main character here β it configures ctx to use the verify argument as the X.509 certificate chain verification function instead of the default verification function that's built into the library when X509_verify_cert(3) gets called. swap in your own, bestie π
β οΈ okay this part is important, don't skip it: theverifyfunction you provide is only called if theX509_V_FLAG_LEGACY_VERIFYorX509_V_FLAG_NO_ALT_CHAINSflag was set onctxusingX509_STORE_CTX_set_flags(3)orX509_VERIFY_PARAM_set_flags(3). otherwise your function is literally ignored π and a different algorithm is used that does not support replacing the verification function. so set those flags or your custom function is just sitting there uninvited to the party π
X509_STORE_set_verify() saves the function pointer verify in the given store object. that pointer will be copied to an X509_STORE_CTX object when store is later passed as an argument to X509_STORE_CTX_init(3). inheritance slay β¨
X509_STORE_set_verify_func() is an alias for X509_STORE_set_verify() implemented as a macro. same function, different name, we love a duo π«Ά
X509_STORE_set_check_issued() saves the function pointer check_issued in the given store object. that pointer will be copied to an X509_STORE_CTX object when store is later passed as an argument to X509_STORE_CTX_init(3). again: passed down like a family recipe π
so the check_issued function you provide should check whether a given certificate subject was issued using the CA certificate issuer, and it must return 0 on failure and 1 on success. the default implementation ignores the ctx argument and returns success if and only if X509_check_issued(3) returns X509_V_OK.
π₯ THE ORDER THING. pay close attention to the order of theissuerandsubjectarguments. inX509_check_issued(3)theissuerprecedes thesubject, but incheck_issued()thesubjectcomes first. they're flipped. it's confusing. it's a lot. i'm so serious about this one π
π RETURN VALUES π
X509_STORE_CTX_verify_fn()is supposed to return1to indicate that the chain is valid, or0if it is not β or if an error occurred. simple as that β¨X509_STORE_CTX_get_verify()returns a function pointer previously set withX509_STORE_CTX_set_verify()orX509_STORE_CTX_init(3), orNULLifctxis uninitialized.X509_STORE_get_verify()returns the function pointer previously set withX509_STORE_set_verify(), orNULLif that function was not called on the store.X509_STORE_get_check_issued()returns the function pointer previously set withX509_STORE_set_check_issued(), orNULLif that function was not called on the store.X509_STORE_CTX_get_check_issued()returns thecheck_issued()function pointer set on theX509_STORE_CTX. this is either thecheck_issued()function inherited from the store used inX509_STORE_CTX_init(3)or the library's default implementation. bestie got options π
π SEE ALSO π
X509_check_issued(3), X509_STORE_CTX_init(3), X509_STORE_CTX_set_error(3), X509_STORE_CTX_set_flags(3), X509_STORE_CTX_set_verify_cb(3), X509_STORE_new(3), X509_STORE_set_flags(3), X509_STORE_set_verify_cb(3), X509_verify_cert(3), X509_VERIFY_PARAM_set_flags(3)
go read those, iykyk π
π§ HISTORY π§
X509_STORE_set_verify_func()first appeared in SSLeay 0.8.0 and has been available since OpenBSD 2.4. an elder. a pioneer. we respect her πX509_STORE_CTX_set_verify()andX509_STORE_CTX_get_verify()first appeared in OpenSSL 1.1.0 and have been available since OpenBSD 7.1.X509_STORE_CTX_verify_fn(),X509_STORE_set_verify(), andX509_STORE_get_verify()first appeared in OpenSSL 1.1.0 and have been available since OpenBSD 7.2.X509_STORE_set_check_issued(),X509_STORE_get_check_issued(), andX509_STORE_CTX_get_check_issued()first appeared in OpenSSL 1.1.0 and have been available since OpenBSD 7.3.
glow-up timeline fr fr β¨
π BUGS π
the reversal of order of subject and issuer between check_issued() and X509_check_issued(3) is very confusing. it has led to bugs and will cause many more. not me being dramatic, that's literally what the page says π the audacity of this API.
mwah, that's the whole page bestie π this icon dropped with Debian on June 8, 2025 β go forth and verify those chains responsibly π¦β¨
π¦ where this page comes from
- alpine 3.24: libressl-doc 4.3.1-r0 Β· custom
- arch rolling: libressl 4.4.0-1 Β· ISC AND custom:OpenSSL
- Copyright (c) 2021, 2022 Ingo Schwarze <schwarze@openbsd.org>
- Copyright (c) 2023 Job Snijders <job@openbsd.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms