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