1,boringssl的gn build文件是自动生成
需要安装perl,go:
cd third_party/boringssl
python src/util/generate_build_files.py gn
Alternatively, use the roll_boringssl.py script.
生成了 build.gn , build.generated.gni
2,ssl的引用:
E:\dev\cef-chromium\chromium\src\: net/socket/ssl_client_socket_impl
#include "third_party/boringssl/src/include/openssl/bio.h" #include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/err.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/mem.h" #include "third_party/boringssl/src/include/openssl/ssl.h"
net 模块中:
build.gn
指定了依赖包
public_deps = [ ":net_nqe_proto", ":net_quic_proto", ":traffic_annotation", "//crypto", "//crypto:platform", "//third_party/boringssl", ]
DEPS
指定了头文件 include_rules = [ "+crypto", "+gin", "+jni", "+mojo/public", "+third_party/apple_apsl", "+third_party/boringssl/src/include", "+third_party/nss", "+third_party/protobuf/src/google/protobuf", "+third_party/zlib", "+v8", # Most of net should not depend on icu, and brotli to keep size down when # built as a library. "-base/i18n", "-third_party/brotli", "-third_party/icu", ]
3, 编译
gn gen out/Default (gn args out/Default) 生成了 build.ninja文件。类似makefile。
https://blog.csdn.net/ai2000ai/article/details/80894644
base.h 需要和 ossl_tpy.h做整合。 boring里面这两个是相同的。 EMBED_OPENSSL https://github.com/lijunjieone/boringssl
编译项目
# Building BoringSSL ## Build Prerequisites * [CMake](https://cmake.org/download/) 2.8.11 or later is required. * Perl 5.6.1 or later is required. On Windows, [Active State Perl](http://www.activestate.com/activeperl/) has been reported to work, as has MSYS Perl. [Strawberry Perl](http://strawberryperl.com/) also works but it adds GCC to `PATH`, which can confuse some build tools when identifying the compiler (removing `C:\Strawberry\c\bin` from `PATH` should resolve any problems). If Perl is not found by CMake, it may be configured explicitly by setting `PERL_EXECUTABLE`. * On Windows you currently must use [Ninja](https://ninja-build.org/) to build; on other platforms, it is not required, but recommended, because it makes builds faster. * If you need to build Ninja from source, then a recent version of [Python](https://www.python.org/downloads/) is required (Python 2.7.5 works). * On Windows only, [Yasm](http://yasm.tortall.net/) is required. If not found by CMake, it may be configured explicitly by setting `CMAKE_ASM_NASM_COMPILER`. * A C compiler is required. On Windows, MSVC 14 (Visual Studio 2015) or later with Platform SDK 8.1 or later are supported. Recent versions of GCC (4.8+) and Clang should work on non-Windows platforms, and maybe on Windows too. To build the tests, you also need a C++ compiler with C++11 support. * [Go](https://golang.org/dl/) is required. If not found by CMake, the go executable may be configured explicitly by setting `GO_EXECUTABLE`. * To build the x86 and x86\_64 assembly, your assembler must support AVX2 instructions and MOVBE. If using GNU binutils, you must have 2.22 or later ## Building Using Ninja (note the 'N' is capitalized in the cmake invocation): mkdir build cd build cmake -GNinja .. ninja Using Make (does not work on Windows): mkdir build cd build cmake .. make You usually don't need to run `cmake` again after changing `CMakeLists.txt` files because the build scripts will detect changes to them and rebuild themselves automatically. Note that the default build flags in the top-level `CMakeLists.txt` are for debugging—optimisation isn't enabled. Pass `-DCMAKE_BUILD_TYPE=Release` to `cmake` to configure a release build. If you want to cross-compile then there is an example toolchain file for 32-bit Intel in `util/`. Wipe out the build directory, recreate it and run `cmake` like this: cmake -DCMAKE_TOOLCHAIN_FILE=../util/32-bit-toolchain.cmake -GNinja .. If you want to build as a shared library, pass `-DBUILD_SHARED_LIBS=1`. On Windows, where functions need to be tagged with `dllimport` when coming from a shared library, define `BORINGSSL_SHARED_LIBRARY` in any code which `#include`s the BoringSSL headers. In order to serve environments where code-size is important as well as those where performance is the overriding concern, `OPENSSL_SMALL` can be defined to remove some code that is especially large. See [CMake's documentation](https://cmake.org/cmake/help/v3.4/manual/cmake-variables.7.html) for other variables which may be used to configure the build.
整合项目
# Incorporating BoringSSL into a project **Note**: if your target project is not a Google project then first read the [main README](/README.md) about the purpose of BoringSSL. ## Bazel If you are using [Bazel](https://bazel.build) then you can incorporate BoringSSL as an external repository by using a commit from the `master-with-bazel` branch. That branch is maintained by a bot from `master` and includes the needed generated files and a top-level BUILD file. For example: git_repository( name = "boringssl", commit = "_some commit_", remote = "https://boringssl.googlesource.com/boringssl", ) You would still need to keep the referenced commit up to date if a specific commit is referred to. ## Directory layout Typically projects create a `third_party/boringssl` directory to put BoringSSL-specific files into. The source code of BoringSSL itself goes into `third_party/boringssl/src`, either by copying or as a [submodule](https://git-scm.com/docs/git-submodule). It's generally a mistake to put BoringSSL's source code into `third_party/boringssl` directly because pre-built files and custom build files need to go somewhere and merging these with the BoringSSL source code makes updating things more complex. ## Build support BoringSSL is designed to work with many different build systems. Currently, different projects use [GYP](https://gyp.gsrc.io/), [GN](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/quick_start.md), [Bazel](https://bazel.build/) and [Make](https://www.gnu.org/software/make/) to build BoringSSL, without too much pain. The development build system is CMake and the CMake build knows how to automatically generate the intermediate files that BoringSSL needs. However, outside of the CMake environment, these intermediates are generated once and checked into the incorporating project's source repository. This avoids incorporating projects needing to support Perl and Go in their build systems. The script [`util/generate_build_files.py`](/util/generate_build_files.py) expects to be run from the `third_party/boringssl` directory and to find the BoringSSL source code in `src/`. You should pass it a single argument: the name of the build system that you're using. If you don't use any of the supported build systems then you should augment `generate_build_files.py` with support for it. The script will pregenerate the intermediate files (see [BUILDING.md](/BUILDING.md) for details about which tools will need to be installed) and output helper files for that build system. It doesn't generate a complete build script, just file and test lists, which change often. For example, see the [file](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated.gni) and [test](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated_tests.gni) lists generated for GN in Chromium. Generally one checks in these generated files alongside the hand-written build files. Periodically an engineer updates the BoringSSL revision, regenerates these files and checks in the updated result. As an example, see how this is done [in Chromium](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/). ## Defines BoringSSL does not present a lot of configurability in order to reduce the number of configurations that need to be tested. But there are a couple of \#defines that you may wish to set: `OPENSSL_NO_ASM` prevents the use of assembly code (although it's up to you to ensure that the build system doesn't link it in if you wish to reduce binary size). This will have a significant performance impact but can be useful if you wish to use tools like [AddressSanitizer](http://clang.llvm.org/docs/AddressSanitizer.html) that interact poorly with assembly code. `OPENSSL_SMALL` removes some code that is especially large at some performance cost. ## Symbols You cannot link multiple versions of BoringSSL or OpenSSL into a single binary without dealing with symbol conflicts. If you are statically linking multiple versions together, there's not a lot that can be done because C doesn't have a module system. If you are using multiple versions in a single binary, in different shared objects, ensure you build BoringSSL with `-fvisibility=hidden` and do not export any of BoringSSL's symbols. This will prevent any collisions with other verisons that may be included in other shared objects. Note that this requires that all callers of BoringSSL APIs live in the same shared object as BoringSSL. If you require that BoringSSL APIs be used across shared object boundaries, continue to build with `-fvisibility=hidden` but define `BORINGSSL_SHARED_LIBRARY` in both BoringSSL and consumers. BoringSSL's own source files (but *not* consumers' source files) must also build with `BORINGSSL_IMPLEMENTATION` defined. This will export BoringSSL's public symbols in the resulting shared object while hiding private symbols. However note that, as with a static link, this precludes dynamically linking with another version of BoringSSL or OpenSSL.
1.gclient简介
gclient是谷歌开发的一套跨平台git仓库管理工具,用来将多个git仓库组成一个solution进行管理。总体上,其核心功能是根据一个Solution的DEPS文件所定义的规则将多个git仓库拉取到指定目录。例如,chromium就是由80多个独立仓库组成。
2.相关概念
- hooks: 当gclient拉完代码后执行的额外脚本;
- solution: 一个包含DEPS文件的仓库,可以认为是一个完整的项目;
- DEPS: 一个特殊的文件,规定了项目依赖关系;
- .gclient:一个特殊文件,规定了要拉取的solution,可由
gclient config
命令创建出来; - include_rules:指定当前目录下哪些目录/文件可以被其他代码include包含,哪些不可以被include。
帮助命令:
gclient --help
3.常用命令
3.1 gclient config
该命令会生成.gclient
文件,用于初始化要拉取的solution,其内容记录了solution仓库的地址以及要保存的位置。
我们在拉取chromium代码时第一步其实也是生成了.gclient
文件,内容如下:
solutions = [
{
"url": "https://chromium.googlesource.com/chromium/src.git", # Solution仓库地址
"managed": False,
"name": "src", # 拉取代码后存放的位置 "custom_deps": {}, # 自定义依赖的仓库地址 "custom_vars": {}, }, ]
以下是可以配置的字段:
- name : checkout出源码的名字
- url : 源码所在的目录,gclient希望checkout出的源码中包括一个DEPS的文件,这个文件包含了必须checkout到工作目录的源码的信息;
- deps_file 这是一个文件名(不包括路径),指在工程目录中包含依赖列表的文件,该项为可选,默认值为"DEPS"
- custom_deps 这是一个可选的字典对象,会覆盖工程的"DEPS"文件定义的条目。一般它用作本地目录中,那些不用checkout的代码;
- target_os : 这个可选的条目可以指出特殊的平台,根据平台来checkout出不同代码
3.2 gclient sync
该命令用于同步solution的各个仓库,它有一些参数:
-f
、--force
:强制更新未更改的模块;--with_branch_heads
: 除了clone默认refspecs外,还会clone "branch_heads" refspecs;--with_tags
: 除了默认的refspec之外,还可以clone git tags;--no-history
: 不拉取git提交历史信息;--revision
: 将代码切换到 version 版本 ;--nohooks
:拉取代码之后不执行hooks。
拉取代码主要是根据DEPS
文件来进行,它里面的内容包括:
deps
: 要获取的子依赖项:
deps = {
"src/outside" : "http://outside-server/trunk@1234",
}
vars
:定义字符串变量,一般用于替代公共的字符串,然后通过Var
来获取实际的值:
vars = {
'chromium_git': 'https://chromium.googlesource.com'
}
deps = {
'src/chrome/browser/resources/media_router/extension/src':
Var('chromium_git') + '/media_router.git' + '@' + '475baa8b2eb0a7a9dd1c96c9c7a6a8d9035cc8d7', 'src/buildtools': Var('chromium_git') + '/chromium/buildtools.git' + '@' + Var('buildtools_revision') }
Hooks
:DEPS包含可选的内容 hooks,也有重要的作用,它表示在sync, update或者recert后,执行一个hook操作,也即执行对应的脚本;
hooks = [
{
#config git log format
'name': 'git-log', 'pattern': '.', 'action': [ 'python', 'src/git-log/config_commit.py', ], }, ... ]
deps_os
:根据不同的平台定义不同的依赖工程,可选的包括:
DEPS_OS_CHOICES = {
"win32": "win``` "win": "win",
"cygwin": "win", "darwin": "mac", "mac": "mac", "unix": "unix", "linux": "unix", "linux2": "unix", "linux3": "unix", "android": "android", } deps_os = { "win": { "src/chrome/tools/test/reference_build/chrome_win": "/trunk/deps/reference_builds/chrome_win@197743", ..... }, "ios": { "src/third_party/GTM": (Var("googlecode_url") % "google-toolbox-for-mac") + "/trunk@" + Var("gtm_revision"), .... }, ... }
3.3 gclient runhooks
执行hooks。当你拉取代码时使用了--nohooks
参数时,就可以使用该命令来手动执行hooks。
3.4 gclient recurse
在每个仓库中都执行一条git 命令
3.5 gclient fetch
相当于每个仓库都执行了git fetch
操作。
3.6 gclient diff
相当于每个仓库都执行git diff
操作。
3.7 gclient status
相当于每个仓库都执行git status
操作。
更多指令可以使用gclient --help
查看。
4. 拉取代码流程
3. gn入门
Chromium是用gn和ninja进行编译的,即gn把.gn文件转换成.ninja文件,然后ninja根据.ninja文件将源码生成目标程序。gn和ninja的关系就与cmake和make的关系差不多。
1. 环境配置
在我们自己的项目中,也可以使用gn来进行编译。
在windows上总是会遇到各种各样的问题,还是直接下载二进制程序省心:
https://github.com/ninja-build/ninja/releases
https://chrome-infra-packages.appspot.com/p/gn/gn
然后设置环境变量,以便在命令行中直接使用。
2. 示例
这里写个hello_word来演示下gn的基本使用。
首先,写一个hello_word.cc源码文件:
#include
int main()
{
std::cout << "Hello world: gn build example" << std::endl;
return 0;
}
然后在同一目录下创建BUILD.gn文件:
executable("hello_world") {
sources = [
"hello_world.cc",
]
}
同时,gn还需要在项目根目录有一个.gn文件用于指定编译工具链。这里我们直接拷贝gn官方的例子的配置,完整工程:hello_world.zip
之后就可以直接执行编译:
gn gen out/Default
ninja -C out/Default
这样就会在out/Default目录生成可执行文件hello_world.exe。
这样一个简单的示例就完成了。
在自己的项目中使用gn,必须遵循以下要求:
- 在根目录创建.gn文件,该文件用于指定BUILDCONFIG.gn文件的位置;
- 在BUILDCONFIG.gn中指定编译时使用的编译工具链;
- 在独立的gn文件中定义编译使用的工具链;
- 在项目根目录下创建BUILD.gn文件,指定编译的目标。
3. gn命令
gn gen out/dir [--args="..."]:创建新的编译目录,会自动创建args.gn文件作为编译参数。
gn args --list out/dir:列出可选的编译参数。
gn ls out/dir:列出所有的target;
gn ls out/dir "//:hello_word*":列出匹配的target;
gn desc out/dir "//:hello_word":查看指定target的描述信息,包括src源码文件、依赖的lib、编译选项等;
gn refs out/dir 文件:查看依赖该文件的target;
gn refs out/dir //:hello_word:查看依赖该target的target
。。。
注意//代表从项目根目录开始。
4. BUILD.gn文件语法
gn语法很接近python,主要的官方文档是以下两篇:
https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/docs/language.md
https://gn.googlesource.com/gn/+/master/docs/reference.md
这里简单介绍下一些关键用法:
4.1 新增编译参数
declare_args() {
enable_test = true
}
这样就新增了一个enable_test的gn编译参数,默认值是true。在BUILD.gn文件中,你就可以根据这个编译参数的值进行一些特殊化配置:
if(enable_test)
{
...
}
4.2 新增宏
defines = [ "AWESOME_FEATURE", "LOG_LEVEL=3" ]
这些宏可以直接在C++或C代码中使用。
4.3 新增编译单元
target就是一个最小的编译单元,可以将它单独传递给ninja进行编译。
从google文档上看有以下几种target:
- action: Declare a target that runs a script a single time.(指定一段指定的脚本)
- action_foreach: Declare a target that runs a script over a set of files.(为一组输入文件分别执行一次脚本)
- bundle_data: [iOS/macOS] Declare a target without output. (声明一个无输出文件的target)
- copy: Declare a target that copies files. (声明一个只是拷贝文件的target)
- create_bundle: [iOS/macOS] Build an iOS or macOS bundle. (编译MACOS/IOS包)
- executable: Declare an executable target. (生成可执行程序)
- generated_file: Declare a generated_file target.
- group: Declare a named group of targets. (执行一组target编译)
- loadable_module: Declare a loadable module target. (创建运行时加载动态连接库,和deps方式有一些区别)
- rust_library: Declare a Rust library target.
- shared_library: Declare a shared library target. (生成动态链接库,.dll or .so)
- source_set: Declare a source set target. (生成静态库,比static_library要快)
- static_library: Declare a static library target. (生成静态链接库,.lib or .a)
- target: Declare an target with the given programmatic type.
因此,我们的hello示例其实也只是增加了一个executable target。
4.4 新增配置
使用config可以提供一个公共的配置对象,包括编译flag、include、defines等,可被其他target包含。
config("myconfig") {
include_dirs = [ "include/common" ]
defines = [ "ENABLE_DOOM_MELON" ]
}
executable("mything") {
configs = [ ":myconfig" ]
}
4.5 新增模板
模板,顾名思义,可以用来定义可重用的代码,比如添加新的target类型等。
通常可以将模板单独定义成一个.gni文件,然后其他文件就可以通过import来引入实现共享。这部分就比较复杂,具体例子可参阅官方文档。
4.6 新增依赖关系
平时我们在编译的时候都会很小心地处理各种动态库和静态库的链接引入,在gn中,我们需要使用deps来实现库的依赖关系:
if (enable_nacl) {
deps += [ "//components/nacl/loader:nacl_loader_unittests" ]
if (is_linux) {
# TODO(dpranke): Figure out what platforms should actually have this.
deps += [ "//components/nacl/loader:nacl_helper" ]
if (enable_nacl_nonsfi) {
deps += [
"//components/nacl/loader:helper_nonsfi",
"//components/nacl/loader:nacl_helper_nonsfi_unittests",
]
}
}
}
5.通用toolchain配置
gn编译的toolchain配置非常关键,决定了你编译的方式和产物的用途,chromium自带的toolchains也能实现跨平台,但是太过庞大,我们日常使用的话,可以使用:https://github.com/timniederhausen/gn-build
6.使用gn编译mini_chromium库
mini_chromium提供了一个mini版本的chromium base库,里面提供很多有用的工具:日志库、字符串处理、文件处理等,github地址:https://github.com/chromium/mini_chromium.git 。
默认它使用的是gyp编译,但是其实它已经写好了BUILD.gn文件,我们只需添加.gn文件指定编译工具链即可,修改后的仓库:https://github.com/243286065/mini_chromium.git。
最后是再windows上和ubuntu上测试通过。不过发现mini_chromium上的确实内容太少了,连timer和json库都没有。
Porting from OpenSSL to BoringSSL
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.
BoringSSL‘s OPENSSL_VERSION_NUMBER
matches the OpenSSL version it targets. Version checks for OpenSSL should ideally work as-is in BoringSSL. BoringSSL also defines upstream’s OPENSSL_NO_*
feature macros corresponding to removed features. If the preprocessor is needed, use these version checks or feature macros where possible, especially when patching third-party projects. Such patches are more generally useful to OpenSSL consumers and thus more appropriate to send upstream.
In some cases, BoringSSL-specific code may be necessary. Use the OPENSSL_IS_BORINGSSL
preprocessor macro in #ifdef
s. However, first contact the BoringSSL maintainers about the missing APIs. We will typically add compatibility functions for convenience. In particular, contact BoringSSL maintainers before working around missing OpenSSL 1.1.0 accessors. BoringSSL was originally derived from OpenSSL 1.0.2 but now targets OpenSSL 1.1.0. Some newer APIs may be missing but can be added on request. (Not all projects have been ported to OpenSSL 1.1.0, so BoringSSL also remains largely compatible with OpenSSL 1.0.2.)
The OPENSSL_IS_BORINGSSL
macro may also be used to distinguish OpenSSL from BoringSSL in configure scripts. Do not use the presence or absence of particular symbols to detect BoringSSL.
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.
Major API changes
Integer types
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 int
, long
, and 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.
Reference counts and opaque types
Some external consumers increment reference counts directly by calling CRYPTO_add
with the corresponding CRYPTO_LOCK_*
value. 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
.
BoringSSL also hides some structs which were previously exposed in OpenSSL 1.0.2, particularly in libssl. Use the relevant accessors instead.
Note that some of these APIs were added in OpenSSL 1.1.0, so projects which do not yet support 1.1.0 may need additional #ifdef
s. Projects supporting OpenSSL 1.1.0 should not require modification.
Error codes
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_REASON
and 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.
*_ctrl
functions
Some OpenSSL APIs are implemented with ioctl
-style functions such as SSL_ctrl
and 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.
For convenience, 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.
Switch any *_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. See the end of this document for a table of functions to use.
HMAC EVP_PKEY
s
EVP_PKEY_HMAC
is removed. Use the HMAC_*
functions in hmac.h
instead. This is compatible with OpenSSL.
DSA EVP_PKEY
s
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
The 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.
TLS renegotiation
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_renegotiate_mode
and set it to ssl_renegotiate_once
or ssl_renegotiate_freely
. Renegotiation is only supported as a client in 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. (Attempts by clients will result in a fatal alert so that ClientHello messages cannot be used to flood a server and escape higher-level limits.)
-
There is no support for renegotiation in DTLS.
-
There is no support for initiating renegotiation;
SSL_renegotiate
always fails andSSL_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. -
Renegotiation does not participate in session resumption. The client will not offer a session on renegotiation or resume any session established by a renegotiation handshake.
-
The server may not change its certificate in the renegotiation. This mitigates the triple handshake attack. Any new stapled OCSP response and SCT list will be ignored. As no authentication state may change, BoringSSL will not re-verify the certificate on a renegotiation. Callbacks such as
SSL_CTX_set_custom_verify
will only run on the initial handshake.
Lowercase hexadecimal
BoringSSL's BN_bn2hex
function uses lowercase hexadecimal digits instead of uppercase. Some code may require changes to avoid being sensitive to this difference.
Legacy ASN.1 functions
OpenSSL's ASN.1 stack uses d2i
functions for parsing. They have the form:
RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len);
In addition to returning the result, OpenSSL places it in *out
if out
is not NULL
. On input, if *out
is not NULL
, OpenSSL will usually (but not always) reuse that object rather than allocating a new one. In BoringSSL, these functions are compatibility wrappers over a newer ASN.1 stack. Even if *out
is not NULL
, these wrappers will always allocate a new object and free the previous one.
Ensure that callers do not rely on this object reuse behavior. It is recommended to avoid the out
parameter completely and always pass in NULL
. Note that less error-prone APIs are available for BoringSSL-specific code (see below).
Memory allocation
OpenSSL provides wrappers OPENSSL_malloc
and OPENSSL_free
over the standard malloc
and free
. Memory allocated by OpenSSL should be released with OPENSSL_free
, not the standard free
. However, by default, they are implemented directly using malloc
and free
, so code which mixes them up usually works.
In BoringSSL, these functions maintain additional book-keeping to zero memory on OPENSSL_free
, so any mixups must be fixed.
Optional BoringSSL-specific simplifications
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.
Return values
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.
Initialization
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 CRYPTO_library_init
. In BORINGSSL_NO_STATIC_INITIALIZER
builds, it must be called to query CPU capabilities before the rest of the library. In the default configuration, this is done with a static initializer and is also unnecessary.
Threading
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.
ASN.1
BoringSSL is in the process of deprecating OpenSSL's d2i
and i2d
in favor of new functions using the much less error-prone CBS
and CBB
types. BoringSSL-only code should use those functions where available.
Replacements for CTRL
values
When porting code which uses SSL_CTX_ctrl
or SSL_ctrl
, use the replacement functions below. If a function has both SSL_CTX
and SSL
variants, only the SSL_CTX
version is listed.
Note some values correspond to multiple functions depending on the larg
parameter.
CTRL value |
Replacement function(s) |
---|---|
DTLS_CTRL_GET_TIMEOUT |
DTLSv1_get_timeout |
DTLS_CTRL_HANDLE_TIMEOUT |
DTLSv1_handle_timeout |
SSL_CTRL_CHAIN |
SSL_CTX_set0_chain or SSL_CTX_set1_chain |
SSL_CTRL_CHAIN_CERT |
SSL_add0_chain_cert or SSL_add1_chain_cert |
SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS |
SSL_CTX_clear_extra_chain_certs |
SSL_CTRL_CLEAR_MODE |
SSL_CTX_clear_mode |
SSL_CTRL_CLEAR_OPTIONS |
SSL_CTX_clear_options |
SSL_CTRL_EXTRA_CHAIN_CERT |
SSL_CTX_add_extra_chain_cert |
SSL_CTRL_GET_CHAIN_CERTS |
SSL_CTX_get0_chain_certs |
SSL_CTRL_GET_CLIENT_CERT_TYPES |
SSL_get0_certificate_types |
SSL_CTRL_GET_EXTRA_CHAIN_CERTS |
SSL_CTX_get_extra_chain_certs or SSL_CTX_get_extra_chain_certs_only |
SSL_CTRL_GET_MAX_CERT_LIST |
SSL_CTX_get_max_cert_list |
SSL_CTRL_GET_NUM_RENEGOTIATIONS |
SSL_num_renegotiations |
SSL_CTRL_GET_READ_AHEAD |
SSL_CTX_get_read_ahead |
SSL_CTRL_GET_RI_SUPPORT |
SSL_get_secure_renegotiation_support |
SSL_CTRL_GET_SESSION_REUSED |
SSL_session_reused |
SSL_CTRL_GET_SESS_CACHE_MODE |
SSL_CTX_get_session_cache_mode |
SSL_CTRL_GET_SESS_CACHE_SIZE |
SSL_CTX_sess_get_cache_size |
SSL_CTRL_GET_TLSEXT_TICKET_KEYS |
SSL_CTX_get_tlsext_ticket_keys |
SSL_CTRL_GET_TOTAL_RENEGOTIATIONS |
SSL_total_renegotiations |
SSL_CTRL_MODE |
SSL_CTX_get_mode or SSL_CTX_set_mode |
SSL_CTRL_NEED_TMP_RSA |
SSL_CTX_need_tmp_RSA is equivalent, but do not use this function. (It is a no-op in BoringSSL.) |
SSL_CTRL_OPTIONS |
SSL_CTX_get_options or SSL_CTX_set_options |
SSL_CTRL_SESS_NUMBER |
SSL_CTX_sess_number |
SSL_CTRL_SET_CURVES |
SSL_CTX_set1_curves |
SSL_CTRL_SET_ECDH_AUTO |
SSL_CTX_set_ecdh_auto |
SSL_CTRL_SET_MAX_CERT_LIST |
SSL_CTX_set_max_cert_list |
SSL_CTRL_SET_MAX_SEND_FRAGMENT |
SSL_CTX_set_max_send_fragment |
SSL_CTRL_SET_MSG_CALLBACK |
SSL_set_msg_callback |
SSL_CTRL_SET_MSG_CALLBACK_ARG |
SSL_set_msg_callback_arg |
SSL_CTRL_SET_MTU |
SSL_set_mtu |
SSL_CTRL_SET_READ_AHEAD |
SSL_CTX_set_read_ahead |
SSL_CTRL_SET_SESS_CACHE_MODE |
SSL_CTX_set_session_cache_mode |
SSL_CTRL_SET_SESS_CACHE_SIZE |
SSL_CTX_sess_set_cache_size |
SSL_CTRL_SET_TLSEXT_HOSTNAME |
SSL_set_tlsext_host_name |
SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG |
SSL_CTX_set_tlsext_servername_arg |
SSL_CTRL_SET_TLSEXT_SERVERNAME_CB |
SSL_CTX_set_tlsext_servername_callback |
SSL_CTRL_SET_TLSEXT_TICKET_KEYS |
SSL_CTX_set_tlsext_ticket_keys |
SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB |
SSL_CTX_set_tlsext_ticket_key_cb |
SSL_CTRL_SET_TMP_DH |
SSL_CTX_set_tmp_dh |
SSL_CTRL_SET_TMP_DH_CB |
SSL_CTX_set_tmp_dh_callback |
SSL_CTRL_SET_TMP_ECDH |
SSL_CTX_set_tmp_ecdh |
SSL_CTRL_SET_TMP_ECDH_CB |
SSL_CTX_set_tmp_ecdh_callback |
SSL_CTRL_SET_TMP_RSA |
SSL_CTX_set_tmp_rsa is equivalent, but do not use this function. (It is a no-op in BoringSSL.) |
SSL_CTRL_SET_TMP_RSA_CB |
SSL_CTX_set_tmp_rsa_callback is equivalent, but do not use this function. (It is a no-op in BoringSSL.) |
Significant API additions
In some places, BoringSSL has added significant APIs. Use of these APIs goes beyound “porting” and means giving up on OpenSSL compatibility.
One example of this has already been mentioned: the CBS and CBB functions should be used whenever parsing or serialising data.
CRYPTO_BUFFER
With the standard OpenSSL APIs, when making many TLS connections, the certificate data for each connection is retained in memory in an expensive X509
structure. Additionally, common certificates often appear in the chains for multiple connections and are needlessly duplicated in memory.
A CRYPTO_BUFFER
is just an opaque byte string. A CRYPTO_BUFFER_POOL
is an intern table for these buffers, i.e. it ensures that only a single copy of any given byte string is kept for each pool.
The function TLS_with_buffers_method
returns an SSL_METHOD
that avoids creating X509
objects for certificates. Additionally, SSL_CTX_set0_buffer_pool
can be used to install a pool on an SSL_CTX
so that certificates can be deduplicated across connections and across SSL_CTX
s.
When using these functions, the application also needs to ensure that it doesn't call other functions that deal with X509
or X509_NAME
objects. For example, SSL_get_peer_certificate
or SSL_get_peer_cert_chain
. Doing so will trigger an assert in debug mode and will result in NULLs in release mode. Instead, call the buffer-based alternatives such as SSL_get0_peer_certificates
. (See ssl.h for functions taking or returning CRYPTO_BUFFER
.) The buffer-based alternative functions will work even when not using TLS_with_buffers_method
, thus application code can transition gradually.
In order to use buffers, the application code also needs to implement its own certificate verification using SSL_[CTX_]set_custom_verify
. Otherwise all connections will fail with a verification error. Auto-chaining is also disabled when using buffers.
Once those changes have been completed, the whole of the OpenSSL X.509 and ASN.1 code should be eliminated by the linker if BoringSSL is linked statically.
Asynchronous and opaque private keys
OpenSSL offers the ENGINE API for implementing opaque private keys (i.e. private keys where software only has oracle access because the secrets are held in special hardware or on another machine). While the ENGINE API has been mostly removed from BoringSSL, it is still possible to support opaque keys in this way. However, when using such keys with TLS and BoringSSL, you should strongly prefer using SSL_PRIVATE_KEY_METHOD
via SSL[_CTX]_set_private_key_method
. This allows a handshake to be suspended while the private operation is in progress. It also supports more forms of opaque key as it exposes higher-level information about the operation to be performed.
编译器只有三种:微软的msvc,GNU的gcc,苹果的clang+llvm
各平台有自己的make(微软的MS nmake、GNU的make),这个是依赖平台的,无法避开的最后编译。
cmake可以跨平台生成各平台的make。但随着源码规模大,编译速度需提升。产生ninja,gn。ninja相当于预编译,查找好复杂的依赖。
用gn的工作方式:
1,gn生成各个平台的工程(xcode工程、vs工程)。用ide编辑修改源码或者工程模块后,同步回gn中。
或者2,vscode+gn
gn gen 后生成了build.njia