OPENSSL-THREADS(7ossl)
π openssl-threads, aka the 7ossl glow-up
okay so this is the OpenSSL thread-safety overview page β the <italic>openssl-threads</italic> man page, section 7ossl. bestie, grab a boba, because we're about to talk about what's safe to touch from more than one thread at once and what absolutely is not π«Ά
β¨ NAME β¨
openssl-threads β the whole overview of thread safety in OpenSSL. yes, the whole vibe check π
πΈ DESCRIPTION πΈ
In this man page, we use the term thread-safe to mean that an object or function can be used by multiple threads at the same time. that's it, that's the definition, no cap.
OpenSSL can be built with or without threads support. the biggest glow-up of this support? it's so that OpenSSL itself can use a single consistent API, exactly as shown in "EXAMPLES" in CRYPTO_THREAD_run_once(3). multi-platform applications can also use this API β it's giving "works everywhere, hun" β¨
okay but here's the part where I need you to listen, because it's lowkey important: being configured for threads support does not imply that all OpenSSL objects are thread-safe. like, to emphasize: most objects are not safe for simultaneous use. exceptions to this should be documented on the specific manual pages, and some general high-level guidance is given right here. so don't come for me if you assumed otherwise π
π reference counting, aka the "don't leak on exit" situation
One major use of the OpenSSL thread API is to implement reference counting. Many objects within OpenSSL are reference-counted, so resources are not released until the last reference is removed. references are often increased automatically β like when an X509 certificate object is added into an X509_STORE trust store. there's often an object_up_ref() function you can call to bump the reference count.
and here's the classic oopsie: failure to match object_up_ref() calls with the right number of object_free() calls is a common source of memory leaks when a program exits. the way that leaks just sit there being messy π match your calls, bestie, periodt.
π¦ set0, get0, set1, get1 β the ownership lore
Many objects have set and get APIs to set attributes in the object. here's the breakdown, iykyk:
- a
"set0"passes ownership from the caller to the object - a
"get0"returns a pointer, but the attribute ownership remains with the object, and a reference to it is returned - a
"set1"or"get1"function does not change the ownership, but instead updates the attribute's reference count so that the object is shared between the caller and the object β and the caller must free the returned attribute when finished
Functions that involve attributes that have reference counts themselves, but are named with just "set" or "get", are historical; and the documentation must state how the references are handled. iconically vague, but that's the rule π
Get methods are often thread-safe as long as the ownership requirements are met and shared objects are not modified. Set methods, or modifying shared objects, are generally not thread-safe, as discussed below. slay responsibly.
π const is a vibe, not a promise
Objects are thread-safe as long as the APIs being invoked don't modify the object; in this case the parameter is usually marked in the API as "const". not all parameters are marked this way though π
and note that a "const" declaration does not mean immutable. for example X509_cmp(3) takes pointers to "const" objects, but the implementation uses a C cast to remove that so it can lock objects, generate and cache a DER encoding, and so on. it's giving "const in the streets, casting in the sheets" π
π§ other thread-safety situations
Another instance of thread-safety is when updates to an object's internal state β such as cached values β are done with locks. one example of this is the reference counting APIs described above. locked and loaded, literally π₯
In all cases, however, it's generally not safe for one thread to mutate an object, such as setting elements of a private or public key, while another thread is using that object, such as verifying a signature. that's a no from me, bestie π
The same APIs can usually be used simultaneously on different objects without interference. for example, two threads can calculate a signature using two different EVP_PKEY_CTX objects. two contexts, two threads, zero drama β¨
π global state & singletons: depends on the facility
For implicit global state or singletons, thread-safety depends on the facility:
CRYPTO_secure_malloc(3)and related APIs have their own lock πCRYPTO_malloc(3)assumes the underlying platform allocation will do any necessary locking- some APIs, such as
NCONF_load(3)and related, do no locking at all β this can be considered a bug π
β factory objects β do not touch after use
A separate, although related, issue is modifying "factory" objects when other objects have been created from that. for example, an SSL_CTX object created by SSL_CTX_new(3) is used to create per-connection SSL objects by calling SSL_new(3).
In this specific case, and probably for factory methods in general, it is not safe to modify the factory object after it has been used to create other objects. hands off the factory, babe π
π₯ THREAD CANCELLATION π₯
Thread safety does not imply cancellation safety. unless a specific function documents otherwise, OpenSSL does not guarantee that an in-progress call can be abandoned safely by thread cancellation or forced termination. an interruption can leave locks held, resources unreleased, or shared state inconsistent β making later use or cleanup unsafe. that's a big yikes π
Deferred cancellation can take effect at a cancellation point reached directly or through a callback, BIO, provider, or other pluggable implementation. automatic thread-local cleanup and OPENSSL_thread_stop(3), when they run, do not unwind the interrupted call. so like, no, it won't clean up after you π«
Applications should act on cancellation only between OpenSSL calls. on POSIX systems, applications using pthread cancellation should disable cancellation with pthread_setcancelstate() before entering OpenSSL and restore it only after OpenSSL returns at a point safe for cancellation. callbacks invoked by OpenSSL must not re-enable it. and heads up: disabling cancellation does not make a blocking call return on a cancellation request; applications requiring prompt cancellation should use nonblocking operation where available.
β οΈ The same restriction applies to other non-local exits which abandon an OpenSSL call in progress, including direct thread exit, long jumps, and language exceptions. do not do it, bestie, I'm begging π₯Ί
π SEE ALSO π
CRYPTO_THREAD_run_once(3)OPENSSL_thread_stop(3)openssl-quic-concurrency(7)- local system threads documentation
go read them, they're iconic π
π BUGS π
This page is admittedly very incomplete. (she said it, not me π)
πΈ COPYRIGHT πΈ
Copyright 2021-2026 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 π this was OpenSSL 3.5.9, dated 2026-09-29 β the <italic>OPENSSL-THREADS(7ossl)</italic> girly herself. stay safe out there, lock your shared state, and don't cancel threads mid-OpenSSL-call. mwah ππ¦
π¦ where this page comes from
- alpine 3.23: openssl-doc 3.5.9-r0 Β· Apache-2.0
- alpine 3.24: openssl-doc 3.5.9-r0 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms