X509_LOOKUP(3SSL)

✨ X509_LOOKUP β€” OpenSSL certificate lookup mechanisms ✨

okay bestie, welcome to the 3SSL manual page πŸ’– this one is all about the little machinery that goes "hmm let me find you a certificate" β€” it's giving librarian energy, but for X.509 objects. no cap.

X509_LOOKUP, X509_LOOKUP_TYPE, X509_LOOKUP_new, X509_LOOKUP_free, X509_LOOKUP_init, X509_LOOKUP_shutdown, X509_LOOKUP_set_method_data, X509_LOOKUP_get_method_data, X509_LOOKUP_ctrl_ex, X509_LOOKUP_ctrl, X509_LOOKUP_load_file_ex, X509_LOOKUP_load_file, X509_LOOKUP_add_dir, X509_LOOKUP_add_store_ex, X509_LOOKUP_add_store, X509_LOOKUP_load_store_ex, X509_LOOKUP_load_store, X509_LOOKUP_get_store, X509_LOOKUP_by_subject_ex, X509_LOOKUP_by_subject, X509_LOOKUP_by_issuer_serial, X509_LOOKUP_by_fingerprint, X509_LOOKUP_by_alias β€” yes all of them, that's the whole squad 🫢


🌸 SYNOPSIS 🌸

#include <openssl/x509_vfy.h>

typedef x509_lookup_st X509_LOOKUP;

typedef enum X509_LOOKUP_TYPE;

X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method);
int X509_LOOKUP_init(X509_LOOKUP *ctx);
int X509_LOOKUP_shutdown(X509_LOOKUP *ctx);
void X509_LOOKUP_free(X509_LOOKUP *ctx);

int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data);
void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx);

int X509_LOOKUP_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
                        char **ret, OSSL_LIB_CTX *libctx, const char *propq);
int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
                     long argl, char **ret);
int X509_LOOKUP_load_file_ex(X509_LOOKUP *ctx, char *name, long type,
                             OSSL_LIB_CTX *libctx, const char *propq);
int X509_LOOKUP_load_file(X509_LOOKUP *ctx, char *name, long type);
int X509_LOOKUP_load_file_ex(X509_LOOKUP *ctx, char *name, long type,
                             OSSL_LIB_CTX *libctx, const char *propq);
int X509_LOOKUP_add_dir(X509_LOOKUP *ctx, char *name, long type);
int X509_LOOKUP_add_store_ex(X509_LOOKUP *ctx, char *uri, OSSL_LIB_CTX *libctx,
                             const char *propq);
int X509_LOOKUP_add_store(X509_LOOKUP *ctx, char *uri);
int X509_LOOKUP_load_store_ex(X509_LOOKUP *ctx, char *uri, OSSL_LIB_CTX *libctx,
                              const char *propq);
int X509_LOOKUP_load_store(X509_LOOKUP *ctx, char *uri);

X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx);

int X509_LOOKUP_by_subject_ex(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                              const X509_NAME *name, X509_OBJECT *ret,
                              OSSL_LIB_CTX *libctx, const char *propq);
int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                           const X509_NAME *name, X509_OBJECT *ret);
int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                                 const X509_NAME *name,
                                 const ASN1_INTEGER *serial, X509_OBJECT *ret);
int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                               const unsigned char *bytes, int len,
                               X509_OBJECT *ret);
int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                         const char *str, int len, X509_OBJECT *ret);

(yes X509_LOOKUP_load_file_ex appears twice up there. that's literally what the header says. we don't edit the header, we respect the header πŸ’…)


πŸ’œ DESCRIPTION πŸ’œ

The X509_LOOKUP structure is the little vault where all the info lives that you need to look up certificates and CRLs, following whatever associated X509_LOOKUP_METHOD(3) you gave it. and here's the slay part: you can stack multiple X509_LOOKUP instances onto one X509_STORE(3) so that store can look things up in all of them. it's giving "one store, many sources" πŸ¦‹

X509_LOOKUP_new() makes a brand new X509_LOOKUP using the lookup method you hand it. you can also get one by calling X509_STORE_add_lookup(3), which β€” plot twist β€” also associates an X509_STORE with the lookup mechanism. iconic.

X509_LOOKUP_init() sets up the internal state and resources the given X509_LOOKUP needs to actually do its job.

X509_LOOKUP_shutdown() tears all that internal state and those resources back down. it's the reverse-glow-up.

X509_LOOKUP_free() destructs the given X509_LOOKUP. and if the argument is NULL? nothing happens. no drama, no crash, we simply do not engage πŸ™ˆ

X509_LOOKUP_set_method_data() and X509_LOOKUP_get_method_data() are besties β€” one associates a pointer to application data with the given X509_LOOKUP, and the other retrieves it back out.

X509_LOOKUP_ctrl_ex() is the setter/getter for extra data on a X509_LOOKUP structure, using any control function from the associated X509_LOOKUP_METHOD(3). the control command's arguments ride in through argc and argl, and the return value comes back through *ret. the library context libctx and property query propq get used when fetching algorithms from providers. what the arguments mean depends entirely on the cmd number of the control command. ngl you generally don't call this one directly β€” you let a macro wrap it for you, see below. the control cmds OpenSSL knows about are discussed deeper in "Control Commands" down there ⬇️

X509_LOOKUP_ctrl() is the same vibe as X509_LOOKUP_ctrl_ex() except it passes NULL for the library context libctx and the property query propq.

X509_LOOKUP_load_file_ex() hands over a filename to be loaded immediately into the associated X509_STORE. the library context libctx and property query propq get used when fetching algorithms from providers. type tells it what kind of object to expect. ⚠️ this one only works with a lookup using the X509_LOOKUP_file(3) implementation.

