MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

migrate to embedded boringssl

+1663 -31
+3 -4
.github/workflows/build-platform.yml
··· 70 70 fi 71 71 apt-get update 72 72 apt-get install -y git ca-certificates gnupg wget software-properties-common curl \ 73 - python3-pip ninja-build cmake pkg-config uuid-dev libssl-dev libsodium-dev jq 73 + python3-pip ninja-build cmake pkg-config uuid-dev libsodium-dev jq 74 74 curl -fsSL https://deb.nodesource.com/setup_22.x | bash - 75 75 apt-get install -y nodejs 76 76 pip3 install meson tomli ··· 81 81 if: startsWith(inputs.platform, 'linux-musl') 82 82 run: | 83 83 apk add --no-cache git clang lld llvm meson ninja cmake pkgconf curl npm nodejs \ 84 - musl-dev openssl-dev openssl-libs-static libsodium-dev libsodium-static \ 84 + musl-dev libsodium-dev libsodium-static \ 85 85 util-linux-dev util-linux-static linux-headers libunwind-dev libunwind-static \ 86 86 py3-tomli tar xz zstd jq bash 87 87 git config --global --add safe.directory "$GITHUB_WORKSPACE" ··· 93 93 for pkg in meson ninja llvm jq; do 94 94 brew list "$pkg" &>/dev/null || brew install "$pkg" 95 95 done 96 - brew list openssl@3 &>/dev/null || brew install openssl@3 97 96 98 97 # === WINDOWS SETUP === 99 98 - name: Disable Windows Defender real-time monitoring ··· 109 108 cache: true 110 109 install: >- 111 110 mingw-w64-clang-x86_64-toolchain mingw-w64-clang-x86_64-meson mingw-w64-clang-x86_64-ninja 112 - mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-openssl mingw-w64-clang-x86_64-libsodium 111 + mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-libsodium 113 112 mingw-w64-clang-x86_64-lld mingw-w64-clang-x86_64-nodejs git jq 114 113 115 114 - name: Configure git line endings
+23 -17
BUILDING.md
··· 29 29 - [Windows prerequisites](#windows-prerequisites) 30 30 - [Building Ant](#building-ant-2) 31 31 - [Meson build options](#meson-build-options) 32 - - [TLS library selection](#tls-library-selection) 33 32 34 33 ## Supported platforms 35 34 ··· 90 89 91 90 System libraries required: 92 91 93 - - **OpenSSL** 94 92 - **libsodium** 95 93 - **libuuid** (Linux/macOS) 96 - - **llhttp** (if not building from source via cmake) 97 94 98 95 The remaining dependencies are vendored as Meson subprojects under `vendor/` 99 96 and are fetched automatically: 100 97 98 + - aklomp-base64 0.5.2 99 + - argtable3 3.3.1 100 + - BoringSSL `297b11798a0ed6bc7736aa57328909a4afbbf67a` 101 + - crprintf `HEAD` 102 + - google-brotli 1.1.0 103 + - libffi 3.5.2 101 104 - libuv 1.52.0 105 + - llhttp 9.3.1 106 + - LMDB (OpenLDAP LMDB 0.9.33) 107 + - minicoro `HEAD` 108 + - MIR `HEAD` 109 + - nghttp2 1.68.0 110 + - PCRE2 10.47 111 + - tlsuv 0.40.13 112 + - uriparser 1.0.0 113 + - utf8proc 2.10.0 114 + - uthash 2.3.0 115 + - uuidv7-h `HEAD` 116 + - wasm-micro-runtime `92f40918bbfad35546a1512b10bd25eaa31add4d` 102 117 - yyjson 0.12.0 103 118 - zlib-ng 2.3.3 104 - - nghttp2 105 - - pcre2 106 - - libffi 107 - - lmdb (OpenLDAP LMDB 0.9.33) 108 - - minicoro 109 - - argtable3 110 - - uthash 111 - - uuidv7 112 - - tlsuv (cmake subproject) 113 119 114 120 ### Unix and macOS 115 121 ··· 121 127 122 128 ```bash 123 129 sudo apt-get install python3 python3-pip gcc-14 g++-14 ninja-build cmake \ 124 - pkg-config uuid-dev libssl-dev libsodium-dev nodejs npm 130 + pkg-config uuid-dev libsodium-dev nodejs npm 125 131 pip3 install meson 126 132 ``` 127 133 ··· 129 135 130 136 ```bash 131 137 sudo dnf install python3 gcc gcc-c++ ninja-build cmake pkgconf \ 132 - libuuid-devel openssl-devel libsodium-devel nodejs npm 138 + libuuid-devel libsodium-devel nodejs npm 133 139 pip3 install meson 134 140 ``` 135 141 136 142 - Alpine (musl): 137 143 ```sh 138 144 apk add clang lld llvm meson ninja cmake pkgconf nodejs npm \ 139 - musl-dev openssl-dev openssl-libs-static libsodium-dev libsodium-static \ 145 + musl-dev libsodium-dev libsodium-static \ 140 146 util-linux-dev util-linux-static linux-headers libunwind-dev libunwind-static 141 147 ``` 142 148 ··· 161 167 - Install remaining tools via [Homebrew](https://brew.sh): 162 168 163 169 ```bash 164 - brew install meson ninja llvm openssl@3 libsodium node 170 + brew install meson ninja llvm libsodium node 165 171 ``` 166 172 167 173 - Rust and Zig: ··· 372 378 ```bash 373 379 pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-meson \ 374 380 mingw-w64-x86_64-ninja mingw-w64-x86_64-cmake \ 375 - mingw-w64-x86_64-openssl mingw-w64-x86_64-libsodium \ 381 + mingw-w64-x86_64-libsodium \ 376 382 mingw-w64-x86_64-lld mingw-w64-x86_64-nodejs git 377 383 ``` 378 384 3. Install Rust via [rustup](https://rustup.rs/) (select the
+1 -1
flake.nix
··· 8 8 outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: 9 9 let pkgs = nixpkgs.legacyPackages.${system}; in { 10 10 devShells.default = pkgs.mkShell { 11 - packages = with pkgs; [ pkg-config libossp_uuid libsodium openssl ]; 11 + packages = with pkgs; [ pkg-config libossp_uuid libsodium ]; 12 12 13 13 shellHook = '' 14 14 export CC="ccache clang"
+7
meson.build
··· 95 95 link_args: link_args, 96 96 export_dynamic: true 97 97 ) 98 + 99 + executable( 100 + 'tlsuv-boringssl-smoke', 101 + files('tests/tlsuv_boringssl_smoke.c'), 102 + dependencies: [tlsuv_dep, libuv_dep, llhttp, zlib_dep] + (host_machine.system() == 'darwin' ? [security_dep] : []), 103 + build_by_default: false 104 + )
+22 -3
meson/deps/meson.build
··· 1 1 cc = meson.get_compiler('c') 2 + cmake = import('cmake') 2 3 3 - openssl_dep = dependency('openssl', required: true, static: is_static) 4 + boringssl_opts = cmake.subproject_options() 5 + boringssl_opts.add_cmake_defines({ 6 + 'BUILD_SHARED_LIBS': 'OFF', 7 + 'BUILD_TESTING': 'OFF', 8 + 'INSTALL_ENABLED': '0', 9 + }) 10 + 11 + boringssl_warning_flag = cc.get_argument_syntax() == 'msvc' ? '/W0' : '-w' 12 + boringssl_opts.append_compile_args('c', boringssl_warning_flag) 13 + boringssl_opts.append_compile_args('cpp', boringssl_warning_flag) 14 + boringssl_opts.set_override_option('warning_level', '0') 15 + 16 + boringssl_sub = cmake.subproject('boringssl', options: boringssl_opts) 17 + ssl_dep = boringssl_sub.dependency('ssl') 18 + crypto_dep = boringssl_sub.dependency('crypto') 19 + 20 + meson.override_dependency('ssl', ssl_dep) 21 + meson.override_dependency('crypto', crypto_dep) 22 + 4 23 libsodium_dep = dependency('libsodium', required: true, static: is_static) 5 24 6 25 if host_machine.system() == 'windows' ··· 77 96 cmake_prefix = get_option('deps_prefix_cmake') 78 97 79 98 tlsuv_sub = subproject('tlsuv', default_options: [ 80 - 'tls_backend=openssl', 99 + 'tls_backend=boringssl', 81 100 'deps_prefix_cmake=' + cmake_prefix, 82 101 'warning_level=0', 83 102 ]) ··· 201 220 llhttp, pcre2_dep, libuv_dep, base64_dep, 202 221 argtable3_dep, tlsuv_dep, libsodium_dep, 203 222 yyjson_dep, minicoro_dep, uuidv7_dep, 204 - uriparser_dep, utf8proc_dep, openssl_dep, 223 + uriparser_dep, utf8proc_dep, ssl_dep, crypto_dep, 205 224 zlib_dep, brotli_common_dep, brotli_dec_dep, 206 225 brotli_enc_dep, uthash_dep, lmdb_dep, wamr_dep, 207 226 ] + win_deps
+1 -1
src/core/features.ts
··· 1 1 process.features = { 2 2 uv: true, 3 - tls: 'openssl', 3 + tls: 'BoringSSL', 4 4 typescript: 'transform' 5 5 }; 6 6
+207
tests/tlsuv_boringssl_smoke.c
··· 1 + #include <stdio.h> 2 + #include <stdlib.h> 3 + #include <string.h> 4 + 5 + #include <tlsuv/http.h> 6 + #include <tlsuv/tls_engine.h> 7 + #include <tlsuv/tlsuv.h> 8 + #include <uv.h> 9 + 10 + typedef struct smoke_http_capture_s { 11 + int status; 12 + int finished; 13 + int eof_seen; 14 + char *body; 15 + size_t body_len; 16 + size_t body_cap; 17 + } smoke_http_capture_t; 18 + 19 + static void smoke_fail(const char *message) { 20 + fprintf(stderr, "FAIL: %s\n", message); 21 + exit(1); 22 + } 23 + 24 + static void smoke_check(int ok, const char *message) { 25 + if (!ok) smoke_fail(message); 26 + printf("ok: %s\n", message); 27 + } 28 + 29 + static void smoke_check_status(int actual, int expected, const char *body) { 30 + if (actual == expected) { 31 + printf("ok: HTTPS request returned %d\n", expected); 32 + return; 33 + } 34 + 35 + fprintf(stderr, "FAIL: HTTPS request returned %d (expected %d)\n", actual, expected); 36 + if (body && *body) { 37 + fprintf(stderr, "response body sample: %.200s\n", body); 38 + } 39 + exit(1); 40 + } 41 + 42 + static void smoke_http_close_cb(tlsuv_http_t *client) { 43 + (void)client; 44 + } 45 + 46 + static void smoke_http_body_cb(tlsuv_http_req_t *req, char *chunk, ssize_t len) { 47 + smoke_http_capture_t *cap = (smoke_http_capture_t *)req->data; 48 + 49 + if (len > 0) { 50 + size_t needed = cap->body_len + (size_t)len + 1; 51 + if (needed > cap->body_cap) { 52 + size_t next_cap = cap->body_cap ? cap->body_cap * 2 : 256; 53 + while (next_cap < needed) next_cap *= 2; 54 + char *next = (char *)realloc(cap->body, next_cap); 55 + if (!next) smoke_fail("out of memory growing HTTP body buffer"); 56 + cap->body = next; 57 + cap->body_cap = next_cap; 58 + } 59 + 60 + memcpy(cap->body + cap->body_len, chunk, (size_t)len); 61 + cap->body_len += (size_t)len; 62 + cap->body[cap->body_len] = '\0'; 63 + return; 64 + } 65 + 66 + if (len == UV_EOF) { 67 + cap->eof_seen = 1; 68 + cap->finished = 1; 69 + tlsuv_http_close(req->client, smoke_http_close_cb); 70 + } 71 + } 72 + 73 + static void smoke_http_resp_cb(tlsuv_http_resp_t *resp, void *ctx) { 74 + smoke_http_capture_t *cap = (smoke_http_capture_t *)ctx; 75 + cap->status = resp->code; 76 + resp->req->data = cap; 77 + resp->body_cb = smoke_http_body_cb; 78 + 79 + if (resp->code < 0) { 80 + cap->finished = 1; 81 + tlsuv_http_close(resp->req->client, smoke_http_close_cb); 82 + } 83 + } 84 + 85 + static void smoke_usage(const char *argv0) { 86 + fprintf(stderr, "usage: %s [--url https://localhost:8443] [--ca path] [--cert path] [--key path]\n", argv0); 87 + } 88 + 89 + int main(int argc, char **argv) { 90 + const char *ca_path = "vendor/tlsuv/tests/certs/ca.pem"; 91 + const char *cert_path = "vendor/tlsuv/tests/certs/server.crt"; 92 + const char *key_path = "vendor/tlsuv/tests/certs/server.key"; 93 + const char *url = NULL; 94 + 95 + for (int i = 1; i < argc; i++) { 96 + if (strcmp(argv[i], "--url") == 0 && i + 1 < argc) { 97 + url = argv[++i]; 98 + } else if (strcmp(argv[i], "--ca") == 0 && i + 1 < argc) { 99 + ca_path = argv[++i]; 100 + } else if (strcmp(argv[i], "--cert") == 0 && i + 1 < argc) { 101 + cert_path = argv[++i]; 102 + } else if (strcmp(argv[i], "--key") == 0 && i + 1 < argc) { 103 + key_path = argv[++i]; 104 + } else if (strcmp(argv[i], "--help") == 0) { 105 + smoke_usage(argv[0]); 106 + return 0; 107 + } else { 108 + smoke_usage(argv[0]); 109 + return 1; 110 + } 111 + } 112 + 113 + tls_context *base = default_tls_context(NULL, 0); 114 + smoke_check(base != NULL, "created default TLS context"); 115 + 116 + const char *version = base->version ? base->version() : NULL; 117 + smoke_check(version != NULL && strstr(version, "BoringSSL") != NULL, "tlsuv reports BoringSSL"); 118 + printf("tls version: %s\n", version); 119 + 120 + smoke_check(base->generate_key != NULL, "generate_key is available"); 121 + smoke_check(base->load_key != NULL, "load_key is available"); 122 + smoke_check(base->load_cert != NULL, "load_cert is available"); 123 + smoke_check(base->set_own_cert != NULL, "set_own_cert is available"); 124 + smoke_check(base->generate_csr_to_pem != NULL, "generate_csr_to_pem is available"); 125 + 126 + tlsuv_private_key_t generated = NULL; 127 + smoke_check(base->generate_key(&generated) == 0 && generated != NULL, "generated private key"); 128 + 129 + char *generated_pem = NULL; 130 + size_t generated_pem_len = 0; 131 + smoke_check(generated->to_pem(generated, &generated_pem, &generated_pem_len) == 0, "generated key exports to PEM"); 132 + smoke_check(generated_pem != NULL && generated_pem_len > 0, "generated key PEM is non-empty"); 133 + 134 + tlsuv_private_key_t roundtrip = NULL; 135 + smoke_check(base->load_key(&roundtrip, generated_pem, generated_pem_len) == 0 && roundtrip != NULL, "generated key PEM reloads"); 136 + 137 + char *csr_pem = NULL; 138 + size_t csr_pem_len = 0; 139 + smoke_check( 140 + base->generate_csr_to_pem( 141 + generated, &csr_pem, &csr_pem_len, 142 + "CN", "boringssl-smoke", 143 + "O", "ant", 144 + NULL 145 + ) == 0, 146 + "generated key can produce CSR" 147 + ); 148 + smoke_check(csr_pem != NULL && csr_pem_len > 0, "CSR PEM is non-empty"); 149 + 150 + tlsuv_private_key_t file_key = NULL; 151 + tlsuv_certificate_t file_cert = NULL; 152 + smoke_check(base->load_key(&file_key, key_path, strlen(key_path)) == 0 && file_key != NULL, "fixture private key loads"); 153 + smoke_check(base->load_cert(&file_cert, cert_path, strlen(cert_path)) == 0 && file_cert != NULL, "fixture certificate loads"); 154 + smoke_check(base->set_own_cert(base, file_key, file_cert) == 0, "fixture key/cert install on context"); 155 + 156 + struct tm expiration = {0}; 157 + smoke_check(file_cert->get_expiration != NULL, "certificate expiration accessor is available"); 158 + smoke_check(file_cert->get_expiration(file_cert, &expiration) == 0, "certificate expiration decodes"); 159 + 160 + if (url != NULL) { 161 + uv_loop_t *loop = uv_loop_new(); 162 + smoke_check(loop != NULL, "created libuv loop"); 163 + 164 + tls_context *http_tls = default_tls_context(ca_path, strlen(ca_path)); 165 + smoke_check(http_tls != NULL, "created CA-backed TLS context"); 166 + 167 + tlsuv_http_t client; 168 + memset(&client, 0, sizeof(client)); 169 + smoke_http_capture_t cap; 170 + memset(&cap, 0, sizeof(cap)); 171 + 172 + smoke_check(tlsuv_http_init(loop, &client, url) == 0, "initialized tlsuv HTTP client"); 173 + tlsuv_http_set_ssl(&client, http_tls); 174 + 175 + tlsuv_http_req_t *req = tlsuv_http_req(&client, "GET", "/get", smoke_http_resp_cb, &cap); 176 + smoke_check(req != NULL, "created HTTPS request"); 177 + tlsuv_http_req_end(req); 178 + 179 + uv_run(loop, UV_RUN_DEFAULT); 180 + 181 + smoke_check(cap.finished, "HTTPS request finished"); 182 + smoke_check_status(cap.status, 200, cap.body); 183 + smoke_check(cap.eof_seen, "HTTPS body reached EOF"); 184 + smoke_check(cap.body != NULL && cap.body_len > 0, "HTTPS body is non-empty"); 185 + printf("https body sample: %.80s\n", cap.body); 186 + 187 + http_tls->free_ctx(http_tls); 188 + if (uv_loop_close(loop) != 0) smoke_fail("failed to close libuv loop"); 189 + free(loop); 190 + free(cap.body); 191 + } else { 192 + printf("skipped live HTTPS probe; rerun with --url https://localhost:8443 to exercise a real handshake\n"); 193 + printf("tip: start vendor/tlsuv/tests/test_server/test-server.go with the existing cert fixtures first\n"); 194 + } 195 + 196 + free(csr_pem); 197 + free(generated_pem); 198 + 199 + if (base && base->free_ctx) base->free_ctx(base); 200 + if (file_cert && file_cert->free) file_cert->free(file_cert); 201 + if (file_key && file_key->free) file_key->free(file_key); 202 + if (roundtrip && roundtrip->free) roundtrip->free(roundtrip); 203 + if (generated && generated->free) generated->free(generated); 204 + 205 + printf("BoringSSL smoke test passed\n"); 206 + return 0; 207 + }
+4
vendor/boringssl.wrap
··· 1 + [wrap-git] 2 + url = https://github.com/google/boringssl.git 3 + revision = 297b11798a0ed6bc7736aa57328909a4afbbf67a 4 + depth = 1
+13
vendor/packagefiles/patches/tlsuv-boringssl.patch
··· 1 + diff --git a/src/alloc.c b/src/alloc.c 2 + index 6a9adf7..2d3a5ab 100644 3 + --- a/src/alloc.c 4 + +++ b/src/alloc.c 5 + @@ -63,7 +63,7 @@ void tlsuv_set_allocator(uv_malloc_func malloc_f, 6 + ALLOC.free_f = free_f; 7 + 8 + uv_replace_allocator(malloc_f, realloc_f, calloc_f, free_f); 9 + -#if USE_OPENSSL 10 + +#if USE_OPENSSL && !defined(OPENSSL_IS_BORINGSSL) 11 + CRYPTO_set_mem_functions(crypto_malloc, crypto_realloc, crypto_free); 12 + #endif 13 +
+9 -4
vendor/packagefiles/tlsuv/meson.build
··· 47 47 tlsuv_sources += files('src/win32/win32_keychain.c') 48 48 endif 49 49 50 - tlsuv_sources += files('src/openssl/engine.c', 'src/openssl/keys.c') 50 + if tls_backend == 'boringssl' 51 + tlsuv_sources += files('src/boringssl/engine.c', 'src/boringssl/keys.c') 52 + else 53 + tlsuv_sources += files('src/openssl/engine.c', 'src/openssl/keys.c') 54 + endif 51 55 52 56 tlsuv_c_args = [ 53 57 '-DTLSUV_VERSION=v' + meson.project_version(), ··· 69 73 tlsuv_c_args += ['-D_POSIX_C_SOURCE=200112', '-D_GNU_SOURCE'] 70 74 endif 71 75 72 - tls_dep = dependency('openssl', required: true) 73 - tlsuv_c_args += ['-I' + tls_dep.get_variable(pkgconfig: 'includedir')] 76 + tls_ssl_dep = dependency('ssl', required: true) 77 + tls_crypto_dep = dependency('crypto', required: true) 74 78 75 79 win_deps = [] 76 80 if host_machine.system() == 'windows' ··· 91 95 'tlsuv', 92 96 tlsuv_sources, tlsuv_config_h, 93 97 c_args: tlsuv_c_args, 94 - dependencies: [libuv_dep, llhttp_dep, zlib_dep] + win_deps, 98 + dependencies: [libuv_dep, llhttp_dep, zlib_dep, tls_ssl_dep, tls_crypto_dep] + win_deps, 95 99 include_directories: [ 96 100 include_directories('include'), 97 101 include_directories('src'), ··· 103 107 104 108 tlsuv_dep = declare_dependency( 105 109 link_with: tlsuv_lib, 110 + dependencies: [tls_ssl_dep, tls_crypto_dep], 106 111 include_directories: [ 107 112 include_directories('include'), 108 113 include_directories('deps/uv_link_t/include'),
+1 -1
vendor/packagefiles/tlsuv/meson_options.txt
··· 1 - option('tls_backend', type: 'combo', choices: ['openssl'], value: 'openssl', description: 'TLS backend library') 1 + option('tls_backend', type: 'combo', choices: ['openssl', 'boringssl'], value: 'boringssl', description: 'TLS backend library') 2 2 option('deps_prefix_cmake', type: 'string', value: '', description: 'Prefix for cmake-built dependencies')
+954
vendor/packagefiles/tlsuv/src/boringssl/engine.c
··· 1 + #include <assert.h> 2 + #include <stdbool.h> 3 + #include <stdarg.h> 4 + #include <stdlib.h> 5 + #include <string.h> 6 + #include <sys/stat.h> 7 + 8 + #include "../alloc.h" 9 + #include "../keychain.h" 10 + #include "../um_debug.h" 11 + 12 + #include <openssl/crypto.h> 13 + #include <openssl/err.h> 14 + #include <openssl/ssl.h> 15 + #include <openssl/x509.h> 16 + 17 + #include "keys.h" 18 + 19 + #if _WIN32 20 + #include <windows.h> 21 + #ifndef PATH_MAX 22 + #define PATH_MAX MAX_PATH 23 + #endif 24 + #endif 25 + 26 + #if __APPLE__ 27 + #include <Security/Security.h> 28 + #endif 29 + 30 + struct boringssl_ctx { 31 + tls_context api; 32 + SSL_CTX *ctx; 33 + int (*cert_verify_f)(const struct tlsuv_certificate_s *cert, void *v_ctx); 34 + void *verify_ctx; 35 + unsigned char *alpn_protocols; 36 + }; 37 + 38 + struct boringssl_engine { 39 + struct tlsuv_engine_s api; 40 + SSL *ssl; 41 + char *alpn; 42 + BIO *bio; 43 + bool handshake_started; 44 + io_ctx io; 45 + io_read read_f; 46 + io_write write_f; 47 + unsigned long error; 48 + }; 49 + 50 + static int is_self_signed(X509 *cert); 51 + static const char *name_str(const X509_NAME *n); 52 + static void init_ssl_context(struct boringssl_ctx *c, const char *cabuf, size_t cabuf_len); 53 + static int tls_set_own_cert(tls_context *ctx, tlsuv_private_key_t key, tlsuv_certificate_t cert); 54 + static int set_ca_bundle(tls_context *tls, const char *ca, size_t ca_len); 55 + tlsuv_engine_t new_boringssl_engine(tls_context *ctx, const char *host); 56 + static int parse_pkcs7_certs(tlsuv_certificate_t *chain, const char *pkcs7, size_t pkcs7len); 57 + static int load_cert(tlsuv_certificate_t *cert, const char *buf, size_t buflen); 58 + static int generate_csr(tlsuv_private_key_t key, char **pem, size_t *pemlen, ...); 59 + static int tls_set_partial_vfy(tls_context *ctx, int allow); 60 + static void tls_set_cert_verify(tls_context *ctx, int (*verify_f)(const struct tlsuv_certificate_s *cert, void *v_ctx), void *v_ctx); 61 + 62 + static void set_io(tlsuv_engine_t self, io_ctx io, io_read rdf, io_write wrtf); 63 + static void set_io_fd(tlsuv_engine_t self, tlsuv_sock_t fd); 64 + static void set_protocols(tlsuv_engine_t self, const char **protocols, int len); 65 + static tls_handshake_state tls_hs_state(tlsuv_engine_t engine); 66 + static tls_handshake_state tls_continue_hs(tlsuv_engine_t self); 67 + static const char *tls_get_alpn(tlsuv_engine_t self); 68 + static int tls_write(tlsuv_engine_t self, const char *data, size_t data_len); 69 + static int tls_read(tlsuv_engine_t self, char *out, size_t *out_bytes, size_t maxout); 70 + static int tls_close(tlsuv_engine_t self); 71 + static int tls_reset(tlsuv_engine_t self); 72 + static void tls_free(tlsuv_engine_t self); 73 + static void tls_free_ctx(tls_context *ctx); 74 + static const char *tls_lib_version(); 75 + static const char *tls_eng_error(tlsuv_engine_t self); 76 + static void msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg); 77 + static void info_cb(const SSL *s, int where, int ret); 78 + static BIO_METHOD *BIO_s_engine(void); 79 + #if _WIN32 80 + static X509_STORE *load_system_certs(); 81 + #endif 82 + 83 + static tls_context boringssl_context_api = { 84 + .version = tls_lib_version, 85 + .strerror = (const char *(*)(long))tls_error, 86 + .new_engine = new_boringssl_engine, 87 + .free_ctx = tls_free_ctx, 88 + .set_ca_bundle = set_ca_bundle, 89 + .set_own_cert = tls_set_own_cert, 90 + .allow_partial_chain = tls_set_partial_vfy, 91 + .set_cert_verify = tls_set_cert_verify, 92 + .parse_pkcs7_certs = parse_pkcs7_certs, 93 + .load_cert = load_cert, 94 + .generate_key = gen_key, 95 + .load_key = load_key, 96 + .generate_csr_to_pem = generate_csr, 97 + }; 98 + 99 + static struct tlsuv_engine_s boringssl_engine_api = { 100 + .set_io = set_io, 101 + .set_io_fd = set_io_fd, 102 + .set_protocols = set_protocols, 103 + .handshake_state = tls_hs_state, 104 + .handshake = tls_continue_hs, 105 + .get_alpn = tls_get_alpn, 106 + .close = tls_close, 107 + .write = tls_write, 108 + .read = tls_read, 109 + .reset = tls_reset, 110 + .free = tls_free, 111 + .strerror = tls_eng_error, 112 + }; 113 + 114 + int configure_boringssl() { 115 + return 0; 116 + } 117 + 118 + static const char *tls_lib_version() { 119 + return OpenSSL_version(OPENSSL_VERSION); 120 + } 121 + 122 + const char *tls_error(unsigned long code) { 123 + static char err_buf[32]; 124 + if (code == 0) return "no error"; 125 + 126 + const char *lib_err = ERR_lib_error_string(code); 127 + if (lib_err) return lib_err; 128 + 129 + snprintf(err_buf, sizeof(err_buf), "error[%lX]", code); 130 + return err_buf; 131 + } 132 + 133 + static const char *tls_eng_error(tlsuv_engine_t self) { 134 + struct boringssl_engine *e = (struct boringssl_engine *)self; 135 + const char *err = ERR_reason_error_string(e->error); 136 + return err; 137 + } 138 + 139 + tls_context *new_boringssl_ctx(const char *ca, size_t ca_len) { 140 + OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, NULL); 141 + 142 + struct boringssl_ctx *c = tlsuv__calloc(1, sizeof(struct boringssl_ctx)); 143 + c->api = boringssl_context_api; 144 + init_ssl_context(c, ca, ca_len); 145 + return &c->api; 146 + } 147 + 148 + static X509_STORE *load_certs(const char *buf, size_t buf_len) { 149 + X509_STORE *certs = X509_STORE_new(); 150 + X509 *c; 151 + struct stat fstat; 152 + 153 + if (stat(buf, &fstat) == 0) { 154 + if (fstat.st_mode & S_IFREG) { 155 + if (!X509_STORE_load_locations(certs, buf, NULL)) { 156 + UM_LOG(ERR, "failed to load certs from [%s]", buf); 157 + } 158 + } else if (fstat.st_mode & S_IFDIR) { 159 + X509_LOOKUP *lu = X509_STORE_add_lookup(certs, X509_LOOKUP_hash_dir()); 160 + if (lu == NULL || X509_LOOKUP_add_dir(lu, buf, X509_FILETYPE_PEM) != 1) { 161 + UM_LOG(ERR, "failed to load cert directory from [%s]", buf); 162 + } 163 + } else { 164 + UM_LOG(ERR, "cert bundle[%s] is not a regular file", buf); 165 + } 166 + } else { 167 + BIO *crt_bio = BIO_new_mem_buf(buf, (int)buf_len); 168 + while ((c = PEM_read_bio_X509(crt_bio, NULL, NULL, NULL)) != NULL) { 169 + int root = is_self_signed(c); 170 + UM_LOG(VERB, "%s root[%s]", name_str(X509_get_subject_name(c)), root ? "true" : "false"); 171 + X509_STORE_add_cert(certs, c); 172 + X509_free(c); 173 + } 174 + BIO_free(crt_bio); 175 + } 176 + 177 + return certs; 178 + } 179 + 180 + static int load_cert(tlsuv_certificate_t *cert, const char *buf, size_t buflen) { 181 + X509_STORE *store = load_certs(buf, buflen); 182 + STACK_OF(X509_OBJECT) *certs = X509_STORE_get0_objects(store); 183 + int count = sk_X509_OBJECT_num(certs); 184 + if (count == 0) { 185 + X509_STORE_free(store); 186 + return -1; 187 + } 188 + 189 + struct cert_s *crt = tlsuv__calloc(1, sizeof(*crt)); 190 + cert_init(crt); 191 + crt->cert = store; 192 + *cert = (tlsuv_certificate_t)crt; 193 + return 0; 194 + } 195 + 196 + static int is_self_signed(X509 *cert) { 197 + X509_NAME *subj = X509_get_subject_name(cert); 198 + X509_NAME *issuer = X509_get_issuer_name(cert); 199 + if (X509_NAME_cmp(subj, issuer) != 0) { 200 + return 0; 201 + } 202 + 203 + EVP_PKEY *pub = X509_get_pubkey(cert); 204 + if (pub == NULL) { 205 + return 0; 206 + } 207 + int ok = X509_verify(cert, pub); 208 + EVP_PKEY_free(pub); 209 + return ok == 1; 210 + } 211 + 212 + static const char *name_str(const X509_NAME *n) { 213 + static char buf[1024]; 214 + BIO *b = BIO_new(BIO_s_mem()); 215 + X509_NAME_print(b, n, 0); 216 + BIO_read(b, buf, sizeof(buf)); 217 + BIO_free(b); 218 + return buf; 219 + } 220 + 221 + #if __APPLE__ 222 + static int apple_ca_verify(int pre_verify, X509_STORE_CTX *st) { 223 + (void)pre_verify; 224 + CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 10, &kCFTypeArrayCallBacks); 225 + 226 + STACK_OF(X509) *chain = X509_STORE_CTX_get1_chain(st); 227 + for (int i = 0; i < sk_X509_num(chain); i++) { 228 + X509 *x = sk_X509_value(chain, i); 229 + uint8_t *der = NULL; 230 + int der_len = i2d_X509(x, &der); 231 + CFDataRef d = CFDataCreate(kCFAllocatorDefault, der, der_len); 232 + OPENSSL_free(der); 233 + 234 + SecCertificateRef c = SecCertificateCreateWithData(kCFAllocatorDefault, d); 235 + CFArrayAppendValue(certs, c); 236 + CFRelease(d); 237 + CFRelease(c); 238 + } 239 + sk_X509_pop_free(chain, X509_free); 240 + 241 + SecTrustRef trust; 242 + SecPolicyRef policy = SecPolicyCreateBasicX509(); 243 + CFErrorRef err = NULL; 244 + bool result = SecTrustCreateWithCertificates(certs, policy, &trust) == errSecSuccess && 245 + SecTrustEvaluateWithError(trust, &err); 246 + CFRelease(trust); 247 + CFRelease(policy); 248 + CFRelease(certs); 249 + return result; 250 + } 251 + #endif 252 + 253 + static int set_ca_bundle(tls_context *tls, const char *ca, size_t ca_len) { 254 + struct boringssl_ctx *c = (struct boringssl_ctx *)tls; 255 + SSL_CTX *ctx = c->ctx; 256 + 257 + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 258 + if (ca != NULL) { 259 + X509_STORE *store = load_certs(ca, ca_len); 260 + SSL_CTX_set0_verify_cert_store(ctx, store); 261 + } else { 262 + #if _WIN32 263 + if (!SSL_CTX_load_verify_store(ctx, "org.openssl.winstore:")) { 264 + X509_STORE *sys_ca = load_system_certs(); 265 + SSL_CTX_set0_verify_cert_store(ctx, sys_ca); 266 + } 267 + #elif __APPLE__ 268 + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, apple_ca_verify); 269 + #elif defined(ANDROID) || defined(__ANDROID__) 270 + X509_STORE *ca_store = SSL_CTX_get_cert_store(ctx); 271 + X509_LOOKUP *lu = X509_STORE_add_lookup(ca_store, X509_LOOKUP_hash_dir()); 272 + if (lu != NULL) { 273 + X509_LOOKUP_add_dir(lu, "/etc/security/cacerts", X509_FILETYPE_PEM); 274 + } 275 + #else 276 + SSL_CTX_set_default_verify_paths(ctx); 277 + #endif 278 + } 279 + 280 + return 0; 281 + } 282 + 283 + static void init_ssl_context(struct boringssl_ctx *c, const char *cabuf, size_t cabuf_len) { 284 + const SSL_METHOD *method = TLS_client_method(); 285 + SSL_CTX *ctx = SSL_CTX_new(method); 286 + if (ctx == NULL) { 287 + ERR_print_errors_fp(stderr); 288 + UM_LOG(ERR, "FATAL: failed to create SSL_CTX: %s", tls_error(ERR_get_error())); 289 + abort(); 290 + } 291 + 292 + SSL_CTX_set_app_data(ctx, c); 293 + c->ctx = ctx; 294 + set_ca_bundle((tls_context *)c, cabuf, cabuf_len); 295 + SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); 296 + SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION); 297 + 298 + char *tls_debug = getenv("TLS_DEBUG"); 299 + if (tls_debug) { 300 + SSL_CTX_set_msg_callback(ctx, msg_cb); 301 + SSL_CTX_set_info_callback(ctx, info_cb); 302 + } 303 + } 304 + 305 + typedef struct string_int_pair_st { 306 + const char *name; 307 + int retval; 308 + } STRINT_PAIR; 309 + 310 + static const char *lookup(int val, const STRINT_PAIR *list, const char *def) { 311 + for (; list->name; ++list) { 312 + if (list->retval == val) return list->name; 313 + } 314 + return def; 315 + } 316 + 317 + static STRINT_PAIR handshakes[] = { 318 + {", HelloRequest", SSL3_MT_HELLO_REQUEST}, 319 + {", ClientHello", SSL3_MT_CLIENT_HELLO}, 320 + {", ServerHello", SSL3_MT_SERVER_HELLO}, 321 + {", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST}, 322 + {", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET}, 323 + {", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA}, 324 + {", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS}, 325 + {", Certificate", SSL3_MT_CERTIFICATE}, 326 + {", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE}, 327 + {", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST}, 328 + {", ServerHelloDone", SSL3_MT_SERVER_DONE}, 329 + {", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY}, 330 + {", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE}, 331 + {", Finished", SSL3_MT_FINISHED}, 332 + {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS}, 333 + {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA}, 334 + {", KeyUpdate", SSL3_MT_KEY_UPDATE}, 335 + #ifndef OPENSSL_NO_NEXTPROTONEG 336 + {", NextProto", SSL3_MT_NEXT_PROTO}, 337 + #endif 338 + {", MessageHash", SSL3_MT_MESSAGE_HASH}, 339 + {NULL} 340 + }; 341 + 342 + static STRINT_PAIR alert_types[] = { 343 + {" close_notify", 0}, 344 + {" end_of_early_data", 1}, 345 + {" unexpected_message", 10}, 346 + {" bad_record_mac", 20}, 347 + {" decryption_failed", 21}, 348 + {" record_overflow", 22}, 349 + {" decompression_failure", 30}, 350 + {" handshake_failure", 40}, 351 + {" bad_certificate", 42}, 352 + {" unsupported_certificate", 43}, 353 + {" certificate_revoked", 44}, 354 + {" certificate_expired", 45}, 355 + {" certificate_unknown", 46}, 356 + {" illegal_parameter", 47}, 357 + {" unknown_ca", 48}, 358 + {" access_denied", 49}, 359 + {" decode_error", 50}, 360 + {" decrypt_error", 51}, 361 + {" export_restriction", 60}, 362 + {" protocol_version", 70}, 363 + {" insufficient_security", 71}, 364 + {" internal_error", 80}, 365 + {" inappropriate_fallback", 86}, 366 + {" user_canceled", 90}, 367 + {" no_renegotiation", 100}, 368 + {" missing_extension", 109}, 369 + {" unsupported_extension", 110}, 370 + {" certificate_unobtainable", 111}, 371 + {" unrecognized_name", 112}, 372 + {" bad_certificate_status_response", 113}, 373 + {" bad_certificate_hash_value", 114}, 374 + {" unknown_psk_identity", 115}, 375 + {" certificate_required", 116}, 376 + {NULL} 377 + }; 378 + 379 + static STRINT_PAIR ssl_versions[] = { 380 + {"SSL 3.0", SSL3_VERSION}, 381 + {"TLS 1.0", TLS1_VERSION}, 382 + {"TLS 1.1", TLS1_1_VERSION}, 383 + {"TLS 1.2", TLS1_2_VERSION}, 384 + {"TLS 1.3", TLS1_3_VERSION}, 385 + {"DTLS 1.0", DTLS1_VERSION}, 386 + {NULL} 387 + }; 388 + 389 + static void msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg) { 390 + (void)ssl; 391 + (void)arg; 392 + const char *str_write_p = write_p ? ">>>" : "<<<"; 393 + const char *str_content_type = "", *str_details1 = "", *str_details2 = ""; 394 + const char *str_version = lookup(version, ssl_versions, "???"); 395 + const unsigned char *bp = buf; 396 + 397 + if (version == SSL3_VERSION || version == TLS1_VERSION || version == TLS1_1_VERSION || 398 + version == TLS1_2_VERSION || version == TLS1_3_VERSION || 399 + version == DTLS1_VERSION) { 400 + switch (content_type) { 401 + case 20: str_content_type = ", ChangeCipherSpec"; break; 402 + case 21: 403 + str_content_type = ", Alert"; 404 + str_details1 = ", ???"; 405 + if (len == 2) { 406 + switch (bp[0]) { 407 + case 1: str_details1 = ", warning"; break; 408 + case 2: str_details1 = ", fatal"; break; 409 + } 410 + str_details2 = lookup((int)bp[1], alert_types, " ???"); 411 + } 412 + break; 413 + case 22: 414 + str_content_type = ", Handshake"; 415 + str_details1 = "???"; 416 + if (len > 0) str_details1 = lookup((int)bp[0], handshakes, "???"); 417 + break; 418 + case 23: str_content_type = ", ApplicationData"; break; 419 + } 420 + } else if (version == 0 && content_type == SSL3_RT_HEADER) { 421 + str_version = ""; 422 + str_content_type = "TLS Header"; 423 + } 424 + 425 + UM_LOG(TRACE, "%s %s%s [length %04lx]%s%s", str_write_p, str_version, str_content_type, (unsigned long)len, str_details1, str_details2); 426 + } 427 + 428 + void info_cb(const SSL *s, int where, int ret) { 429 + const char *str; 430 + int w = where & ~SSL_ST_MASK; 431 + 432 + if (w & SSL_ST_CONNECT) str = "SSL_connect"; 433 + else if (w & SSL_ST_ACCEPT) str = "SSL_accept"; 434 + else str = "undefined"; 435 + 436 + if (where & SSL_CB_LOOP) { 437 + UM_LOG(TRACE, "%s:%s", str, SSL_state_string_long(s)); 438 + } else if (where & SSL_CB_ALERT) { 439 + str = (where & SSL_CB_READ) ? "read" : "write"; 440 + UM_LOG(VERB, "SSL3 alert %s:%s:%s", str, SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); 441 + } else if (where & SSL_CB_EXIT) { 442 + if (ret == 0) UM_LOG(VERB, "%s:failed in %s", str, SSL_state_string_long(s)); 443 + else if (ret < 0) UM_LOG(VERB, "%s:error in %s", str, SSL_state_string_long(s)); 444 + } 445 + } 446 + 447 + tlsuv_engine_t new_boringssl_engine(tls_context *ctx, const char *host) { 448 + struct boringssl_ctx *context = (struct boringssl_ctx *)ctx; 449 + struct boringssl_engine *engine = tlsuv__calloc(1, sizeof(struct boringssl_engine)); 450 + engine->api = boringssl_engine_api; 451 + engine->ssl = SSL_new(context->ctx); 452 + 453 + SSL_set_tlsext_host_name(engine->ssl, host); 454 + SSL_set1_host(engine->ssl, host); 455 + SSL_set_connect_state(engine->ssl); 456 + SSL_set_app_data(engine->ssl, engine); 457 + 458 + return &engine->api; 459 + } 460 + 461 + static void set_io(tlsuv_engine_t self, io_ctx io, io_read rdf, io_write wrtf) { 462 + struct boringssl_engine *e = (struct boringssl_engine *)self; 463 + assert(e->bio == NULL); 464 + 465 + #ifdef SSL_OP_IGNORE_UNEXPECTED_EOF 466 + SSL_set_options(e->ssl, SSL_OP_IGNORE_UNEXPECTED_EOF); 467 + #endif 468 + e->bio = BIO_new(BIO_s_engine()); 469 + BIO_set_data(e->bio, e); 470 + BIO_set_init(e->bio, true); 471 + SSL_set_bio(e->ssl, e->bio, e->bio); 472 + 473 + e->io = io; 474 + e->read_f = rdf; 475 + e->write_f = wrtf; 476 + } 477 + 478 + static void set_io_fd(tlsuv_engine_t self, tlsuv_sock_t fd) { 479 + struct boringssl_engine *e = (struct boringssl_engine *)self; 480 + assert(e->bio == NULL); 481 + e->bio = BIO_new_socket((int)fd, false); 482 + SSL_set_bio(e->ssl, e->bio, e->bio); 483 + } 484 + 485 + static void set_protocols(tlsuv_engine_t self, const char **protocols, int len) { 486 + struct boringssl_engine *e = (struct boringssl_engine *)self; 487 + size_t protolen = 0; 488 + for (int i = 0; i < len; i++) protolen += strlen(protocols[i]) + 1; 489 + 490 + unsigned char *alpn_protocols = tlsuv__malloc(protolen + 1); 491 + unsigned char *p = alpn_protocols; 492 + for (int i = 0; i < len; i++) { 493 + size_t plen = strlen(protocols[i]); 494 + *p++ = (unsigned char)plen; 495 + strncpy((char *)p, protocols[i], plen); 496 + p += plen; 497 + } 498 + *p = 0; 499 + SSL_set_alpn_protos(e->ssl, alpn_protocols, (unsigned int)strlen((char *)alpn_protocols)); 500 + tlsuv__free(alpn_protocols); 501 + } 502 + 503 + static int cert_verify_cb(X509_STORE_CTX *certs, void *ctx) { 504 + struct boringssl_ctx *c = ctx; 505 + X509_STORE *store = X509_STORE_new(); 506 + X509 *crt = X509_STORE_CTX_get0_cert(certs); 507 + X509_STORE_add_cert(store, crt); 508 + 509 + char n[1024]; 510 + X509_NAME_oneline(X509_get_subject_name(crt), n, 1024); 511 + UM_LOG(VERB, "verifying %s", n); 512 + 513 + int rc = 1; 514 + struct cert_s cert; 515 + cert_init(&cert); 516 + cert.cert = store; 517 + if (c->cert_verify_f && c->cert_verify_f((const struct tlsuv_certificate_s *)&cert, c->verify_ctx) != 0) { 518 + UM_LOG(WARN, "verify failed for certificate[%s]", n); 519 + rc = 0; 520 + } 521 + X509_STORE_free(store); 522 + return rc; 523 + } 524 + 525 + int tls_set_partial_vfy(tls_context *ctx, int allow) { 526 + struct boringssl_ctx *c = (struct boringssl_ctx *)ctx; 527 + X509_VERIFY_PARAM *vfy = SSL_CTX_get0_param(c->ctx); 528 + if (allow) X509_VERIFY_PARAM_set_flags(vfy, X509_V_FLAG_PARTIAL_CHAIN); 529 + else X509_VERIFY_PARAM_clear_flags(vfy, X509_V_FLAG_PARTIAL_CHAIN); 530 + return 0; 531 + } 532 + 533 + static void tls_set_cert_verify(tls_context *ctx, int (*verify_f)(const struct tlsuv_certificate_s *cert, void *v_ctx), void *v_ctx) { 534 + struct boringssl_ctx *c = (struct boringssl_ctx *)ctx; 535 + c->cert_verify_f = verify_f; 536 + c->verify_ctx = v_ctx; 537 + SSL_CTX_set_verify(c->ctx, SSL_VERIFY_PEER, NULL); 538 + SSL_CTX_set_cert_verify_callback(c->ctx, cert_verify_cb, c); 539 + } 540 + 541 + static void tls_free_ctx(tls_context *ctx) { 542 + struct boringssl_ctx *c = (struct boringssl_ctx *)ctx; 543 + if (c->alpn_protocols) { 544 + tlsuv__free(c->alpn_protocols); 545 + } 546 + SSL_CTX_free(c->ctx); 547 + tlsuv__free(c); 548 + } 549 + 550 + static int tls_reset(tlsuv_engine_t self) { 551 + struct boringssl_engine *e = (struct boringssl_engine *)self; 552 + ERR_clear_error(); 553 + e->bio = NULL; 554 + if (!SSL_clear(e->ssl)) { 555 + int err = SSL_get_error(e->ssl, 0); 556 + UM_LOG(ERR, "error resetting TLS engine: %d(%s)", err, tls_error(err)); 557 + return -1; 558 + } 559 + return 0; 560 + } 561 + 562 + static void tls_free(tlsuv_engine_t self) { 563 + struct boringssl_engine *e = (struct boringssl_engine *)self; 564 + SSL_free(e->ssl); 565 + if (e->alpn) { 566 + tlsuv__free(e->alpn); 567 + } 568 + tlsuv__free(e); 569 + } 570 + 571 + #define SSL_OP_CHECK(op, desc) do { \ 572 + if ((op) != 1) { \ 573 + uint32_t err = ERR_get_error(); \ 574 + UM_LOG(ERR, "failed to " desc ": %d(%s)", err, tls_error(err)); \ 575 + return TLS_ERR; \ 576 + } \ 577 + } while (0) 578 + 579 + static X509 *tls_set_cert_internal(SSL_CTX *ssl, X509_STORE *store) { 580 + STACK_OF(X509_OBJECT) *certs = X509_STORE_get0_objects(store); 581 + X509 *crt = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(certs, 0)); 582 + SSL_CTX_use_certificate(ssl, crt); 583 + 584 + for (int i = 1; i < sk_X509_OBJECT_num(certs); i++) { 585 + X509 *x509 = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(certs, i)); 586 + X509_up_ref(x509); 587 + SSL_CTX_add_extra_chain_cert(ssl, x509); 588 + } 589 + return crt; 590 + } 591 + 592 + static int tls_set_own_cert(tls_context *ctx, tlsuv_private_key_t key, tlsuv_certificate_t cert) { 593 + struct boringssl_ctx *c = (struct boringssl_ctx *)ctx; 594 + SSL_CTX *ssl = c->ctx; 595 + 596 + SSL_CTX_use_PrivateKey(ssl, NULL); 597 + SSL_CTX_use_certificate(ssl, NULL); 598 + SSL_CTX_clear_chain_certs(ssl); 599 + 600 + if (key == NULL) { 601 + return 0; 602 + } 603 + 604 + struct cert_s *crt = (struct cert_s *)cert; 605 + X509_STORE *store = NULL; 606 + if (crt == NULL) { 607 + if (key->get_certificate) { 608 + if (key->get_certificate(key, (tlsuv_certificate_t *)&crt) != 0) { 609 + return -1; 610 + } 611 + store = crt->cert; 612 + free(crt); 613 + } 614 + } else { 615 + store = crt->cert; 616 + X509_STORE_up_ref(crt->cert); 617 + } 618 + 619 + if (store == NULL) { 620 + return -1; 621 + } 622 + 623 + struct priv_key_s *pk = (struct priv_key_s *)key; 624 + X509 *certs = tls_set_cert_internal(ssl, store); 625 + X509_STORE_free(store); 626 + 627 + SSL_OP_CHECK(X509_check_private_key(certs, pk->pkey), "verify key/cert combo"); 628 + SSL_OP_CHECK(SSL_CTX_use_PrivateKey(ssl, pk->pkey), "set private key"); 629 + return 0; 630 + } 631 + 632 + static tls_handshake_state tls_hs_state(tlsuv_engine_t engine) { 633 + struct boringssl_engine *eng = (struct boringssl_engine *)engine; 634 + if (SSL_is_init_finished(eng->ssl)) return TLS_HS_COMPLETE; 635 + return eng->handshake_started ? TLS_HS_CONTINUE : TLS_HS_BEFORE; 636 + } 637 + 638 + static int print_err_cb(const char *e, size_t len, void *v) { 639 + (void)v; 640 + UM_LOG(WARN, "%.*s", (int)len, e); 641 + return 1; 642 + } 643 + 644 + static tls_handshake_state tls_continue_hs(tlsuv_engine_t self) { 645 + struct boringssl_engine *eng = (struct boringssl_engine *)self; 646 + ERR_clear_error(); 647 + eng->handshake_started = true; 648 + 649 + int rc = SSL_do_handshake(eng->ssl); 650 + if (rc != 1) { 651 + eng->error = ERR_peek_error(); 652 + ERR_print_errors_cb(print_err_cb, NULL); 653 + } 654 + 655 + if (rc == 1) { 656 + eng->error = 0; 657 + return TLS_HS_COMPLETE; 658 + } 659 + 660 + int err = SSL_get_error(eng->ssl, rc); 661 + if (rc == 0) { 662 + UM_LOG(ERR, "boringssl: handshake was terminated: %s", tls_error(eng->error)); 663 + return TLS_HS_ERROR; 664 + } 665 + 666 + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { 667 + return TLS_HS_CONTINUE; 668 + } 669 + 670 + UM_LOG(ERR, "boringssl: handshake was terminated: %s", tls_error(eng->error)); 671 + return TLS_HS_ERROR; 672 + } 673 + 674 + static const char *tls_get_alpn(tlsuv_engine_t self) { 675 + struct boringssl_engine *eng = (struct boringssl_engine *)self; 676 + const unsigned char *proto; 677 + unsigned int protolen; 678 + SSL_get0_alpn_selected(eng->ssl, &proto, &protolen); 679 + 680 + eng->alpn = tlsuv__calloc(1, protolen + 1); 681 + strncpy(eng->alpn, (const char *)proto, protolen); 682 + return eng->alpn; 683 + } 684 + 685 + static int tls_write(tlsuv_engine_t self, const char *data, size_t data_len) { 686 + struct boringssl_engine *eng = (struct boringssl_engine *)self; 687 + ERR_clear_error(); 688 + 689 + if (data_len > INT_MAX) data_len = INT_MAX; 690 + 691 + size_t wrote = 0; 692 + while (data_len > wrote) { 693 + int remaining = (int)(data_len - wrote); 694 + int ret = SSL_write(eng->ssl, data + wrote, remaining); 695 + if (ret <= 0) { 696 + int err = SSL_get_error(eng->ssl, ret); 697 + if (err == SSL_ERROR_WANT_WRITE) { 698 + return wrote > 0 ? (int)wrote : TLS_AGAIN; 699 + } 700 + eng->error = ERR_peek_last_error(); 701 + UM_LOG(ERR, "boringssl: write[%d] error: %s", err, tls_error(eng->error)); 702 + return -1; 703 + } 704 + wrote += (size_t)ret; 705 + } 706 + 707 + return (int)wrote; 708 + } 709 + 710 + static int tls_read(tlsuv_engine_t self, char *out, size_t *out_bytes, size_t maxout) { 711 + struct boringssl_engine *eng = (struct boringssl_engine *)self; 712 + int err = SSL_ERROR_NONE; 713 + uint8_t *writep = (uint8_t *)out; 714 + size_t total_out = 0; 715 + 716 + ERR_clear_error(); 717 + while (maxout - total_out > 0) { 718 + int want = (int)(maxout - total_out); 719 + int rc = SSL_read(eng->ssl, writep, want); 720 + if (rc <= 0) { 721 + err = SSL_get_error(eng->ssl, rc); 722 + break; 723 + } 724 + total_out += (size_t)rc; 725 + writep += rc; 726 + } 727 + 728 + if (total_out > 0) { 729 + *out_bytes = total_out; 730 + return SSL_pending(eng->ssl) ? TLS_MORE_AVAILABLE : TLS_OK; 731 + } 732 + 733 + *out_bytes = 0; 734 + if (SSL_get_shutdown(eng->ssl)) return TLS_EOF; 735 + 736 + unsigned long err_code = ERR_peek_last_error(); 737 + switch (err) { 738 + case SSL_ERROR_NONE: 739 + UM_LOG(WARN, "boringssl read: SSL_ERROR_NONE with 0 bytes read"); 740 + return TLS_OK; 741 + case SSL_ERROR_ZERO_RETURN: 742 + return TLS_EOF; 743 + case SSL_ERROR_WANT_WRITE: 744 + case SSL_ERROR_WANT_READ: 745 + return TLS_AGAIN; 746 + case SSL_ERROR_SYSCALL: 747 + case SSL_ERROR_SSL: 748 + eng->error = err_code; 749 + UM_LOG(WARN, "boringssl read[%d]: %lX/%s", err, err_code, tls_error(err_code)); 750 + return TLS_ERR; 751 + default: 752 + UM_LOG(WARN, "boringssl read: unexpected err[%d] code[%lX]", err, err_code); 753 + break; 754 + } 755 + return TLS_OK; 756 + } 757 + 758 + static int tls_close(tlsuv_engine_t self) { 759 + struct boringssl_engine *eng = (struct boringssl_engine *)self; 760 + ERR_clear_error(); 761 + int rc = SSL_shutdown(eng->ssl); 762 + if (rc < 0) { 763 + int err = SSL_get_error(eng->ssl, rc); 764 + unsigned long err_code = ERR_peek_last_error(); 765 + UM_LOG(WARN, "boringssl shutdown[%d]: %lX/%s", err, err_code, tls_error(err_code)); 766 + } 767 + return 0; 768 + } 769 + 770 + static int parse_pkcs7_certs(tlsuv_certificate_t *chain, const char *pkcs7buf, size_t pkcs7len) { 771 + BIO *buf = BIO_new_mem_buf(pkcs7buf, (int)pkcs7len); 772 + PKCS7 *pkcs7 = PEM_read_bio_PKCS7(buf, NULL, NULL, NULL); 773 + if (pkcs7 == NULL) { 774 + BIO_free(buf); 775 + buf = BIO_new_mem_buf(pkcs7buf, (int)pkcs7len); 776 + pkcs7 = d2i_PKCS7_bio(buf, NULL); 777 + } 778 + 779 + if (pkcs7 == NULL) { 780 + BIO_free(buf); 781 + return -1; 782 + } 783 + 784 + STACK_OF(X509) *certs; 785 + if (PKCS7_type_is_signed(pkcs7)) certs = pkcs7->d.sign->cert; 786 + else if (PKCS7_type_is_signedAndEnveloped(pkcs7)) certs = pkcs7->d.signed_and_enveloped->cert; 787 + else { 788 + BIO_free(buf); 789 + PKCS7_free(pkcs7); 790 + return -1; 791 + } 792 + 793 + X509_STORE *store = X509_STORE_new(); 794 + for (int i = 0; i < sk_X509_num(certs); i++) { 795 + X509 *c = sk_X509_value(certs, i); 796 + X509_STORE_add_cert(store, c); 797 + } 798 + 799 + struct cert_s *c = tlsuv__calloc(1, sizeof(*c)); 800 + cert_init(c); 801 + c->cert = store; 802 + *chain = (tlsuv_certificate_t)c; 803 + 804 + PKCS7_free(pkcs7); 805 + BIO_free(buf); 806 + return 0; 807 + } 808 + 809 + static int generate_csr(tlsuv_private_key_t key, char **pem, size_t *pemlen, ...) { 810 + struct priv_key_s *privkey = (struct priv_key_s *)key; 811 + int ret = 0; 812 + const char *op = NULL; 813 + EVP_PKEY *pk = privkey->pkey; 814 + X509_REQ *req = X509_REQ_new(); 815 + X509_NAME *subj = X509_REQ_get_subject_name(req); 816 + BIO *b = BIO_new(BIO_s_mem()); 817 + 818 + va_list va; 819 + va_start(va, pemlen); 820 + while (true) { 821 + char *id = va_arg(va, char *); 822 + if (id == NULL) break; 823 + const uint8_t *val = va_arg(va, uint8_t *); 824 + if (val == NULL) break; 825 + X509_NAME_add_entry_by_txt(subj, id, MBSTRING_ASC, val, -1, -1, 0); 826 + } 827 + va_end(va); 828 + 829 + #define ssl_check(OP) do { \ 830 + op = #OP; \ 831 + if ((OP) == 0) { \ 832 + ret = ERR_get_error(); \ 833 + goto on_error; \ 834 + } \ 835 + } while (0) 836 + 837 + ssl_check(X509_REQ_set_pubkey(req, pk)); 838 + ssl_check(X509_REQ_sign(req, pk, EVP_sha256())); 839 + ssl_check(PEM_write_bio_X509_REQ(b, req)); 840 + 841 + on_error: 842 + if (ret) { 843 + UM_LOG(WARN, "%s => %s", op, tls_error(ret)); 844 + } else { 845 + size_t len = BIO_ctrl_pending(b); 846 + *pem = tlsuv__calloc(1, len + 1); 847 + BIO_read(b, *pem, (int)len); 848 + if (pemlen) *pemlen = len; 849 + } 850 + 851 + BIO_free(b); 852 + X509_REQ_free(req); 853 + return ret; 854 + } 855 + 856 + #if _WIN32 857 + #include <wincrypt.h> 858 + #pragma comment (lib, "crypt32.lib") 859 + 860 + static X509_STORE *load_system_certs() { 861 + X509_STORE *store = X509_STORE_new(); 862 + X509 *c; 863 + HCERTSTORE hCertStore; 864 + PCCERT_CONTEXT pCertContext = NULL; 865 + 866 + if (!(hCertStore = CertOpenSystemStore(0, "ROOT"))) { 867 + UM_LOG(ERR, "The first system store did not open."); 868 + return store; 869 + } 870 + 871 + while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)) != NULL) { 872 + c = d2i_X509(NULL, (const uint8_t **)&pCertContext->pbCertEncoded, (long)pCertContext->cbCertEncoded); 873 + X509_STORE_add_cert(store, c); 874 + } 875 + CertFreeCertificateContext(pCertContext); 876 + CertCloseStore(hCertStore, 0); 877 + 878 + return store; 879 + } 880 + #endif 881 + 882 + static int engine_bio_write(BIO *b, const char *data, int len) { 883 + struct boringssl_engine *e = BIO_get_data(b); 884 + assert(e); 885 + assert(e->write_f); 886 + 887 + ssize_t r = e->write_f(e->io, data, (size_t)len); 888 + if (r > 0) { 889 + return (int)r; 890 + } 891 + if (r == 0) { 892 + BIO_set_retry_write(b); 893 + } 894 + return -1; 895 + } 896 + 897 + static int engine_bio_read(BIO *b, char *data, int len) { 898 + struct boringssl_engine *e = BIO_get_data(b); 899 + assert(e); 900 + assert(e->read_f); 901 + 902 + ssize_t r = e->read_f(e->io, data, (size_t)len); 903 + if (r > 0) { 904 + return (int)r; 905 + } 906 + if (r == 0) { 907 + BIO_set_retry_read(b); 908 + } 909 + return -1; 910 + } 911 + 912 + static int engine_bio_puts(BIO *b, const char *str) { 913 + return engine_bio_write(b, str, (int)strlen(str)); 914 + } 915 + 916 + static long engine_bio_ctrl(BIO *b, int cmd, long num, void *ptr) { 917 + (void)b; 918 + (void)num; 919 + (void)ptr; 920 + switch (cmd) { 921 + case BIO_CTRL_FLUSH: 922 + case BIO_CTRL_DGRAM_QUERY_MTU: 923 + return 1; 924 + default: 925 + return 0; 926 + } 927 + } 928 + 929 + static int engine_bio_create(BIO *b) { 930 + BIO_set_init(b, 0); 931 + BIO_set_data(b, NULL); 932 + return 1; 933 + } 934 + 935 + static int engine_bio_destroy(BIO *b) { 936 + if (b == NULL) return 0; 937 + BIO_set_data(b, NULL); 938 + BIO_set_init(b, 0); 939 + return 1; 940 + } 941 + 942 + static BIO_METHOD *BIO_s_engine(void) { 943 + static BIO_METHOD *engine = NULL; 944 + if (engine == NULL) { 945 + engine = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "tlsuv-engine"); 946 + BIO_meth_set_write(engine, engine_bio_write); 947 + BIO_meth_set_read(engine, engine_bio_read); 948 + BIO_meth_set_puts(engine, engine_bio_puts); 949 + BIO_meth_set_ctrl(engine, engine_bio_ctrl); 950 + BIO_meth_set_create(engine, engine_bio_create); 951 + BIO_meth_set_destroy(engine, engine_bio_destroy); 952 + } 953 + return engine; 954 + }
+386
vendor/packagefiles/tlsuv/src/boringssl/keys.c
··· 1 + #define OPENSSL_SUPPRESS_DEPRECATED 2 + 3 + #include <openssl/err.h> 4 + #include <openssl/evp.h> 5 + #include <openssl/pem.h> 6 + #include <openssl/asn1.h> 7 + #include <openssl/x509.h> 8 + 9 + #include <assert.h> 10 + #include <string.h> 11 + 12 + #include "../alloc.h" 13 + #include "../um_debug.h" 14 + #include "keys.h" 15 + 16 + static const char *cert_to_text(const struct tlsuv_certificate_s *cert); 17 + static int cert_to_pem(const struct tlsuv_certificate_s *cert, int full, char **pem, size_t *pemlen); 18 + static void cert_free(tlsuv_certificate_t cert); 19 + static int cert_verify(const struct tlsuv_certificate_s *cert, enum hash_algo md, const char *data, size_t datalen, const char *sig, size_t siglen); 20 + static int cert_exp(const struct tlsuv_certificate_s *cert, struct tm *time); 21 + 22 + static struct cert_s cert_API = { 23 + .free = cert_free, 24 + .verify = cert_verify, 25 + .to_pem = cert_to_pem, 26 + .get_text = cert_to_text, 27 + .get_expiration = cert_exp, 28 + }; 29 + 30 + static int pubkey_to_pem(tlsuv_public_key_t pub, char **pem, size_t *pemlen); 31 + static void pubkey_free(tlsuv_public_key_t k); 32 + static int pubkey_verify(tlsuv_public_key_t pk, enum hash_algo md, const char *data, size_t datalen, const char *sig, size_t siglen); 33 + 34 + static struct pub_key_s PUB_KEY_API = { 35 + .free = pubkey_free, 36 + .verify = pubkey_verify, 37 + .to_pem = pubkey_to_pem, 38 + }; 39 + 40 + static void privkey_free(tlsuv_private_key_t k); 41 + static tlsuv_public_key_t privkey_pubkey(tlsuv_private_key_t pk); 42 + static int privkey_to_pem(tlsuv_private_key_t pk, char **pem, size_t *pemlen); 43 + static int privkey_sign(tlsuv_private_key_t pk, enum hash_algo md, const char *data, size_t datalen, char *sig, size_t *siglen); 44 + static int privkey_get_cert(tlsuv_private_key_t pk, tlsuv_certificate_t *cert); 45 + static int privkey_store_cert(tlsuv_private_key_t pk, tlsuv_certificate_t cert); 46 + 47 + static struct priv_key_s PRIV_KEY_API = { 48 + .free = privkey_free, 49 + .to_pem = privkey_to_pem, 50 + .pubkey = privkey_pubkey, 51 + .sign = privkey_sign, 52 + .get_certificate = privkey_get_cert, 53 + .store_certificate = privkey_store_cert, 54 + }; 55 + 56 + static tlsuv_private_key_t new_private_key(EVP_PKEY *pkey) { 57 + struct priv_key_s *private_key = tlsuv__calloc(1, sizeof(struct priv_key_s)); 58 + *private_key = PRIV_KEY_API; 59 + private_key->pkey = pkey; 60 + return (tlsuv_private_key_t)private_key; 61 + } 62 + 63 + void pub_key_init(struct pub_key_s *pubkey) { 64 + *pubkey = PUB_KEY_API; 65 + } 66 + 67 + void cert_init(struct cert_s *c) { 68 + *c = cert_API; 69 + } 70 + 71 + static void pubkey_free(tlsuv_public_key_t k) { 72 + struct pub_key_s *pub = (struct pub_key_s *)k; 73 + EVP_PKEY_free(pub->pkey); 74 + tlsuv__free(pub); 75 + } 76 + 77 + static int verify_ecdsa_sig(EC_KEY *ec, const EVP_MD *hash, const char *data, size_t datalen, const char *sig, size_t siglen) { 78 + int rc; 79 + ECDSA_SIG *ecdsa_sig = NULL; 80 + EVP_MD_CTX *digestor = EVP_MD_CTX_new(); 81 + uint8_t digest[EVP_MAX_MD_SIZE]; 82 + unsigned int digest_len; 83 + 84 + EVP_DigestInit(digestor, hash); 85 + EVP_DigestUpdate(digestor, data, datalen); 86 + rc = EVP_DigestFinal(digestor, digest, &digest_len); 87 + 88 + if (rc == 1) { 89 + BIGNUM *r = BN_bin2bn((const uint8_t *)sig, (int)(siglen / 2), NULL); 90 + BIGNUM *s = BN_bin2bn((const uint8_t *)sig + siglen / 2, (int)(siglen / 2), NULL); 91 + 92 + ecdsa_sig = ECDSA_SIG_new(); 93 + ECDSA_SIG_set0(ecdsa_sig, r, s); 94 + rc = ECDSA_do_verify(digest, (int)digest_len, ecdsa_sig, ec); 95 + } 96 + 97 + ECDSA_SIG_free(ecdsa_sig); 98 + EVP_MD_CTX_free(digestor); 99 + return rc == 1 ? 0 : -1; 100 + } 101 + 102 + int verify_signature(EVP_PKEY *pk, enum hash_algo md, const char *data, size_t datalen, const char *sig, size_t siglen) { 103 + const EVP_MD *hash = NULL; 104 + switch (md) { 105 + case hash_SHA256: hash = EVP_sha256(); break; 106 + case hash_SHA384: hash = EVP_sha384(); break; 107 + case hash_SHA512: hash = EVP_sha512(); break; 108 + default: break; 109 + } 110 + 111 + EVP_MD_CTX *digestor = EVP_MD_CTX_new(); 112 + if (EVP_DigestVerifyInit(digestor, NULL, hash, NULL, pk) != 1 || 113 + EVP_DigestVerifyUpdate(digestor, data, datalen) != 1) { 114 + UM_LOG(WARN, "failed to create digest: %s", tls_error(ERR_get_error())); 115 + EVP_MD_CTX_free(digestor); 116 + return -1; 117 + } 118 + 119 + int rc = EVP_DigestVerifyFinal(digestor, (const uint8_t *)sig, siglen); 120 + EVP_MD_CTX_free(digestor); 121 + 122 + if (rc != 1 && EVP_PKEY_id(pk) == EVP_PKEY_EC) { 123 + const uint8_t *p = (const uint8_t *)sig; 124 + ECDSA_SIG *ecdsa_sig = d2i_ECDSA_SIG(NULL, &p, (int)siglen); 125 + if (ecdsa_sig == NULL) { 126 + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pk); 127 + int verified = verify_ecdsa_sig(ec, hash, data, datalen, sig, siglen); 128 + EC_KEY_free(ec); 129 + return verified; 130 + } 131 + ECDSA_SIG_free(ecdsa_sig); 132 + } 133 + 134 + return rc == 1 ? 0 : -1; 135 + } 136 + 137 + static int pubkey_verify(tlsuv_public_key_t pk, enum hash_algo md, const char *data, size_t datalen, const char *sig, size_t siglen) { 138 + struct pub_key_s *pub = (struct pub_key_s *)pk; 139 + return verify_signature(pub->pkey, md, data, datalen, sig, siglen); 140 + } 141 + 142 + static void privkey_free(tlsuv_private_key_t k) { 143 + struct priv_key_s *priv = (struct priv_key_s *)k; 144 + EVP_PKEY_free(priv->pkey); 145 + tlsuv__free(priv); 146 + } 147 + 148 + static int privkey_sign(tlsuv_private_key_t pk, enum hash_algo md, const char *data, size_t datalen, char *sig, size_t *siglen) { 149 + struct priv_key_s *priv = (struct priv_key_s *)pk; 150 + int rc = 0; 151 + EVP_MD_CTX *digest = EVP_MD_CTX_new(); 152 + EVP_PKEY_CTX *pctx = NULL; 153 + 154 + const EVP_MD *hash = NULL; 155 + switch (md) { 156 + case hash_SHA256: hash = EVP_sha256(); break; 157 + case hash_SHA384: hash = EVP_sha384(); break; 158 + case hash_SHA512: hash = EVP_sha512(); break; 159 + default: break; 160 + } 161 + 162 + if ((EVP_DigestSignInit(digest, &pctx, hash, NULL, priv->pkey) != 1) || 163 + (EVP_DigestSignUpdate(digest, data, datalen) != 1)) { 164 + unsigned long err = ERR_get_error(); 165 + UM_LOG(WARN, "failed to setup digest %ld/%s", err, ERR_lib_error_string(err)); 166 + rc = -1; 167 + } 168 + 169 + if (rc == 0 && EVP_DigestSignFinal(digest, (uint8_t *)sig, siglen) != 1) { 170 + unsigned long err = ERR_get_error(); 171 + UM_LOG(WARN, "failed to sign digest %ld/%s", err, ERR_lib_error_string(err)); 172 + rc = -1; 173 + } 174 + 175 + EVP_MD_CTX_free(digest); 176 + return rc; 177 + } 178 + 179 + static tlsuv_public_key_t privkey_pubkey(tlsuv_private_key_t pk) { 180 + struct priv_key_s *priv = (struct priv_key_s *)pk; 181 + struct pub_key_s *pub = tlsuv__calloc(1, sizeof(*pub)); 182 + pub_key_init(pub); 183 + 184 + BIO *bio = BIO_new(BIO_s_mem()); 185 + PEM_write_bio_PUBKEY(bio, priv->pkey); 186 + pub->pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); 187 + BIO_free_all(bio); 188 + 189 + return (tlsuv_public_key_t)pub; 190 + } 191 + 192 + static int privkey_to_pem(tlsuv_private_key_t pk, char **pem, size_t *pemlen) { 193 + BIO *b = BIO_new(BIO_s_mem()); 194 + struct priv_key_s *privkey = (struct priv_key_s *)pk; 195 + 196 + *pem = NULL; 197 + *pemlen = 0; 198 + 199 + if (!PEM_write_bio_PKCS8PrivateKey(b, privkey->pkey, NULL, NULL, 0, NULL, NULL)) { 200 + unsigned long err = ERR_get_error(); 201 + UM_LOG(WARN, "failed to generate PEM for private key: %ld/%s", err, ERR_lib_error_string(err)); 202 + } else { 203 + size_t len = BIO_ctrl_pending(b); 204 + *pem = tlsuv__calloc(1, len + 1); 205 + BIO_read(b, *pem, (int)len); 206 + *pemlen = len; 207 + } 208 + 209 + BIO_free(b); 210 + return *pem != NULL ? 0 : -1; 211 + } 212 + 213 + static int pubkey_to_pem(tlsuv_public_key_t pub, char **pem, size_t *pemlen) { 214 + BIO *b = BIO_new(BIO_s_mem()); 215 + struct pub_key_s *pubkey = (struct pub_key_s *)pub; 216 + 217 + *pem = NULL; 218 + *pemlen = 0; 219 + 220 + if (!PEM_write_bio_PUBKEY(b, pubkey->pkey)) { 221 + unsigned long err = ERR_get_error(); 222 + UM_LOG(WARN, "failed to generate PEM for public key: %ld/%s", err, ERR_lib_error_string(err)); 223 + } else { 224 + size_t len = BIO_ctrl_pending(b); 225 + *pem = tlsuv__calloc(1, len + 1); 226 + BIO_read(b, *pem, (int)len); 227 + *pemlen = len; 228 + } 229 + 230 + BIO_free(b); 231 + return *pem != NULL ? 0 : -1; 232 + } 233 + 234 + int load_key(tlsuv_private_key_t *key, const char *keydata, size_t keydatalen) { 235 + BIO *kb; 236 + int rc = 0; 237 + FILE *kf = fopen(keydata, "r"); 238 + if (kf != NULL) { 239 + kb = BIO_new_fp(kf, 1); 240 + } else { 241 + kb = BIO_new_mem_buf(keydata, (int)keydatalen); 242 + } 243 + 244 + EVP_PKEY *pk = NULL; 245 + if (!PEM_read_bio_PrivateKey(kb, &pk, NULL, NULL)) { 246 + unsigned long err = ERR_get_error(); 247 + UM_LOG(WARN, "failed to load key: %ld/%s", err, ERR_lib_error_string(err)); 248 + rc = -1; 249 + } else { 250 + *key = new_private_key(pk); 251 + } 252 + 253 + BIO_free(kb); 254 + return rc; 255 + } 256 + 257 + int gen_key(tlsuv_private_key_t *key) { 258 + int rc = 0; 259 + EVP_PKEY *pk = EVP_PKEY_new(); 260 + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); 261 + EVP_PKEY_keygen_init(pctx); 262 + EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1); 263 + 264 + if (!EVP_PKEY_keygen(pctx, &pk)) { 265 + uint32_t err = ERR_get_error(); 266 + UM_LOG(ERR, "failed to generate key: %d(%s)", err, tls_error(err)); 267 + rc = -1; 268 + EVP_PKEY_free(pk); 269 + } 270 + 271 + if (rc == 0) { 272 + *key = new_private_key(pk); 273 + } 274 + 275 + EVP_PKEY_CTX_free(pctx); 276 + return rc; 277 + } 278 + 279 + static int privkey_get_cert(tlsuv_private_key_t pk, tlsuv_certificate_t *cert) { 280 + (void)pk; 281 + (void)cert; 282 + return -1; 283 + } 284 + 285 + static int privkey_store_cert(tlsuv_private_key_t pk, tlsuv_certificate_t cert) { 286 + (void)pk; 287 + (void)cert; 288 + return -1; 289 + } 290 + 291 + static const char *cert_to_text(const struct tlsuv_certificate_s *cert) { 292 + struct cert_s *c = (struct cert_s *)cert; 293 + 294 + if (c->text) return c->text; 295 + 296 + STACK_OF(X509_OBJECT) *s = X509_STORE_get0_objects(c->cert); 297 + X509 *x509 = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(s, 0)); 298 + BIO *bio = BIO_new(BIO_s_mem()); 299 + X509_print_ex(bio, x509, 0, X509_FLAG_NO_HEADER | X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME); 300 + 301 + int len = BIO_pending(bio); 302 + c->text = tlsuv__malloc((size_t)len + 1); 303 + BIO_read(bio, c->text, len); 304 + c->text[len] = '\0'; 305 + BIO_free(bio); 306 + 307 + return c->text; 308 + } 309 + 310 + static void cert_free(tlsuv_certificate_t cert) { 311 + struct cert_s *c = (struct cert_s *)cert; 312 + if (c->cert != NULL) { 313 + X509_STORE_free(c->cert); 314 + } 315 + tlsuv__free(c->text); 316 + tlsuv__free(c); 317 + } 318 + 319 + static int cert_to_pem(const struct tlsuv_certificate_s *cert, int full_chain, char **pem, size_t *pemlen) { 320 + X509_STORE *store = ((struct cert_s *)cert)->cert; 321 + BIO *pembio = BIO_new(BIO_s_mem()); 322 + STACK_OF(X509_OBJECT) *s = X509_STORE_get0_objects(store); 323 + 324 + for (int i = 0; i < sk_X509_OBJECT_num(s); i++) { 325 + X509 *c = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(s, i)); 326 + PEM_write_bio_X509(pembio, c); 327 + if (!full_chain) { 328 + break; 329 + } 330 + } 331 + 332 + *pemlen = BIO_ctrl_pending(pembio); 333 + *pem = tlsuv__calloc(1, *pemlen + 1); 334 + BIO_read(pembio, *pem, (int)*pemlen); 335 + BIO_free_all(pembio); 336 + return 0; 337 + } 338 + 339 + static int cert_verify(const struct tlsuv_certificate_s *cert, enum hash_algo md, const char *data, size_t datalen, const char *sig, size_t siglen) { 340 + X509_STORE *store = ((struct cert_s *)cert)->cert; 341 + STACK_OF(X509_OBJECT) *s = X509_STORE_get0_objects(store); 342 + X509 *c = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(s, 0)); 343 + EVP_PKEY *pk = X509_get_pubkey(c); 344 + if (pk == NULL) { 345 + unsigned long err = ERR_peek_error(); 346 + UM_LOG(WARN, "no pub key: %ld/%s", err, ERR_lib_error_string(err)); 347 + return -1; 348 + } 349 + 350 + int rc = verify_signature(pk, md, data, datalen, sig, siglen); 351 + EVP_PKEY_free(pk); 352 + return rc; 353 + } 354 + 355 + static int cert_exp(const struct tlsuv_certificate_s *cert, struct tm *time) { 356 + if (time == NULL || cert == NULL) { 357 + return -1; 358 + } 359 + 360 + X509_STORE *store = ((struct cert_s *)cert)->cert; 361 + STACK_OF(X509_OBJECT) *s = X509_STORE_get0_objects(store); 362 + X509 *c = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(s, 0)); 363 + const ASN1_TIME *notAfter = X509_get0_notAfter(c); 364 + ASN1_GENERALIZEDTIME *gt = ASN1_TIME_to_generalizedtime(notAfter, NULL); 365 + if (gt == NULL) { 366 + return -1; 367 + } 368 + 369 + const char *v = (const char *)ASN1_STRING_get0_data((const ASN1_STRING *)gt); 370 + size_t len = (size_t)ASN1_STRING_length((const ASN1_STRING *)gt); 371 + if (v == NULL || len < 14) { 372 + ASN1_GENERALIZEDTIME_free(gt); 373 + return -1; 374 + } 375 + 376 + memset(time, 0, sizeof(*time)); 377 + time->tm_year = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] - '0') - 1900; 378 + time->tm_mon = ((v[4] - '0') * 10 + (v[5] - '0')) - 1; 379 + time->tm_mday = (v[6] - '0') * 10 + (v[7] - '0'); 380 + time->tm_hour = (v[8] - '0') * 10 + (v[9] - '0'); 381 + time->tm_min = (v[10] - '0') * 10 + (v[11] - '0'); 382 + time->tm_sec = (v[12] - '0') * 10 + (v[13] - '0'); 383 + 384 + ASN1_GENERALIZEDTIME_free(gt); 385 + return 0; 386 + }
+31
vendor/packagefiles/tlsuv/src/boringssl/keys.h
··· 1 + #ifndef TLSUV_BORINGSSL_KEYS_H 2 + #define TLSUV_BORINGSSL_KEYS_H 3 + 4 + #include <tlsuv/tls_engine.h> 5 + 6 + struct cert_s { 7 + TLSUV_CERT_API 8 + X509_STORE *cert; 9 + char *text; 10 + }; 11 + 12 + struct pub_key_s { 13 + TLSUV_PUBKEY_API 14 + EVP_PKEY *pkey; 15 + }; 16 + 17 + struct priv_key_s { 18 + TLSUV_PRIVKEY_API 19 + EVP_PKEY *pkey; 20 + }; 21 + 22 + const char *tls_error(unsigned long code); 23 + 24 + void pub_key_init(struct pub_key_s *pubkey); 25 + void cert_init(struct cert_s *c); 26 + 27 + int gen_key(tlsuv_private_key_t *key); 28 + int load_key(tlsuv_private_key_t *key, const char *keydata, size_t keydatalen); 29 + int verify_signature(EVP_PKEY *pk, enum hash_algo md, const char *data, size_t datalen, const char *sig, size_t siglen); 30 + 31 + #endif
+1
vendor/tlsuv.wrap
··· 3 3 revision = v0.40.13 4 4 depth = 1 5 5 patch_directory = tlsuv 6 + diff_files = patches/tlsuv-boringssl.patch 6 7 7 8 [provide] 8 9 tlsuv = tlsuv_dep