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