OPENSSL-THREADS(7ossl)

πŸ“¦ version 3.5.0, in opensuse-leap 16.0

OPENSSL-THREADS πŸ’… (that's the 7ossl manual page, bestie)

okay so welcome to the thread-safety overview page, aka the "can two threads touch this at the same time" page. it's openssl-threads, and yes it's giving very much read this before you parallelize anything energy. 🧡✨


NAME πŸŽ€

openssl-threads β€” Overview of thread safety in OpenSSL


DESCRIPTION ✨

okay so first, definitions, because words matter πŸ’… 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 bar.

OpenSSL can be built with or without threads support. and like, the biggest use of that support is so OpenSSL itself can use a single consistent API β€” the receipts are in "EXAMPLES" in CRYPTO_THREAD_run_once(3). Multi-platform applications can also use this API. slay for portability 🫢

but here's the thing, and I need you to hear me on this one:

being configured for threads support does not imply that all OpenSSL objects are thread-safe. To emphasize: most objects are not safe for simultaneous use.

exceptions to that should be documented on the specific manual pages, and some general high-level guidance is given right here. so no cap, read this first.

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 (such as when an X509 certificate object is added into an X509_STORE trust store). There is often an object_up_ref() function that can be used to increase the reference count. And ngl β€” 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. 😭 so like, count your refs, bestie.

Many objects have set and get API's to set attributes in the object. the ownership tea β˜•:

  • 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. (iykyk, legacy vibes πŸ™ˆ)

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. πŸ’€

Objects are thread-safe as long as the API's 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, unfortunately. And heads up β€” 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. the audacity honestly ✨

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 API's described above. πŸ‘‘

In all cases, however, it is 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. like, do not do that. please. 🫢

The same API's 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. different objects = different vibes, no drama 🌈

For implicit global state or singletons, thread-safety depends on the facility:

  • CRYPTO_secure_malloc(3) and related API's have their own lock
  • CRYPTO_malloc(3) assumes the underlying platform allocation will do any necessary locking
  • Some API's, such as NCONF_load(3) and related, do no locking at all β€” this can be considered a bug πŸ’€

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. main character object can't just change its whole personality mid-scene πŸŽ€


SEE ALSO πŸ¦‹


BUGS πŸ™ˆ

This page is admittedly very incomplete. (yes, the man page itself is saying it. iconic honesty tbh.)


Copyright 2021 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-THREADS(7ossl) from OpenSSL 3.5.0, dated 2026-09-25 β€” go forth and lock your shared state, ily, bye! πŸŽ€βœ¨πŸ«Ά

πŸ“¦ where this page comes from