X509_LOOKUP_load_file() is the same as X509_LOOKUP_load_file_ex() but passes NULL for the library context libctx and property query propq.

X509_LOOKUP_add_dir() hands over a directory specification, and certificates and CRLs get loaded from it on demand into the associated X509_STORE. type says what kind of object to expect. ⚠️ only usable with a lookup using the X509_LOOKUP_hash_dir(3) implementation.

X509_LOOKUP_add_store_ex() hands over a URI for a directory-like structure, and containers holding certificates and CRLs get loaded from it on demand into the associated X509_STORE. the library context libctx and property query propq get used when fetching algorithms from providers.

X509_LOOKUP_add_store() is the same as X509_LOOKUP_add_store_ex() but passes NULL for the library context libctx and property query propq.

X509_LOOKUP_load_store_ex() hands over a URI for a single container, and certificates and CRLs get loaded from it immediately into the associated X509_STORE. the library context libctx and property query propq get used when fetching algorithms from providers. ⚠️ these functions only work with a lookup using the X509_LOOKUP_store(3) implementation.

X509_LOOKUP_load_store() is the same as X509_LOOKUP_load_store_ex() but passes NULL for the library context libctx and property query propq.

and here's the backstage tea πŸŽ€: X509_LOOKUP_load_file_ex(), X509_LOOKUP_load_file(), X509_LOOKUP_add_dir(), X509_LOOKUP_add_store_ex(), X509_LOOKUP_add_store(), X509_LOOKUP_load_store_ex() and X509_LOOKUP_load_store() are all implemented as macros that use X509_LOOKUP_ctrl(). so they're not doing anything mysterious, they're just cute little wrappers, fr fr.

X509_LOOKUP_by_subject_ex(), X509_LOOKUP_by_subject(), X509_LOOKUP_by_issuer_serial(), X509_LOOKUP_by_fingerprint(), and X509_LOOKUP_by_alias() all go look up certificates and CRLs inside the X509_STORE(3) associated with the X509_LOOKUP, each using a different criterion, and the object they found lands in ret. heads up: some of the underlying X509_LOOKUP_METHODs will also cache the objects matching your criteria in the associated X509_STORE, which is exactly what makes it possible to handle the case where your criteria have more than one hit πŸ‘‘


🧁 Control Commands

The X509_LOOKUP_METHODs built into OpenSSL recognize these X509_LOOKUP_ctrl() cmds:

  • X509_L_FILE_LOAD β€” the command that X509_LOOKUP_load_file_ex() and X509_LOOKUP_load_file() use. the filename goes in argc, and the type goes in argl.
  • X509_L_ADD_DIR β€” the command that X509_LOOKUP_add_dir() uses. the directory specification goes in argc, and the type goes in argl.
  • X509_L_ADD_STORE β€” the command that X509_LOOKUP_add_store_ex() and X509_LOOKUP_add_store() use. the URI goes in argc.
  • X509_L_LOAD_STORE β€” the command that X509_LOOKUP_load_store_ex() and X509_LOOKUP_load_store() use. the URI goes in argc.

🌈 RETURN VALUES 🌈

vibe check on what each one hands back:

  • X509_LOOKUP_new() β€” returns an X509_LOOKUP pointer when it slays, or NULL on error 😭
  • X509_LOOKUP_init() and X509_LOOKUP_shutdown() β€” return 1 on success, or 0 on error.
  • X509_LOOKUP_ctrl_ex() and X509_LOOKUP_ctrl() β€” return -1 if the X509_LOOKUP doesn't have an associated X509_LOOKUP_METHOD, or 1 if the method doesn't have a control function. otherwise they return whatever the control function in the X509_LOOKUP_METHOD returns, which is usually 1 on success and 0 on error, but could also be -1 on failure. yes, three possible numbers, keep up bestie πŸ’€
  • X509_LOOKUP_get_store() β€” returns an X509_STORE pointer if there is one, otherwise NULL.
  • X509_LOOKUP_by_subject_ex() β€” returns 0 if there's no X509_LOOKUP_METHOD implementing any of the get_by_subject_ex() or get_by_subject() functions. it calls get_by_subject_ex() if present, otherwise get_by_subject(), and returns that function's result, which is usually 1 on success and 0 on error.
  • X509_LOOKUP_by_subject() β€” same as X509_LOOKUP_by_subject_ex() but passes NULL for both the libctx and propq.
  • X509_LOOKUP_by_issuer_serial(), X509_LOOKUP_by_fingerprint(), and X509_LOOKUP_by_alias() β€” all return 0 if there's no X509_LOOKUP_METHOD, or if that method doesn't implement the corresponding function. otherwise they return whatever the corresponding function in the X509_LOOKUP_METHOD returns, which is usually 1 on success and 0 in error.

πŸ¦‹ SEE ALSO πŸ¦‹

X509_LOOKUP_METHOD(3), X509_STORE(3)

go read those too, they're essential reading, no skips πŸ“š


⭐ HISTORY ⭐

the lore drop:

  • X509_LOOKUP_by_subject_ex() and X509_LOOKUP_ctrl_ex() were added in OpenSSL 3.0.
  • the macros X509_LOOKUP_load_file_ex(), X509_LOOKUP_load_store_ex() and X509_LOOKUP_add_store_ex() were added in OpenSSL 3.0.

so if you're on 3.0+, you're eating good πŸ”₯


Copyright 2020-2025 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>.


and that's the whole page bestie, periodt πŸ’… this was OpenSSL 4.0.3, dated 2026-09-29, living under the X509_LOOKUP(3SSL) name β€” stay certified, stay curious, and go look up some certificates πŸŽ€βœ¨

πŸ“¦ where this page comes from