1# BoringSSL API Conventions 2 3This document describes conventions for BoringSSL APIs. The [style 4guide](./STYLE.md) also includes guidelines, but this document is targeted at 5both API consumers and developers. API documentation in BoringSSL may assume 6these conventions by default, rather than repeating them for every function. 7 8 9## Documentation 10 11All supported public APIs are documented in the public header files, found in 12`include/openssl`. The API documentation is also available 13[online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html). 14 15Experimental public APIs are found in `include/openssl/experimental`. Use of 16these will likely be incompatible with changes in the near future as they are 17finalized. 18 19## Forward declarations 20 21Do not write `typedef struct foo_st FOO` or try otherwise to define BoringSSL's 22types. Including `openssl/base.h` (or `openssl/ossl_typ.h` for consumers who 23wish to be OpenSSL-compatible) will forward-declare each type without importing 24the rest of the library or invasive macros. 25 26 27## Error-handling 28 29Most functions in BoringSSL may fail, either due to allocation failures or input 30errors. Functions which return an `int` typically return one on success and zero 31on failure. Functions which return a pointer typically return `NULL` on failure. 32However, due to legacy constraints, some functions are more complex. Consult the 33API documentation before using a function. 34 35On error, most functions also push errors on the error queue, an `errno`-like 36mechanism. See the documentation for 37[err.h](https://commondatastorage.googleapis.com/chromium-boringssl-docs/err.h.html) 38for more details. 39 40As with `errno`, callers must test the function's return value, not the error 41queue to determine whether an operation failed. Some codepaths may not interact 42with the error queue, and the error queue may have state from a previous failed 43operation. After checking for failure, the caller can then inspect the error 44queue in the failure case for details. 45 46As a notable exception, some functions in the SSL/TLS library use a multi-step 47process to indicate failure: First, the return value indicates whether the 48operation failed. Then, `SSL_get_error` indicates whether the failure was due to 49an error (`SSL_ERROR_SSL`) or some recoverable condition (e.g. 50`SSL_ERROR_WANT_READ`). In the former case, the caller can use the error queue 51for more information. 52 53When ignoring a failed operation, it is recommended to call `ERR_clear_error` to 54avoid the state interacting with future operations. Failing to do so should not 55affect the actual behavior of any functions, but may result in errors from both 56operations being mixed in error logging. We hope to 57[improve](https://bugs.chromium.org/p/boringssl/issues/detail?id=38) this 58situation in the future. 59 60Where possible, avoid conditioning on specific reason codes and limit usage to 61logging. The reason codes are very fine-grained and tend to leak details of the 62library's internal structure. Changes in the library often have a side effect of 63changing the exact reason code returned. 64 65 66## Memory allocation 67 68BoringSSL allocates memory via `OPENSSL_malloc`, found in `mem.h`. Use 69`OPENSSL_free`, found in the same header file, to release it. BoringSSL 70functions will fail gracefully on allocation error, but it is recommended to use 71a `malloc` implementation that `abort`s on failure. 72 73 74## Pointers and slices 75 76Unless otherwise specified, pointer parameters that refer to a single object, 77either as an input or output parameter, may not be `NULL`. In this case, 78BoringSSL often will not check for `NULL` before dereferencing, so passing 79`NULL` may crash or exhibit other undefined behavior. (Sometimes the function 80will check for `NULL` anyway, for OpenSSL compatibility, but we still consider 81passing `NULL` to be a caller error.) 82 83Pointer parameters may also refer to a contiguous sequence of objects, sometimes 84referred to as a *slice*. These will typically be a pair of pointer and length 85parameters named like `plaintext` and `plaintext_len`, or `objs` and `num_objs`. 86We prefer the former for byte buffers and the latter for sequences of other 87types. The documentation will usually refer to both parameters together, e.g. 88"`EVP_DigestUpdate` hashes `len` bytes from `data`." 89 90Parameters in C and C++ that use array syntax, such as 91`uint8_t out[SHA256_DIGEST_LENGTH]`, are really pointers. In BoringSSL's uses of 92this syntax, the pointer must point to the specified number of values. 93 94In other cases, the documentation will describe how the function parameters 95determine the slice's length. For example, a slice's length may be measured in 96units other than element count, multiple slice parameters may share a length, or 97a slice's length may be implicitly determined by other means like RSA key size. 98 99By default, BoringSSL follows C++'s 100[slice conventions](https://davidben.net/2024/01/15/empty-slices.html) 101for pointers. That is, unless otherwise specified, pointers for non-empty 102(non-zero length) slices must be represented by a valid pointer to that many 103objects in memory. Pointers for empty (zero length) slices must either be `NULL` 104or point within some sequence of objects of a compatible type. 105 106WARNING: The dangling, non-null pointer used by Rust empty slices may *not* be 107passed into BoringSSL. Rust FFIs must adjust such pointers to before passing to 108BoringSSL. For example, see the `FfiSlice` abstraction in `bssl-crypto`. (We may 109relax this if pointer arithmetic rules in C/C++ are adjusted to permit Rust's 110pointers. Until then, it is impractical for a C/C++ library to act on such a 111slice representation. See 112[this document](https://davidben.net/2024/01/15/empty-slices.html) for more 113discussion.) 114 115In some cases, OpenSSL compatibility requires that a function will treat `NULL` 116slice pointers differently from non-`NULL` pointers. Such behavior will be 117described in documentation. For examples, see `EVP_EncryptUpdate`, 118`EVP_DigestSignFinal`, and `HMAC_Init_ex`. Callers passing potentially empty 119slices into such functions should take care that the `NULL` case is either 120unreachable or still has the desired behavior. 121 122If a `const char *` parameter is described as a "NUL-terminated string" or a 123"C string", it must point to a sequence of `char` values containing a NUL (zero) 124value, which determines the length. Unless otherwise specified, the pointer may 125not be `NULL`, matching the C standard library. 126 127For purposes of C and C++'s 128[strict aliasing](https://en.cppreference.com/w/c/language/object#Strict_aliasing) 129requirements, objects passed by pointers must be accessible as the specified 130type. `uint8_t` may be assumed to be the same type as `unsigned char` and thus 131may be the pointer type for all object types. BoringSSL does not support 132platforms where `uint8_t` is a non-character type. However, there is no 133strict aliasing sanitizer, very few C and C++ codebases are valid by strict 134aliasing, and BoringSSL itself has some 135[known strict aliasing bugs](https://crbug.com/boringssl/444), thus we strongly 136recommend consumers build with `-fno-strict-aliasing`. 137 138Pointer parameters additionally have ownership and lifetime requirements, 139discussed in the section below. 140 141 142## Object initialization and cleanup 143 144BoringSSL defines a number of structs for use in its APIs. It is a C library, 145so the caller is responsible for ensuring these structs are properly 146initialized and released. Consult the documentation for a module for the 147proper use of its types. Some general conventions are listed below. 148 149 150### Heap-allocated types 151 152Some types, such as `RSA`, are heap-allocated. All instances will be allocated 153and returned from BoringSSL's APIs. It is an error to instantiate a heap- 154allocated type on the stack or embedded within another object. 155 156Heap-allocated types may have functioned named like `RSA_new` which allocates a 157fresh blank `RSA`. Other functions may also return newly-allocated instances. 158For example, `RSA_parse_public_key` is documented to return a newly-allocated 159`RSA` object. 160 161Heap-allocated objects must be released by the corresponding free function, 162named like `RSA_free`. Like C's `free` and C++'s `delete`, all free functions 163internally check for `NULL`. It is redundant to check for `NULL` before calling. 164 165A heap-allocated type may be reference-counted. In this case, a function named 166like `RSA_up_ref` will be available to take an additional reference count. The 167free function must be called to decrement the reference count. It will only 168release resources when the final reference is released. For OpenSSL 169compatibility, these functions return `int`, but callers may assume they always 170successfully return one because reference counts use saturating arithmetic. 171 172C++ consumers are recommended to use `bssl::UniquePtr` to manage heap-allocated 173objects. `bssl::UniquePtr<T>`, like other types, is forward-declared in 174`openssl/base.h`. Code that needs access to the free functions, such as code 175which destroys a `bssl::UniquePtr`, must include the corresponding module's 176header. (This matches `std::unique_ptr`'s relationship with forward 177declarations.) Note, despite the name, `bssl::UniquePtr` is also used with 178reference-counted types. It owns a single reference to the object. To take an 179additional reference, use the `bssl::UpRef` function, which will return a 180separate `bssl::UniquePtr`. 181 182 183### Stack-allocated types 184 185Other types in BoringSSL are stack-allocated, such as `EVP_MD_CTX`. These 186types may be allocated on the stack or embedded within another object. 187However, they must still be initialized before use. 188 189Every stack-allocated object in BoringSSL has a *zero state*, analogous to 190initializing a pointer to `NULL`. In this state, the object may not be 191completely initialized, but it is safe to call cleanup functions. Entering the 192zero state cannot fail. (It is usually `memset(0)`.) 193 194The function to enter the zero state is named like `EVP_MD_CTX_init` or 195`CBB_zero` and will always return `void`. To release resources associated with 196the type, call the cleanup function, named like `EVP_MD_CTX_cleanup`. The 197cleanup function must be called on all codepaths, regardless of success or 198failure. For example: 199 200 uint8_t md[EVP_MAX_MD_SIZE]; 201 unsigned md_len; 202 EVP_MD_CTX ctx; 203 EVP_MD_CTX_init(&ctx); /* Enter the zero state. */ 204 int ok = EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL) && 205 EVP_DigestUpdate(&ctx, "hello ", 6) && 206 EVP_DigestUpdate(&ctx, "world", 5) && 207 EVP_DigestFinal_ex(&ctx, md, &md_len); 208 EVP_MD_CTX_cleanup(&ctx); /* Release |ctx|. */ 209 210Note that `EVP_MD_CTX_cleanup` is called whether or not the `EVP_Digest*` 211operations succeeded. More complex C functions may use the `goto err` pattern: 212 213 int ret = 0; 214 EVP_MD_CTX ctx; 215 EVP_MD_CTX_init(&ctx); 216 217 if (!some_other_operation()) { 218 goto err; 219 } 220 221 uint8_t md[EVP_MAX_MD_SIZE]; 222 unsigned md_len; 223 if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL) || 224 !EVP_DigestUpdate(&ctx, "hello ", 6) || 225 !EVP_DigestUpdate(&ctx, "world", 5) || 226 !EVP_DigestFinal_ex(&ctx, md, &md_len) { 227 goto err; 228 } 229 230 ret = 1; 231 232 err: 233 EVP_MD_CTX_cleanup(&ctx); 234 return ret; 235 236Note that, because `ctx` is set to the zero state before any failures, 237`EVP_MD_CTX_cleanup` is safe to call even if the first operation fails before 238`EVP_DigestInit_ex`. However, it would be illegal to move the `EVP_MD_CTX_init` 239below the `some_other_operation` call. 240 241As a rule of thumb, enter the zero state of stack-allocated structs in the 242same place they are declared. 243 244C++ consumers are recommended to use the wrappers named like 245`bssl::ScopedEVP_MD_CTX`, defined in the corresponding module's header. These 246wrappers are automatically initialized to the zero state and are automatically 247cleaned up. 248 249 250### Data-only types 251 252A few types, such as `SHA_CTX`, are data-only types and do not require cleanup. 253These are usually for low-level cryptographic operations. These types may be 254used freely without special cleanup conventions. 255 256 257### Ownership and lifetime 258 259When working with allocated objects, it is important to think about *ownership* 260of each object, or what code is responsible for releasing it. This matches the 261corresponding notion in higher-level languages like C++ and Rust. 262 263Ownership applies to both uniquely-owned types and reference-counted types. For 264the latter, ownership means the code is responsible for releasing one 265reference. Note a *reference* in BoringSSL refers to an increment (and eventual 266decrement) of an object's reference count, not `T&` in C++. Thus, to "take a 267reference" means to increment the reference count and take ownership of 268decrementing it. 269 270As BoringSSL's APIs are primarily in C, ownership and lifetime obligations are 271not rigorously annotated in the type signatures or checked at compile-time. 272Instead, they are described in 273[API documentation](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html). 274This section describes some conventions. 275 276Unless otherwise documented, functions do not take ownership of pointer 277arguments. The pointer typically must remain valid for the duration of the 278function call. The function may internally copy information from the argument or 279take a reference, but the caller is free to release its copy or reference at any 280point after the call completes. 281 282A function may instead be documented to *take* or *transfer* ownership of a 283pointer. The caller must own the object before the function call and, after 284transfer, no longer owns it. As a corollary, the caller may no longer reference 285the object without a separate guarantee on the lifetime. The function may even 286release the object before returning. Callers that wish to independently retain a 287transfered object must therefore take a reference or make a copy before 288transferring. Callers should also take note of whether the function is 289documented to transfer pointers unconditionally or only on success. Unlike C++ 290and Rust, functions in BoringSSL typically only transfer on success. 291 292Likewise, output pointers may be owning or non-owning. Unless otherwise 293documented, functions output non-owning pointers. The caller is not responsible 294for releasing the output pointer, but it must not use the pointer beyond its 295lifetime. The pointer may be released when the parent object is released or even 296sooner on state change in the parent object. 297 298If documented to output a *newly-allocated* object or a *reference* or *copy* of 299one, the caller is responsible for releasing the object when it is done. 300 301By convention, functions named `get0` return non-owning pointers. Functions 302named `new` or `get1` return owning pointers. Functions named `set0` take 303ownership of arguments. Functions named `set1` do not. They typically take a 304reference or make a copy internally. These names originally referred to the 305effect on a reference count, but the convention applies equally to 306non-reference-counted types. 307 308API documentation may also describe more complex obligations. For instance, an 309object may borrow a pointer for longer than the duration of a single function 310call, in which case the caller must ensure the lifetime extends accordingly. 311 312Memory errors are one of the most common and dangerous bugs in C and C++, so 313callers are encouraged to make use of tools such as 314[AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) and 315higher-level languages. 316 317 318## Thread safety 319 320BoringSSL is internally aware of the platform threading library and calls into 321it as needed. Consult the API documentation for the threading guarantees of 322particular objects. In general, stateless reference-counted objects like `RSA` 323or `EVP_PKEY` which represent keys may typically be used from multiple threads 324simultaneously, provided no thread mutates the key. 325