X509_VERIFY_CERT(3ossl)
π X509_VERIFY_CERT(3ossl) β like, the whole OpenSSL manpage, bestie
okay so this is one of those OpenSSL manual pages, bestie β the 3ossl girlies β and it's literally all about building and verifying X509 certificate chains. yes, chains. like friendship bracelets but cryptographic. let's get into it β¨
π NAME π
X509_build_chain, X509_verify_cert, X509_STORE_CTX_verify β build and verify X509 certificate chain. that's the whole vibe. no cap.
π¦ SYNOPSIS π¦
like, include this first or nothing works, obviously:
#include <openssl/x509_vfy.h>
STACK_OF(X509) *X509_build_chain(X509 *target, STACK_OF(X509) *certs,
X509_STORE *store, int with_self_signed,
OSSL_LIB_CTX *libctx, const char *propq);
int X509_verify_cert(X509_STORE_CTX *ctx);
int X509_STORE_CTX_verify(X509_STORE_CTX *ctx);
πΈ DESCRIPTION πΈ
π§ X509_build_chain() β the chain-builder era
so X509_build_chain() builds a certificate chain starting from target, using the optional list of intermediate CA certificates certs (optional, bestie, it's optional).
- if
storeisNULL, it builds the chain as far down as possible and ignores errors β like, it's not even mad, it just keeps going π - else the chain must reach a trust anchor contained in
store. no anchor, no slay.
internally it uses an X509_STORE_CTX structure associated with the library context libctx and the property query string propq β both of which may be NULL, so yes you can absolutely pass NULL twice and it will not be weird about it.
and, important: if there's more than one possibility for the chain, only one is taken. it does not audition all the options. it picks one and moves on, main character energy π
on success it returns a pointer to a new stack of (up_ref'ed) certificates, starting with target and followed by all available intermediate certificates. a self-signed trust anchor is included only if target is the trust anchor of with_self_signed is 1. (that's literally how it's worded, we're keeping it, don't @ me.)
π«Ά if a non-NULL stack is returned, the caller is responsible for freeing it. yes, you. it's your stack now. take care of it.
π X509_verify_cert() β the actual vibe check
X509_verify_cert() attempts to discover and validate a certificate chain based on parameters in ctx. so it's like: find the chain, check the chain, be iconic about it.
the verification context, of type X509_STORE_CTX, can be constructed using X509_STORE_CTX_new(3) and X509_STORE_CTX_init(3). it usually includes:
- a target certificate to be verified
- a set of certificates serving as trust anchors
- a list of non-trusted certificates that may be helpful for chain construction
- flags such as
X509_V_FLAG_X509_STRICT - and various other optional components such as a callback function that allows customizing the verification outcome β¨
a complete description of the certificate verification process is contained in the openssl-verification-options(1) manual page β go read that one too, iykwimaityd.
applications rarely call this function directly but it is used by OpenSSL internally for certificate validation, in both the S/MIME and SSL/TLS code. so like, it's the popular girl that everyone secretly relies on.
π a negative return value fromX509_verify_cert()can occur if it is invoked incorrectly, such as with no certificate set inctx, or when it is called twice in succession without reinitialisingctxfor the second call. a negative return value can also happen due to internal resource problems or because an internal inconsistency has been detected. applications must interpret any return value<= 0as an error. literally any of them.<= 0. don't get cute with it.
π X509_STORE_CTX_verify() β the remix
X509_STORE_CTX_verify() behaves like X509_verify_cert() except that its target certificate is the first element of the list of untrusted certificates in ctx unless a target certificate is set explicitly. so it's the same but it picks a target for you. convenient. slay.
π raw public keys β yes, that's a thing
when the verification target is a raw public key, rather than a certificate, both functions validate the target raw public key. in that case the number of possible checks is significantly reduced β like, don't expect the full menu, okay?
the raw public key can be authenticated only via DANE TLSA records, either locally synthesised or obtained by the application from DNS. raw public key DANE TLSA records may be added via SSL_add_expected_rpk(3) or SSL_dane_tlsa_add(3).
β RETURN VALUES β
X509_build_chain()β returnsNULLon error, else a stack of certificates. that's it. that's the whole rule.X509_verify_cert()andX509_STORE_CTX_verify()β both return1if a complete chain can be built and validated, otherwise they return0, and in exceptional circumstances (such as malloc failure and internal errors) they can also return a negative code.
breaking it down even further, because clarity is cute:
- if a complete chain can be built and validated, both functions return
1β - if the certificate must be rejected on the basis of the data available, or any required certificate status data is not available, they return
0β - if no definite answer is possible, they usually return a negative code π€·ββοΈ
on error or failure, additional error information can be obtained by examining ctx using, for example, X509_STORE_CTX_get_error(3).
π also, plot twist: even if verification indicated success, the stored error code may be different from X509_V_OK β likely because a verification callback function has waived the error. so like, check it. don't assume.
π SEE ALSO π
go read these too, they're all part of the lore:
SSL_add_expected_rpk(3)SSL_CTX_dane_enable(3)SSL_dane_tlsa_add(3)X509_STORE_CTX_new(3)X509_STORE_CTX_init(3)X509_STORE_CTX_init_rpk(3)X509_STORE_CTX_get_error(3)
π HISTORY π
X509_build_chain() and X509_STORE_CTX_verify() were added in OpenSSL 3.0. so they're, like, established. not new-new. periodt.
π COPYRIGHT π
Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.
okay bye bestie π«Ά this page was brought to you by OpenSSL 3.5.0, dated 2026-09-25, and it's the X509_VERIFY_CERT(3ossl) manual page β go build some chains that actually validate, love u πβ¨π
π¦ where this page comes from
- opensuse-leap 16.0: openssl-3-doc 3.5.0-160000.11.1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms