xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/API-CONVENTIONS.md (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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.
6
7
8## Documentation
9
10All supported public APIs are documented in the public header files, found in
11`include/openssl`. The API documentation is also available
12[online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
13
14Some headers lack documention comments. These are functions and structures from
15OpenSSL's legacy ASN.1, X.509, and PEM implementation. If possible, avoid using
16them. These are left largely unmodified from upstream and are retained only for
17compatibility with existing OpenSSL consumers.
18
19Experimental public APIs are found in `include/openssl/experimental`. Use of
20these will likely be incompatible with changes in the near future as they are
21finalized.
22
23## Forward declarations
24
25Do not write `typedef struct foo_st FOO` or try otherwise to define BoringSSL's
26types. Including `openssl/base.h` (or `openssl/ossl_typ.h` for consumers who
27wish to be OpenSSL-compatible) will forward-declare each type without importing
28the rest of the library or invasive macros.
29
30
31## Error-handling
32
33Most functions in BoringSSL may fail, either due to allocation failures or input
34errors. Functions which return an `int` typically return one on success and zero
35on failure. Functions which return a pointer typically return `NULL` on failure.
36However, due to legacy constraints, some functions are more complex. Consult the
37API documentation before using a function.
38
39On error, most functions also push errors on the error queue, an `errno`-like
40mechanism. See the documentation for
41[err.h](https://commondatastorage.googleapis.com/chromium-boringssl-docs/err.h.html)
42for more details.
43
44As with `errno`, callers must test the function's return value, not the error
45queue to determine whether an operation failed. Some codepaths may not interact
46with the error queue, and the error queue may have state from a previous failed
47operation.
48
49When ignoring a failed operation, it is recommended to call `ERR_clear_error` to
50avoid the state interacting with future operations. Failing to do so should not
51affect the actual behavior of any functions, but may result in errors from both
52operations being mixed in error logging. We hope to
53[improve](https://bugs.chromium.org/p/boringssl/issues/detail?id=38) this
54situation in the future.
55
56Where possible, avoid conditioning on specific reason codes and limit usage to
57logging. The reason codes are very specific and may change over time.
58
59
60## Memory allocation
61
62BoringSSL allocates memory via `OPENSSL_malloc`, found in `mem.h`. Use
63`OPENSSL_free`, found in the same header file, to release it. BoringSSL
64functions will fail gracefully on allocation error, but it is recommended to use
65a `malloc` implementation that `abort`s on failure.
66
67
68## Object initialization and cleanup
69
70BoringSSL defines a number of structs for use in its APIs. It is a C library,
71so the caller is responsible for ensuring these structs are properly
72initialized and released. Consult the documentation for a module for the
73proper use of its types. Some general conventions are listed below.
74
75
76### Heap-allocated types
77
78Some types, such as `RSA`, are heap-allocated. All instances will be allocated
79and returned from BoringSSL's APIs. It is an error to instantiate a heap-
80allocated type on the stack or embedded within another object.
81
82Heap-allocated types may have functioned named like `RSA_new` which allocates a
83fresh blank `RSA`. Other functions may also return newly-allocated instances.
84For example, `RSA_parse_public_key` is documented to return a newly-allocated
85`RSA` object.
86
87Heap-allocated objects must be released by the corresponding free function,
88named like `RSA_free`. Like C's `free` and C++'s `delete`, all free functions
89internally check for `NULL`. Consumers are not required to check for `NULL`
90before calling.
91
92A heap-allocated type may be reference-counted. In this case, a function named
93like `RSA_up_ref` will be available to take an additional reference count. The
94free function must be called to decrement the reference count. It will only
95release resources when the final reference is released. For OpenSSL
96compatibility, these functions return `int`, but callers may assume they always
97successfully return one because reference counts use saturating arithmetic.
98
99C++ consumers are recommended to use `bssl::UniquePtr` to manage heap-allocated
100objects. `bssl::UniquePtr<T>`, like other types, is forward-declared in
101`openssl/base.h`. Code that needs access to the free functions, such as code
102which destroys a `bssl::UniquePtr`, must include the corresponding module's
103header. (This matches `std::unique_ptr`'s relationship with forward
104declarations.) Note, despite the name, `bssl::UniquePtr` is also used with
105reference-counted types. It owns a single reference to the object. To take an
106additional reference, use the `bssl::UpRef` function, which will return a
107separate `bssl::UniquePtr`.
108
109
110### Stack-allocated types
111
112Other types in BoringSSL are stack-allocated, such as `EVP_MD_CTX`. These
113types may be allocated on the stack or embedded within another object.
114However, they must still be initialized before use.
115
116Every stack-allocated object in BoringSSL has a *zero state*, analogous to
117initializing a pointer to `NULL`. In this state, the object may not be
118completely initialized, but it is safe to call cleanup functions. Entering the
119zero state cannot fail. (It is usually `memset(0)`.)
120
121The function to enter the zero state is named like `EVP_MD_CTX_init` or
122`CBB_zero` and will always return `void`. To release resources associated with
123the type, call the cleanup function, named like `EVP_MD_CTX_cleanup`. The
124cleanup function must be called on all codepaths, regardless of success or
125failure. For example:
126
127    uint8_t md[EVP_MAX_MD_SIZE];
128    unsigned md_len;
129    EVP_MD_CTX ctx;
130    EVP_MD_CTX_init(&ctx);  /* Enter the zero state. */
131    int ok = EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL) &&
132             EVP_DigestUpdate(&ctx, "hello ", 6) &&
133             EVP_DigestUpdate(&ctx, "world", 5) &&
134             EVP_DigestFinal_ex(&ctx, md, &md_len);
135    EVP_MD_CTX_cleanup(&ctx);  /* Release |ctx|. */
136
137Note that `EVP_MD_CTX_cleanup` is called whether or not the `EVP_Digest*`
138operations succeeded. More complex C functions may use the `goto err` pattern:
139
140      int ret = 0;
141      EVP_MD_CTX ctx;
142      EVP_MD_CTX_init(&ctx);
143
144      if (!some_other_operation()) {
145        goto err;
146      }
147
148      uint8_t md[EVP_MAX_MD_SIZE];
149      unsigned md_len;
150      if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL) ||
151          !EVP_DigestUpdate(&ctx, "hello ", 6) ||
152          !EVP_DigestUpdate(&ctx, "world", 5) ||
153          !EVP_DigestFinal_ex(&ctx, md, &md_len) {
154        goto err;
155      }
156
157      ret = 1;
158
159    err:
160      EVP_MD_CTX_cleanup(&ctx);
161      return ret;
162
163Note that, because `ctx` is set to the zero state before any failures,
164`EVP_MD_CTX_cleanup` is safe to call even if the first operation fails before
165`EVP_DigestInit_ex`. However, it would be illegal to move the `EVP_MD_CTX_init`
166below the `some_other_operation` call.
167
168As a rule of thumb, enter the zero state of stack-allocated structs in the
169same place they are declared.
170
171C++ consumers are recommended to use the wrappers named like
172`bssl::ScopedEVP_MD_CTX`, defined in the corresponding module's header. These
173wrappers are automatically initialized to the zero state and are automatically
174cleaned up.
175
176
177### Data-only types
178
179A few types, such as `SHA_CTX`, are data-only types and do not require cleanup.
180These are usually for low-level cryptographic operations. These types may be
181used freely without special cleanup conventions.
182
183
184### Ownership and lifetime
185
186When working with allocated objects, it is important to think about *ownership*
187of each object, or what code is responsible for releasing it. This matches the
188corresponding notion in higher-level languages like C++ and Rust.
189
190Ownership applies to both uniquely-owned types and reference-counted types. For
191the latter, ownership means the code is responsible for releasing one
192reference. Note a *reference* in BoringSSL refers to an increment (and eventual
193decrement) of an object's reference count, not `T&` in C++. Thus, to "take a
194reference" means to increment the reference count and take ownership of
195decrementing it.
196
197As BoringSSL's APIs are primarily in C, ownership and lifetime obligations are
198not rigorously annotated in the type signatures or checked at compile-time.
199Instead, they are described in
200[API documentation](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
201This section describes some conventions.
202
203Unless otherwise documented, functions do not take ownership of pointer
204arguments. The pointer typically must remain valid for the duration of the
205function call. The function may internally copy information from the argument or
206take a reference, but the caller is free to release its copy or reference at any
207point after the call completes.
208
209A function may instead be documented to *take* or *transfer* ownership of a
210pointer. The caller must own the object before the function call and, after
211transfer, no longer owns it. As a corollary, the caller may no longer reference
212the object without a separate guarantee on the lifetime. The function may even
213release the object before returning. Callers that wish to independently retain a
214transfered object must therefore take a reference or make a copy before
215transferring. Callers should also take note of whether the function is
216documented to transfer pointers unconditionally or only on success. Unlike C++
217and Rust, functions in BoringSSL typically only transfer on success.
218
219Likewise, output pointers may be owning or non-owning. Unless otherwise
220documented, functions output non-owning pointers. The caller is not responsible
221for releasing the output pointer, but it must not use the pointer beyond its
222lifetime. The pointer may be released when the parent object is released or even
223sooner on state change in the parent object.
224
225If documented to output a *newly-allocated* object or a *reference* or *copy* of
226one, the caller is responsible for releasing the object when it is done.
227
228By convention, functions named `get0` return non-owning pointers. Functions
229named `new` or `get1` return owning pointers. Functions named `set0` take
230ownership of arguments. Functions named `set1` do not. They typically take a
231reference or make a copy internally. These names originally referred to the
232effect on a reference count, but the convention applies equally to
233non-reference-counted types.
234
235API documentation may also describe more complex obligations. For instance, an
236object may borrow a pointer for longer than the duration of a single function
237call, in which case the caller must ensure the lifetime extends accordingly.
238
239Memory errors are one of the most common and dangerous bugs in C and C++, so
240callers are encouraged to make use of tools such as
241[AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) and
242higher-level languages.
243
244
245## Thread safety
246
247BoringSSL is internally aware of the platform threading library and calls into
248it as needed. Consult the API documentation for the threading guarantees of
249particular objects. In general, stateless reference-counted objects like `RSA`
250or `EVP_PKEY` which represent keys may typically be used from multiple threads
251simultaneously, provided no thread mutates the key.
252