BoringSSL is an OpenSSL derivative and is mostly source-compatible, for the subset of OpenSSL retained. Libraries ideally need little to no changes for BoringSSL support, provided they do not use removed APIs. In general, see if the library compiles and, on failure, consult the documentation in the header files and see if problematic features can be removed.
In some cases, BoringSSL-specific code may be necessary. In that case, the
OPENSSL_IS_BORINGSSL preprocessor macro may be used in
#ifdefs. This macro should also be used in lieu of the presence of any particular function to detect OpenSSL vs BoringSSL in configure scripts, etc., where those are necessary.
For convenience, BoringSSL defines upstream's
OPENSSL_NO_* feature macros corresponding to removed features. These may also be used to disable code which uses a removed feature.
Note: BoringSSL does not have a stable API or ABI. It must be updated with its consumers. It is not suitable for, say, a system library in a traditional Linux distribution. For instance, Chromium statically links the specific revision of BoringSSL it was built against. Likewise, Android's system-internal copy of BoringSSL is not exposed by the NDK and must not be used by third-party applications.
Some APIs have been converted to use
size_t for consistency and to avoid integer overflows at the API boundary. (Existing logic uses a mismash of
unsigned.) For the most part, implicit casts mean that existing code continues to compile. In some cases, this may require BoringSSL-specific code, particularly to avoid compiler warnings.
Most notably, the
STACK_OF(T) types have all been converted to use
size_t instead of
int for indices and lengths.
Some external consumers increment reference counts directly by calling
CRYPTO_add with the corresponding
These APIs no longer exist in BoringSSL. Instead, code which increments reference counts should call the corresponding
FOO_up_ref function, such as
EVP_PKEY_up_ref. Note that not all of these APIs are present in OpenSSL and may require
OpenSSL's errors are extremely specific, leaking internals of the library, including even a function code for the function which emitted the error! As some logic in BoringSSL has been rewritten, code which conditions on the error may break (grep for
ERR_GET_FUNC). This danger also exists when upgrading OpenSSL versions.
Where possible, avoid conditioning on the exact error reason. Otherwise, a BoringSSL
#ifdef may be necessary. Exactly how best to resolve this issue is still being determined. It's possible some new APIs will be added in the future.
Function codes have been completely removed. Remove code which conditions on these as it will break with the slightest change in the library, OpenSSL or BoringSSL.
Some OpenSSL APIs are implemented with
ioctl-style functions such as
EVP_PKEY_CTX_ctrl, combined with convenience macros, such as
# define SSL_CTX_set_mode(ctx,op) \ SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
In BoringSSL, these macros have been replaced with proper functions. The underlying
_ctrl functions have been removed.
SSL_CTRL_* values are retained as macros to
doesnt_exist so existing code which uses them (or the wrapper macros) in
#ifdef expressions will continue to function. However, the macros themselves will not work.
*_ctrl callers to the macro/function versions. This works in both OpenSSL and BoringSSL. Note that BoringSSL's function versions will be type-checked and may require more care with types.
EVP_PKEY_HMAC is removed. Use the
HMAC_* functions in
hmac.h instead. This is compatible with OpenSSL.
EVP_PKEY_DSA is deprecated. It is currently still possible to parse DER into a DSA
EVP_PKEY, but signing or verifying with those objects will not work.
DES_cblock type has been switched from an array to a struct to avoid the pitfalls around array types in C. Where features which require DES cannot be disabled, BoringSSL-specific codepaths may be necessary.
OpenSSL enables TLS renegotiation by default and accepts renegotiation requests from the peer transparently. Renegotiation is an extremely problematic protocol feature, so BoringSSL rejects peer renegotiations by default.
To enable renegotiation, call
SSL_set_reject_peer_renegotiations and set it to off. Renegotiation is only supported as a client in SSL3/TLS and the HelloRequest must be received at a quiet point in the application protocol. This is sufficient to support the common use of requesting a new client certificate between an HTTP request and response in (unpipelined) HTTP/1.1.
Things which do not work:
There is no support for renegotiation as a server.
There is no support for renegotiation in DTLS.
There is no support for initiating renegotiation;
SSL_renegotiate always fails and
SSL_set_state does nothing.
Interleaving application data with the new handshake is forbidden.
If a HelloRequest is received while
SSL_write has unsent application data, the renegotiation is rejected.
BoringSSL makes some changes to OpenSSL which simplify the API but remain compatible with OpenSSL consumers. In general, consult the BoringSSL documentation for any functions in new BoringSSL-only code.
Most OpenSSL APIs return 1 on success and either 0 or -1 on failure. BoringSSL has narrowed most of these to 1 on success and 0 on failure. BoringSSL-specific code may take advantage of the less error-prone APIs and use
! to check for errors.
OpenSSL has a number of different initialization functions for setting up error strings and loading algorithms, etc. All of these functions still exist in BoringSSL for convenience, but they do nothing and are not necessary.
The one exception is
SSL_library_init which merely calls it). In
BORINGSSL_NO_STATIC_INITIALIZER builds, it must be called to query CPU capabitilies before the rest of the library. In the default configuration, this is done with a static initializer and is also unnecessary.
OpenSSL provides a number of APIs to configure threading callbacks and set up locks. Without initializing these, the library is not thread-safe. Configuring these does nothing in BoringSSL. Instead, BoringSSL calls pthreads and the corresponding Windows APIs internally and is always thread-safe where the API guarantees it.