Add RPK and PQ crypto features
This commit is contained in:
parent
8f488550eb
commit
c4e8a94a69
|
|
@ -197,3 +197,16 @@ jobs:
|
||||||
run: ln -s clang clang++-12
|
run: ln -s clang clang++-12
|
||||||
- run: cargo test --features fips
|
- run: cargo test --features fips
|
||||||
name: Run tests
|
name: Run tests
|
||||||
|
|
||||||
|
test-rpk:
|
||||||
|
name: Test RPK
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
- name: Install Rust (rustup)
|
||||||
|
run: rustup update stable --no-self-update && rustup default stable
|
||||||
|
shell: bash
|
||||||
|
- run: cargo test --features rpk
|
||||||
|
name: Run tests
|
||||||
|
|
|
||||||
|
|
@ -5,3 +5,4 @@ members = [
|
||||||
"tokio-boring",
|
"tokio-boring",
|
||||||
"hyper-boring"
|
"hyper-boring"
|
||||||
]
|
]
|
||||||
|
resolver = "2"
|
||||||
|
|
@ -11,7 +11,7 @@ documentation = "https://docs.rs/boring-sys"
|
||||||
links = "boringssl"
|
links = "boringssl"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
categories = ["cryptography", "external-ffi-bindings"]
|
categories = ["cryptography", "external-ffi-bindings"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
include = [
|
include = [
|
||||||
"/*.md",
|
"/*.md",
|
||||||
"/*.toml",
|
"/*.toml",
|
||||||
|
|
@ -24,12 +24,21 @@ include = [
|
||||||
"/deps/boringssl/LICENSE",
|
"/deps/boringssl/LICENSE",
|
||||||
"/build.rs",
|
"/build.rs",
|
||||||
"/src",
|
"/src",
|
||||||
|
"/patches",
|
||||||
|
"/scripts"
|
||||||
]
|
]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = { version = "0.65.1", default-features = false, features = ["runtime"] }
|
bindgen = { version = "0.65.1", default-features = false, features = ["runtime"] }
|
||||||
cmake = "0.1"
|
cmake = "0.1"
|
||||||
|
fslock = "0.2.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Use a FIPS-validated version of boringssl.
|
# Use a FIPS-validated version of boringssl.
|
||||||
fips = []
|
fips = []
|
||||||
|
|
||||||
|
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
|
||||||
|
rpk = []
|
||||||
|
|
||||||
|
# Enables post-quantum crypto (https://blog.cloudflare.com/post-quantum-for-all/)
|
||||||
|
post-quantum = []
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
use fslock::LockFile;
|
||||||
|
use std::env;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
|
@ -285,7 +289,6 @@ fn get_extra_clang_args_for_bindgen() -> Vec<String> {
|
||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
match os.as_ref() {
|
match os.as_ref() {
|
||||||
"ios" => {
|
"ios" => {
|
||||||
use std::io::Write;
|
|
||||||
// When cross-compiling for iOS, tell bindgen to use iOS sysroot,
|
// When cross-compiling for iOS, tell bindgen to use iOS sysroot,
|
||||||
// and *don't* use system headers of the host macOS.
|
// and *don't* use system headers of the host macOS.
|
||||||
let sdk = get_ios_sdk_name();
|
let sdk = get_ios_sdk_name();
|
||||||
|
|
@ -325,28 +328,93 @@ fn get_extra_clang_args_for_bindgen() -> Vec<String> {
|
||||||
params
|
params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ensure_patches_applied() -> io::Result<()> {
|
||||||
|
let mut lock_file = LockFile::open(&PathBuf::from(BORING_SSL_PATH).join(".patch_lock"))?;
|
||||||
|
|
||||||
|
lock_file.lock()?;
|
||||||
|
|
||||||
|
let mut cmd = Command::new("git");
|
||||||
|
|
||||||
|
cmd.args(["reset", "--hard"])
|
||||||
|
.current_dir(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(BORING_SSL_PATH));
|
||||||
|
|
||||||
|
run_command(&mut cmd)?;
|
||||||
|
|
||||||
|
if cfg!(feature = "post-quantum") {
|
||||||
|
println!("cargo:warning=applying post quantum crypto patch to boringssl");
|
||||||
|
run_apply_patch_script("scripts/apply_pq_patch.sh", "")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg!(feature = "rpk") {
|
||||||
|
println!("cargo:warning=applying RPK patch to boringssl");
|
||||||
|
run_apply_patch_script("scripts/apply_rpk_patch.sh", "src")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_command(command: &mut Command) -> io::Result<()> {
|
||||||
|
let exit_status = command.spawn()?.wait()?;
|
||||||
|
|
||||||
|
if !exit_status.success() {
|
||||||
|
let err = match exit_status.code() {
|
||||||
|
Some(code) => format!("{:?} exited with status: {}", command, code),
|
||||||
|
None => format!("{:?} was terminated by signal", command),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Err(io::Error::new(io::ErrorKind::Other, err));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_apply_patch_script(
|
||||||
|
script_path: impl AsRef<Path>,
|
||||||
|
from_dir: impl AsRef<Path>,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
|
||||||
|
let src_path = manifest_dir
|
||||||
|
.join(BORING_SSL_PATH)
|
||||||
|
.join(from_dir)
|
||||||
|
.canonicalize()?;
|
||||||
|
|
||||||
|
let cmd_path = manifest_dir.join(script_path).canonicalize()?;
|
||||||
|
|
||||||
|
let mut cmd = Command::new(cmd_path);
|
||||||
|
cmd.current_dir(src_path);
|
||||||
|
run_command(&mut cmd)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
use std::env;
|
|
||||||
|
|
||||||
println!("cargo:rerun-if-env-changed=BORING_BSSL_PATH");
|
println!("cargo:rerun-if-env-changed=BORING_BSSL_PATH");
|
||||||
let bssl_dir = std::env::var("BORING_BSSL_PATH").unwrap_or_else(|_| {
|
|
||||||
if !Path::new(BORING_SSL_PATH).join("CMakeLists.txt").exists() {
|
|
||||||
println!("cargo:warning=fetching boringssl git submodule");
|
|
||||||
// fetch the boringssl submodule
|
|
||||||
let status = Command::new("git")
|
|
||||||
.args([
|
|
||||||
"submodule",
|
|
||||||
"update",
|
|
||||||
"--init",
|
|
||||||
"--recursive",
|
|
||||||
BORING_SSL_PATH,
|
|
||||||
])
|
|
||||||
.status();
|
|
||||||
if !status.map_or(false, |status| status.success()) {
|
|
||||||
panic!("failed to fetch submodule - consider running `git submodule update --init --recursive deps/boringssl` yourself");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#[cfg(all(feature = "fips", feature = "rpk"))]
|
||||||
|
compile_error!("`fips` and `rpk` features are mutually exclusive");
|
||||||
|
|
||||||
|
if !Path::new(BORING_SSL_PATH).join("CMakeLists.txt").exists() {
|
||||||
|
println!("cargo:warning=fetching boringssl git submodule");
|
||||||
|
// fetch the boringssl submodule
|
||||||
|
let status = Command::new("git")
|
||||||
|
.args([
|
||||||
|
"submodule",
|
||||||
|
"update",
|
||||||
|
"--init",
|
||||||
|
"--recursive",
|
||||||
|
BORING_SSL_PATH,
|
||||||
|
])
|
||||||
|
.status();
|
||||||
|
|
||||||
|
if !status.map_or(false, |status| status.success()) {
|
||||||
|
panic!("failed to fetch submodule - consider running `git submodule update --init --recursive deps/boringssl` yourself");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_patches_applied().unwrap();
|
||||||
|
|
||||||
|
let bssl_dir = std::env::var("BORING_BSSL_PATH").unwrap_or_else(|_| {
|
||||||
let mut cfg = get_boringssl_cmake_config();
|
let mut cfg = get_boringssl_cmake_config();
|
||||||
|
|
||||||
if cfg!(feature = "fuzzing") {
|
if cfg!(feature = "fuzzing") {
|
||||||
|
|
@ -385,12 +453,6 @@ fn main() {
|
||||||
println!("cargo:rustc-link-lib=static=crypto");
|
println!("cargo:rustc-link-lib=static=crypto");
|
||||||
println!("cargo:rustc-link-lib=static=ssl");
|
println!("cargo:rustc-link-lib=static=ssl");
|
||||||
|
|
||||||
// MacOS: Allow cdylib to link with undefined symbols
|
|
||||||
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
|
|
||||||
if target_os == "macos" {
|
|
||||||
println!("cargo:rustc-cdylib-link-arg=-Wl,-undefined,dynamic_lookup");
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("cargo:rerun-if-env-changed=BORING_BSSL_INCLUDE_PATH");
|
println!("cargo:rerun-if-env-changed=BORING_BSSL_INCLUDE_PATH");
|
||||||
let include_path = std::env::var("BORING_BSSL_INCLUDE_PATH").unwrap_or_else(|_| {
|
let include_path = std::env::var("BORING_BSSL_INCLUDE_PATH").unwrap_or_else(|_| {
|
||||||
if cfg!(feature = "fips") {
|
if cfg!(feature = "fips") {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,84 @@
|
||||||
|
--- google_boringssl/include/openssl/ssl.h 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/include/openssl/ssl.h 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -138,6 +138,25 @@
|
||||||
|
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
|
||||||
|
* OTHERWISE.
|
||||||
|
*/
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_SSL_H
|
||||||
|
#define OPENSSL_HEADER_SSL_H
|
||||||
|
@@ -1102,6 +1121,16 @@
|
||||||
|
SSL_CTX *ctx, CRYPTO_BUFFER *const *certs, size_t num_certs,
|
||||||
|
EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method);
|
||||||
|
|
||||||
|
+// SSL_CTX_set_nullchain_and_key sets the private key for a
|
||||||
|
+// TLS client or server. Reference to the given |EVP_PKEY|
|
||||||
|
+// object is added as needed. Exactly one of |privkey| or |privkey_method|
|
||||||
|
+// may be non-NULL. Returns one on success and zero on error.
|
||||||
|
+// Note the lack of a corresponding public-key certificate.
|
||||||
|
+// See SSL_CTX_set_server_raw_public_key_certificate.
|
||||||
|
+OPENSSL_EXPORT int SSL_CTX_set_nullchain_and_key(
|
||||||
|
+ SSL_CTX *ctx,
|
||||||
|
+ EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method);
|
||||||
|
+
|
||||||
|
// SSL_set_chain_and_key sets the certificate chain and private key for a TLS
|
||||||
|
// client or server. References to the given |CRYPTO_BUFFER| and |EVP_PKEY|
|
||||||
|
// objects are added as needed. Exactly one of |privkey| or |privkey_method|
|
||||||
|
@@ -1110,6 +1139,16 @@
|
||||||
|
SSL *ssl, CRYPTO_BUFFER *const *certs, size_t num_certs, EVP_PKEY *privkey,
|
||||||
|
const SSL_PRIVATE_KEY_METHOD *privkey_method);
|
||||||
|
|
||||||
|
+// SSL_set_nullchain_and_key sets the private key for a TLS
|
||||||
|
+// client or server. Reference to the given |EVP_PKEY|
|
||||||
|
+// object is added as needed. Exactly one of |privkey| or |privkey_method|
|
||||||
|
+// may be non-NULL. Returns one on success and zero on error.
|
||||||
|
+// Note the lack of a corresponding public-key certificate.
|
||||||
|
+// See SSL_set_server_raw_public_key_certificate.
|
||||||
|
+OPENSSL_EXPORT int SSL_set_nullchain_and_key(
|
||||||
|
+ SSL *ssl, EVP_PKEY *privkey,
|
||||||
|
+ const SSL_PRIVATE_KEY_METHOD *privkey_method);
|
||||||
|
+
|
||||||
|
// SSL_CTX_get0_chain returns the list of |CRYPTO_BUFFER|s that were set by
|
||||||
|
// |SSL_CTX_set_chain_and_key|. Reference counts are not incremented by this
|
||||||
|
// call. The return value may be |NULL| if no chain has been set.
|
||||||
|
@@ -2821,6 +2860,21 @@
|
||||||
|
OPENSSL_EXPORT int SSL_has_application_settings(const SSL *ssl);
|
||||||
|
|
||||||
|
|
||||||
|
+// Server Certificate Type.
|
||||||
|
+
|
||||||
|
+#define TLSEXT_CERTIFICATETYPE_X509 0
|
||||||
|
+#define TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY 2
|
||||||
|
+
|
||||||
|
+OPENSSL_EXPORT int SSL_CTX_set_server_raw_public_key_certificate(
|
||||||
|
+ SSL_CTX *ctx, const uint8_t *raw_public_key, unsigned raw_public_key_len);
|
||||||
|
+
|
||||||
|
+OPENSSL_EXPORT int SSL_CTX_has_server_raw_public_key_certificate(SSL_CTX *ctx);
|
||||||
|
+
|
||||||
|
+OPENSSL_EXPORT int SSL_set_server_raw_public_key_certificate(
|
||||||
|
+ SSL *ssl, const uint8_t *raw_public_key, unsigned raw_public_key_len);
|
||||||
|
+
|
||||||
|
+OPENSSL_EXPORT int SSL_has_server_raw_public_key_certificate(SSL *ssl);
|
||||||
|
+
|
||||||
|
// Certificate compression.
|
||||||
|
//
|
||||||
|
// Certificates in TLS 1.3 can be compressed (RFC 8879). BoringSSL supports this
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
--- google_boringssl/include/openssl/tls1.h 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/include/openssl/tls1.h 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -146,6 +146,25 @@
|
||||||
|
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
|
||||||
|
* OTHERWISE.
|
||||||
|
*/
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_TLS1_H
|
||||||
|
#define OPENSSL_HEADER_TLS1_H
|
||||||
|
@@ -197,6 +216,9 @@
|
||||||
|
// ExtensionType value from RFC 7301
|
||||||
|
#define TLSEXT_TYPE_application_layer_protocol_negotiation 16
|
||||||
|
|
||||||
|
+// ExtensionType value from RFC 7250
|
||||||
|
+#define TLSEXT_TYPE_server_certificate_type 20
|
||||||
|
+
|
||||||
|
// ExtensionType value from RFC 7685
|
||||||
|
#define TLSEXT_TYPE_padding 21
|
||||||
|
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
--- google_boringssl/ssl/extensions.cc 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/ssl/extensions.cc 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -105,6 +105,25 @@
|
||||||
|
* This product includes cryptographic software written by Eric Young
|
||||||
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||||
|
* Hudson (tjh@cryptsoft.com). */
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
@@ -3234,6 +3253,146 @@
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+// Server Certificate Type
|
||||||
|
+
|
||||||
|
+static bool ext_server_certificate_type_add_clienthello(const SSL_HANDSHAKE *hs,
|
||||||
|
+ CBB *out,
|
||||||
|
+ CBB *out_compressible,
|
||||||
|
+ ssl_client_hello_type_t type) {
|
||||||
|
+
|
||||||
|
+ if (hs->max_version <= TLS1_2_VERSION) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (hs->config->server_certificate_type_list.empty()) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ CBB contents, server_certificate_types;
|
||||||
|
+ if (!CBB_add_u16(out, TLSEXT_TYPE_server_certificate_type) ||
|
||||||
|
+ !CBB_add_u16_length_prefixed(out, &contents) ||
|
||||||
|
+ !CBB_add_u8_length_prefixed(&contents, &server_certificate_types) ||
|
||||||
|
+ !CBB_add_bytes(&server_certificate_types,
|
||||||
|
+ hs->config->server_certificate_type_list.data(),
|
||||||
|
+ hs->config->server_certificate_type_list.size()) ||
|
||||||
|
+ !CBB_flush(out)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool ssl_is_certificate_type_allowed(CBS *certificate_type_list,
|
||||||
|
+ uint8_t certificate_type)
|
||||||
|
+{
|
||||||
|
+ uint8_t supported_certificate_type;
|
||||||
|
+ while (CBS_len(certificate_type_list) > 0) {
|
||||||
|
+ if (!CBS_get_u8(certificate_type_list,
|
||||||
|
+ &supported_certificate_type)) {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (supported_certificate_type != certificate_type) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool ext_server_certificate_type_parse_serverhello(SSL_HANDSHAKE *hs,
|
||||||
|
+ uint8_t *out_alert,
|
||||||
|
+ CBS *content)
|
||||||
|
+{
|
||||||
|
+ if (hs->max_version <= TLS1_2_VERSION ||
|
||||||
|
+ hs->config->server_certificate_type_list.empty()) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Strict
|
||||||
|
+ if (!content) {
|
||||||
|
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||||
|
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ CBS certificate_type_list =
|
||||||
|
+ MakeConstSpan(hs->config->server_certificate_type_list);
|
||||||
|
+
|
||||||
|
+ uint8_t certificate_type;
|
||||||
|
+ if (CBS_get_u8(content, &certificate_type) &&
|
||||||
|
+ ssl_is_certificate_type_allowed(&certificate_type_list,
|
||||||
|
+ certificate_type)) {
|
||||||
|
+ hs->server_certificate_type = certificate_type;
|
||||||
|
+ hs->server_certificate_type_negotiated = 1;
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||||
|
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool ext_server_certificate_type_parse_clienthello(SSL_HANDSHAKE *hs,
|
||||||
|
+ uint8_t *out_alert,
|
||||||
|
+ CBS *content)
|
||||||
|
+{
|
||||||
|
+ if (!content) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (hs->max_version <= TLS1_2_VERSION ||
|
||||||
|
+ hs->config->server_certificate_type_list.empty()) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ CBS certificate_type_list =
|
||||||
|
+ MakeConstSpan(hs->config->server_certificate_type_list);
|
||||||
|
+
|
||||||
|
+ CBS type_list;
|
||||||
|
+ if (!CBS_get_u8_length_prefixed(content, &type_list)) {
|
||||||
|
+ type_list.len = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ uint8_t type;
|
||||||
|
+ while(CBS_len(&type_list) > 0) {
|
||||||
|
+ if (!CBS_get_u8(&type_list, &type)) {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!ssl_is_certificate_type_allowed(&certificate_type_list, type)) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hs->server_certificate_type = type;
|
||||||
|
+ hs->server_certificate_type_negotiated = 1;
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool ext_server_certificate_type_add_serverhello(SSL_HANDSHAKE *hs,
|
||||||
|
+ CBB *out)
|
||||||
|
+{
|
||||||
|
+ if (!hs->server_certificate_type_negotiated) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ CBB contents;
|
||||||
|
+ if (!CBB_add_u16(out, TLSEXT_TYPE_server_certificate_type) ||
|
||||||
|
+ !CBB_add_u16_length_prefixed(out, &contents) ||
|
||||||
|
+ !CBB_add_u8(&contents, hs->server_certificate_type) ||
|
||||||
|
+ !CBB_flush(out)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// kExtensions contains all the supported extensions.
|
||||||
|
static const struct tls_extension kExtensions[] = {
|
||||||
|
{
|
||||||
|
@@ -3447,6 +3604,13 @@
|
||||||
|
ignore_parse_clienthello,
|
||||||
|
ext_alps_add_serverhello,
|
||||||
|
},
|
||||||
|
+ {
|
||||||
|
+ TLSEXT_TYPE_server_certificate_type,
|
||||||
|
+ ext_server_certificate_type_add_clienthello,
|
||||||
|
+ ext_server_certificate_type_parse_serverhello,
|
||||||
|
+ ext_server_certificate_type_parse_clienthello,
|
||||||
|
+ ext_server_certificate_type_add_serverhello,
|
||||||
|
+ },
|
||||||
|
};
|
||||||
|
|
||||||
|
#define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
--- google_boringssl/ssl/handshake.cc 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/ssl/handshake.cc 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -109,6 +109,25 @@
|
||||||
|
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||||
|
* ECC cipher suite support in OpenSSL originally developed by
|
||||||
|
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
@@ -149,6 +168,7 @@
|
||||||
|
cert_compression_negotiated(false),
|
||||||
|
apply_jdk11_workaround(false),
|
||||||
|
can_release_private_key(false),
|
||||||
|
+ server_certificate_type_negotiated(false),
|
||||||
|
channel_id_negotiated(false) {
|
||||||
|
assert(ssl);
|
||||||
|
|
||||||
|
@@ -333,7 +353,21 @@
|
||||||
|
|
||||||
|
uint8_t alert = SSL_AD_CERTIFICATE_UNKNOWN;
|
||||||
|
enum ssl_verify_result_t ret;
|
||||||
|
- if (hs->config->custom_verify_callback != nullptr) {
|
||||||
|
+ if (hs->server_certificate_type_negotiated &&
|
||||||
|
+ hs->server_certificate_type == TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY) {
|
||||||
|
+ ret = ssl_verify_invalid;
|
||||||
|
+ EVP_PKEY *peer_pubkey = hs->peer_pubkey.get();
|
||||||
|
+ CBS spki = MakeConstSpan(ssl->config->server_raw_public_key_certificate);
|
||||||
|
+ EVP_PKEY *pubkey = EVP_parse_public_key(&spki);
|
||||||
|
+ if (!pubkey) {
|
||||||
|
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
|
||||||
|
+ alert = SSL_AD_INTERNAL_ERROR;
|
||||||
|
+ } else if (EVP_PKEY_cmp(peer_pubkey, pubkey) == 1 /* Equal */) {
|
||||||
|
+ ret = ssl_verify_ok;
|
||||||
|
+ } else {
|
||||||
|
+ alert = SSL_AD_BAD_CERTIFICATE;
|
||||||
|
+ }
|
||||||
|
+ } else if (hs->config->custom_verify_callback != nullptr) {
|
||||||
|
ret = hs->config->custom_verify_callback(ssl, &alert);
|
||||||
|
switch (ret) {
|
||||||
|
case ssl_verify_ok:
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
--- google_boringssl/ssl/internal.h 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/ssl/internal.h 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -138,6 +138,25 @@
|
||||||
|
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
|
||||||
|
* OTHERWISE.
|
||||||
|
*/
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_SSL_INTERNAL_H
|
||||||
|
#define OPENSSL_HEADER_SSL_INTERNAL_H
|
||||||
|
@@ -1279,6 +1298,8 @@
|
||||||
|
// configured.
|
||||||
|
bool ssl_has_certificate(const SSL_HANDSHAKE *hs);
|
||||||
|
|
||||||
|
+bool ssl_has_raw_public_key_certificate(const SSL_HANDSHAKE *hs);
|
||||||
|
+
|
||||||
|
// ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
|
||||||
|
// by a TLS Certificate message. On success, it advances |cbs| and returns
|
||||||
|
// true. Otherwise, it returns false and sets |*out_alert| to an alert to send
|
||||||
|
@@ -1687,6 +1708,8 @@
|
||||||
|
// |cert_compression_negotiated| is true.
|
||||||
|
uint16_t cert_compression_alg_id;
|
||||||
|
|
||||||
|
+ uint8_t server_certificate_type;
|
||||||
|
+
|
||||||
|
// ech_hpke_ctx is the HPKE context used in ECH. On the server, it is
|
||||||
|
// initialized if |ech_status| is |ssl_ech_accepted|. On the client, it is
|
||||||
|
// initialized if |selected_ech_config| is not nullptr.
|
||||||
|
@@ -1817,6 +1840,8 @@
|
||||||
|
// cert_compression_negotiated is true iff |cert_compression_alg_id| is valid.
|
||||||
|
bool cert_compression_negotiated : 1;
|
||||||
|
|
||||||
|
+ bool server_certificate_type_negotiated : 1;
|
||||||
|
+
|
||||||
|
// apply_jdk11_workaround is true if the peer is probably a JDK 11 client
|
||||||
|
// which implemented TLS 1.3 incorrectly.
|
||||||
|
bool apply_jdk11_workaround : 1;
|
||||||
|
@@ -2731,6 +2756,9 @@
|
||||||
|
// along with their corresponding ALPS values.
|
||||||
|
GrowableArray<ALPSConfig> alps_configs;
|
||||||
|
|
||||||
|
+ Array<uint8_t> server_certificate_type_list;
|
||||||
|
+ Array<uint8_t> server_raw_public_key_certificate;
|
||||||
|
+
|
||||||
|
// Contains the QUIC transport params that this endpoint will send.
|
||||||
|
Array<uint8_t> quic_transport_params;
|
||||||
|
|
||||||
|
@@ -3306,6 +3334,9 @@
|
||||||
|
// format.
|
||||||
|
bssl::Array<uint8_t> alpn_client_proto_list;
|
||||||
|
|
||||||
|
+ bssl::Array<uint8_t> server_certificate_type_list;
|
||||||
|
+ bssl::Array<uint8_t> server_raw_public_key_certificate;
|
||||||
|
+
|
||||||
|
// SRTP profiles we are willing to do from RFC 5764
|
||||||
|
bssl::UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> srtp_profiles;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
--- google_boringssl/ssl/ssl_cert.cc 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/ssl/ssl_cert.cc 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -111,6 +111,25 @@
|
||||||
|
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||||
|
* ECC cipher suite support in OpenSSL originally developed by
|
||||||
|
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
@@ -302,6 +321,25 @@
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int cert_set_key(
|
||||||
|
+ CERT *cert,
|
||||||
|
+ EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method) {
|
||||||
|
+ if (privkey == NULL && privkey_method == NULL) {
|
||||||
|
+ OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (privkey != NULL && privkey_method != NULL) {
|
||||||
|
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ cert->privatekey = UpRef(privkey);
|
||||||
|
+ cert->key_method = privkey_method;
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool ssl_set_cert(CERT *cert, UniquePtr<CRYPTO_BUFFER> buffer) {
|
||||||
|
switch (check_leaf_cert_and_privkey(buffer.get(), cert->privatekey.get())) {
|
||||||
|
case leaf_cert_and_privkey_error:
|
||||||
|
@@ -343,6 +381,12 @@
|
||||||
|
ssl_has_private_key(hs);
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool ssl_has_raw_public_key_certificate(const SSL_HANDSHAKE *hs) {
|
||||||
|
+ return hs->server_certificate_type_negotiated &&
|
||||||
|
+ hs->server_certificate_type == TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY &&
|
||||||
|
+ ssl_has_private_key(hs);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool ssl_parse_cert_chain(uint8_t *out_alert,
|
||||||
|
UniquePtr<STACK_OF(CRYPTO_BUFFER)> *out_chain,
|
||||||
|
UniquePtr<EVP_PKEY> *out_pubkey,
|
||||||
|
@@ -727,11 +771,20 @@
|
||||||
|
|
||||||
|
bool ssl_on_certificate_selected(SSL_HANDSHAKE *hs) {
|
||||||
|
SSL *const ssl = hs->ssl;
|
||||||
|
- if (!ssl_has_certificate(hs)) {
|
||||||
|
+ if (!ssl_has_certificate(hs) &&
|
||||||
|
+ !ssl_has_raw_public_key_certificate(hs)) {
|
||||||
|
// Nothing to do.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (ssl_has_raw_public_key_certificate(hs)) {
|
||||||
|
+ CBS spki = MakeConstSpan(
|
||||||
|
+ ssl->config->server_raw_public_key_certificate.data(),
|
||||||
|
+ ssl->config->server_raw_public_key_certificate.size());
|
||||||
|
+ hs->local_pubkey = UniquePtr<EVP_PKEY>(EVP_parse_public_key(&spki));
|
||||||
|
+ return hs->local_pubkey != NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(hs)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@@ -886,6 +939,15 @@
|
||||||
|
privkey, privkey_method);
|
||||||
|
}
|
||||||
|
|
||||||
|
+int SSL_set_nullchain_and_key(SSL *ssl,
|
||||||
|
+ EVP_PKEY *privkey,
|
||||||
|
+ const SSL_PRIVATE_KEY_METHOD *privkey_method) {
|
||||||
|
+ if (!ssl->config) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ return cert_set_key(ssl->config->cert.get(), privkey, privkey_method);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs,
|
||||||
|
size_t num_certs, EVP_PKEY *privkey,
|
||||||
|
const SSL_PRIVATE_KEY_METHOD *privkey_method) {
|
||||||
|
@@ -893,6 +955,12 @@
|
||||||
|
privkey_method);
|
||||||
|
}
|
||||||
|
|
||||||
|
+int SSL_CTX_set_nullchain_and_key(SSL_CTX *ctx,
|
||||||
|
+ EVP_PKEY *privkey,
|
||||||
|
+ const SSL_PRIVATE_KEY_METHOD *privkey_method) {
|
||||||
|
+ return cert_set_key(ctx->cert.get(), privkey, privkey_method);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
const STACK_OF(CRYPTO_BUFFER)* SSL_CTX_get0_chain(const SSL_CTX *ctx) {
|
||||||
|
return ctx->cert->chain.get();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
--- google_boringssl/ssl/ssl_lib.cc 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/ssl/ssl_lib.cc 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -137,6 +137,25 @@
|
||||||
|
* SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
|
||||||
|
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
|
||||||
|
* OTHERWISE. */
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
@@ -712,6 +731,11 @@
|
||||||
|
ssl->config->handoff = ctx->handoff;
|
||||||
|
ssl->quic_method = ctx->quic_method;
|
||||||
|
|
||||||
|
+ ssl->config->server_certificate_type_list.CopyFrom(
|
||||||
|
+ ctx->server_certificate_type_list);
|
||||||
|
+ ssl->config->server_raw_public_key_certificate.CopyFrom(
|
||||||
|
+ ctx->server_raw_public_key_certificate);
|
||||||
|
+
|
||||||
|
if (!ssl->method->ssl_new(ssl.get()) ||
|
||||||
|
!ssl->ctx->x509_method->ssl_new(ssl->s3->hs.get())) {
|
||||||
|
return nullptr;
|
||||||
|
@@ -3124,5 +3148,52 @@
|
||||||
|
ctx->legacy_ocsp_callback_arg = arg;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+int SSL_CTX_set_server_raw_public_key_certificate(SSL_CTX *ctx,
|
||||||
|
+ const uint8_t *raw_public_key, unsigned raw_public_key_len) {
|
||||||
|
+ if (!ctx->server_raw_public_key_certificate.CopyFrom(
|
||||||
|
+ MakeConstSpan(raw_public_key, raw_public_key_len))) {
|
||||||
|
+ return 0; /* Failure */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!ctx->server_certificate_type_list.Init(1)) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ ctx->server_certificate_type_list[0] = TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY;
|
||||||
|
+
|
||||||
|
+ return 1; /* Success */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int SSL_CTX_has_server_raw_public_key_certificate(SSL_CTX *ctx) {
|
||||||
|
+ return !ctx->server_raw_public_key_certificate.empty();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int SSL_set_server_raw_public_key_certificate(SSL *ssl,
|
||||||
|
+ const uint8_t *raw_public_key, unsigned raw_public_key_len) {
|
||||||
|
+ if (!ssl->config) {
|
||||||
|
+ return 0; /* Failure */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!ssl->config->server_raw_public_key_certificate.CopyFrom(
|
||||||
|
+ MakeConstSpan(raw_public_key, raw_public_key_len))) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!ssl->config->server_certificate_type_list.Init(1)) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ ssl->config->server_certificate_type_list[0] =
|
||||||
|
+ TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY;
|
||||||
|
+
|
||||||
|
+ return 1; /* Success */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int SSL_has_server_raw_public_key_certificate(SSL *ssl) {
|
||||||
|
+ if (!ssl->config) {
|
||||||
|
+ return 0; /* Failure */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return !ssl->config->server_raw_public_key_certificate.empty();
|
||||||
|
+}
|
||||||
|
|
||||||
|
namespace fips202205 {
|
||||||
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
--- google_boringssl/ssl/tls13_both.cc 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/ssl/tls13_both.cc 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -11,6 +11,25 @@
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
@@ -203,7 +222,16 @@
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (sk_CRYPTO_BUFFER_num(certs.get()) == 0) {
|
||||||
|
+ if (hs->server_certificate_type_negotiated &&
|
||||||
|
+ hs->server_certificate_type == TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY) {
|
||||||
|
+ pkey = UniquePtr<EVP_PKEY>(EVP_parse_public_key(&certificate));
|
||||||
|
+ if (!pkey) {
|
||||||
|
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||||
|
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (sk_CRYPTO_BUFFER_num(certs.get()) == 0) {
|
||||||
|
pkey = ssl_cert_parse_pubkey(&certificate);
|
||||||
|
if (!pkey) {
|
||||||
|
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||||
|
@@ -319,7 +347,10 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sk_CRYPTO_BUFFER_num(hs->new_session->certs.get()) == 0) {
|
||||||
|
- if (!allow_anonymous) {
|
||||||
|
+ if (!allow_anonymous &&
|
||||||
|
+ !(hs->server_certificate_type_negotiated &&
|
||||||
|
+ hs->server_certificate_type ==
|
||||||
|
+ TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY)) {
|
||||||
|
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
|
||||||
|
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
|
||||||
|
return false;
|
||||||
|
@@ -436,6 +467,20 @@
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (hs->server_certificate_type_negotiated &&
|
||||||
|
+ hs->server_certificate_type == TLSEXT_CERTIFICATETYPE_RAW_PUBLIC_KEY) {
|
||||||
|
+ CBB leaf, extensions;
|
||||||
|
+ if (!CBB_add_u24_length_prefixed(&certificate_list, &leaf) ||
|
||||||
|
+ !CBB_add_bytes(&leaf,
|
||||||
|
+ ssl->config->server_raw_public_key_certificate.data(),
|
||||||
|
+ ssl->config->server_raw_public_key_certificate.size()) ||
|
||||||
|
+ !CBB_add_u16_length_prefixed(&certificate_list, &extensions)) {
|
||||||
|
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ return ssl_add_message_cbb(ssl, cbb.get());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (!ssl_has_certificate(hs)) {
|
||||||
|
return ssl_add_message_cbb(ssl, cbb.get());
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
--- google_boringssl/ssl/tls13_server.cc 2021-02-03 18:29:04.000000000 -0800
|
||||||
|
+++ boringssl/ssl/tls13_server.cc 2021-02-03 20:24:49.000000000 -0800
|
||||||
|
@@ -11,6 +11,25 @@
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||||
|
+/* ====================================================================
|
||||||
|
+ * Copyright 2020 Apple Inc.
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
+ * copy of this software and associated documentation files (the “Software”),
|
||||||
|
+ * to deal in the Software without restriction, including without limitation
|
||||||
|
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
+ * and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
+ * the Software is furnished to do so, subject to the following conditions:
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
+ * IN THE SOFTWARE.
|
||||||
|
+ */
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
@@ -759,7 +778,8 @@
|
||||||
|
|
||||||
|
// Send the server Certificate message, if necessary.
|
||||||
|
if (!ssl->s3->session_reused) {
|
||||||
|
- if (!ssl_has_certificate(hs)) {
|
||||||
|
+ if (!ssl_has_certificate(hs) &&
|
||||||
|
+ !ssl_has_raw_public_key_certificate(hs)) {
|
||||||
|
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
|
||||||
|
return ssl_hs_error;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
git apply -v --whitespace=fix ../../patches/boring-pq.patch
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
git apply -v --whitespace=fix ../../../patches/rpk-patch/include/*/*.patch ../../../patches/rpk-patch/ssl/*.patch
|
||||||
|
|
@ -21,6 +21,16 @@ mod generated {
|
||||||
}
|
}
|
||||||
pub use generated::*;
|
pub use generated::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "post-quantum")]
|
||||||
|
mod ensure_post_quantum_crypto_patch_applied {
|
||||||
|
use super::KYBER512_encap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
mod ensure_raw_public_key_patch_applied {
|
||||||
|
use super::SSL_CTX_set_server_raw_public_key_certificate;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
pub type BN_ULONG = u64;
|
pub type BN_ULONG = u64;
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ documentation = "https://docs.rs/boring"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["crypto", "tls", "ssl", "dtls"]
|
keywords = ["crypto", "tls", "ssl", "dtls"]
|
||||||
categories = ["cryptography", "api-bindings"]
|
categories = ["cryptography", "api-bindings"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
|
|
@ -25,3 +25,9 @@ rusty-hook = "^0.11"
|
||||||
[features]
|
[features]
|
||||||
# Use a FIPS-validated version of boringssl.
|
# Use a FIPS-validated version of boringssl.
|
||||||
fips = ["boring-sys/fips"]
|
fips = ["boring-sys/fips"]
|
||||||
|
|
||||||
|
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
|
||||||
|
rpk = ["boring-sys/rpk"]
|
||||||
|
|
||||||
|
# Enables post-quantum crypto (https://blog.cloudflare.com/post-quantum-for-all/)
|
||||||
|
post-quantum = ["boring-sys/post-quantum"]
|
||||||
|
|
@ -20,9 +20,19 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
|
||||||
-----END DH PARAMETERS-----
|
-----END DH PARAMETERS-----
|
||||||
";
|
";
|
||||||
|
|
||||||
|
enum ContextType {
|
||||||
|
WithMethod(SslMethod),
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
Rpk,
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::inconsistent_digit_grouping)]
|
#[allow(clippy::inconsistent_digit_grouping)]
|
||||||
fn ctx(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
|
fn ctx(ty: ContextType) -> Result<SslContextBuilder, ErrorStack> {
|
||||||
let mut ctx = SslContextBuilder::new(method)?;
|
let mut ctx = match ty {
|
||||||
|
ContextType::WithMethod(method) => SslContextBuilder::new(method),
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
ContextType::Rpk => SslContextBuilder::new_rpk(),
|
||||||
|
}?;
|
||||||
|
|
||||||
let mut opts = SslOptions::ALL
|
let mut opts = SslOptions::ALL
|
||||||
| SslOptions::NO_COMPRESSION
|
| SslOptions::NO_COMPRESSION
|
||||||
|
|
@ -64,7 +74,7 @@ impl SslConnector {
|
||||||
///
|
///
|
||||||
/// The default configuration is subject to change, and is currently derived from Python.
|
/// The default configuration is subject to change, and is currently derived from Python.
|
||||||
pub fn builder(method: SslMethod) -> Result<SslConnectorBuilder, ErrorStack> {
|
pub fn builder(method: SslMethod) -> Result<SslConnectorBuilder, ErrorStack> {
|
||||||
let mut ctx = ctx(method)?;
|
let mut ctx = ctx(ContextType::WithMethod(method))?;
|
||||||
ctx.set_default_verify_paths()?;
|
ctx.set_default_verify_paths()?;
|
||||||
ctx.set_cipher_list(
|
ctx.set_cipher_list(
|
||||||
"DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK",
|
"DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK",
|
||||||
|
|
@ -74,6 +84,17 @@ impl SslConnector {
|
||||||
Ok(SslConnectorBuilder(ctx))
|
Ok(SslConnectorBuilder(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new builder for TLS connections with raw public key.
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
pub fn rpk_builder() -> Result<SslConnectorBuilder, ErrorStack> {
|
||||||
|
let mut ctx = ctx(ContextType::Rpk)?;
|
||||||
|
ctx.set_cipher_list(
|
||||||
|
"DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK",
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(SslConnectorBuilder(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
/// Initiates a client-side TLS session on a stream.
|
/// Initiates a client-side TLS session on a stream.
|
||||||
///
|
///
|
||||||
/// The domain is used for SNI and hostname verification.
|
/// The domain is used for SNI and hostname verification.
|
||||||
|
|
@ -179,7 +200,13 @@ impl ConnectConfiguration {
|
||||||
self.ssl.set_hostname(domain)?;
|
self.ssl.set_hostname(domain)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.verify_hostname {
|
#[cfg(feature = "rpk")]
|
||||||
|
let verify_hostname = !self.ssl.ssl_context().is_rpk() && self.verify_hostname;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "rpk"))]
|
||||||
|
let verify_hostname = self.verify_hostname;
|
||||||
|
|
||||||
|
if verify_hostname {
|
||||||
setup_verify_hostname(&mut self.ssl, domain)?;
|
setup_verify_hostname(&mut self.ssl, domain)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,6 +236,21 @@ impl DerefMut for ConnectConfiguration {
|
||||||
pub struct SslAcceptor(SslContext);
|
pub struct SslAcceptor(SslContext);
|
||||||
|
|
||||||
impl SslAcceptor {
|
impl SslAcceptor {
|
||||||
|
/// Creates a new builder configured to connect to clients that support Raw Public Keys.
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
pub fn rpk() -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||||
|
let mut ctx = ctx(ContextType::Rpk)?;
|
||||||
|
ctx.set_options(SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1);
|
||||||
|
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
||||||
|
ctx.set_tmp_dh(&dh)?;
|
||||||
|
ctx.set_cipher_list(
|
||||||
|
"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:\
|
||||||
|
ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
|
||||||
|
DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
|
||||||
|
)?;
|
||||||
|
Ok(SslAcceptorBuilder(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new builder configured to connect to non-legacy clients. This should generally be
|
/// Creates a new builder configured to connect to non-legacy clients. This should generally be
|
||||||
/// considered a reasonable default choice.
|
/// considered a reasonable default choice.
|
||||||
///
|
///
|
||||||
|
|
@ -217,7 +259,7 @@ impl SslAcceptor {
|
||||||
///
|
///
|
||||||
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||||
pub fn mozilla_intermediate_v5(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
pub fn mozilla_intermediate_v5(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||||
let mut ctx = ctx(method)?;
|
let mut ctx = ctx(ContextType::WithMethod(method))?;
|
||||||
ctx.set_options(SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1);
|
ctx.set_options(SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1);
|
||||||
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
||||||
ctx.set_tmp_dh(&dh)?;
|
ctx.set_tmp_dh(&dh)?;
|
||||||
|
|
@ -238,7 +280,7 @@ impl SslAcceptor {
|
||||||
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||||
// FIXME remove in next major version
|
// FIXME remove in next major version
|
||||||
pub fn mozilla_intermediate(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
pub fn mozilla_intermediate(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||||
let mut ctx = ctx(method)?;
|
let mut ctx = ctx(ContextType::WithMethod(method))?;
|
||||||
ctx.set_options(SslOptions::CIPHER_SERVER_PREFERENCE);
|
ctx.set_options(SslOptions::CIPHER_SERVER_PREFERENCE);
|
||||||
ctx.set_options(SslOptions::NO_TLSV1_3);
|
ctx.set_options(SslOptions::NO_TLSV1_3);
|
||||||
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
||||||
|
|
@ -264,7 +306,7 @@ impl SslAcceptor {
|
||||||
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||||
// FIXME remove in next major version
|
// FIXME remove in next major version
|
||||||
pub fn mozilla_modern(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
pub fn mozilla_modern(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||||
let mut ctx = ctx(method)?;
|
let mut ctx = ctx(ContextType::WithMethod(method))?;
|
||||||
ctx.set_options(
|
ctx.set_options(
|
||||||
SslOptions::CIPHER_SERVER_PREFERENCE | SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1,
|
SslOptions::CIPHER_SERVER_PREFERENCE | SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,12 @@ impl SslMethod {
|
||||||
unsafe { SslMethod(TLS_method()) }
|
unsafe { SslMethod(TLS_method()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Same as `tls`, but doesn't create X509 for certificates.
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
pub fn tls_with_buffer() -> SslMethod {
|
||||||
|
unsafe { SslMethod(ffi::TLS_with_buffers_method()) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Support all versions of the DTLS protocol.
|
/// Support all versions of the DTLS protocol.
|
||||||
///
|
///
|
||||||
/// This corresponds to `DTLS_method` on OpenSSL 1.1.0 and `DTLSv1_method`
|
/// This corresponds to `DTLS_method` on OpenSSL 1.1.0 and `DTLSv1_method`
|
||||||
|
|
@ -413,6 +419,11 @@ lazy_static! {
|
||||||
static ref SESSION_CTX_INDEX: Index<Ssl, SslContext> = Ssl::new_ex_index().unwrap();
|
static ref SESSION_CTX_INDEX: Index<Ssl, SslContext> = Ssl::new_ex_index().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
lazy_static! {
|
||||||
|
static ref RPK_FLAG_INDEX: Index<SslContext, bool> = SslContext::new_ex_index().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn free_data_box<T>(
|
unsafe extern "C" fn free_data_box<T>(
|
||||||
_parent: *mut c_void,
|
_parent: *mut c_void,
|
||||||
ptr: *mut c_void,
|
ptr: *mut c_void,
|
||||||
|
|
@ -621,6 +632,15 @@ impl SslCurve {
|
||||||
pub const SECP521R1: SslCurve = SslCurve(ffi::NID_secp521r1);
|
pub const SECP521R1: SslCurve = SslCurve(ffi::NID_secp521r1);
|
||||||
|
|
||||||
pub const X25519: SslCurve = SslCurve(ffi::NID_X25519);
|
pub const X25519: SslCurve = SslCurve(ffi::NID_X25519);
|
||||||
|
|
||||||
|
#[cfg(feature = "post-quantum")]
|
||||||
|
pub const X25519_KYBER512_DRAFT00: SslCurve = SslCurve(ffi::NID_X25519Kyber512Draft00);
|
||||||
|
|
||||||
|
#[cfg(feature = "post-quantum")]
|
||||||
|
pub const P256_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::NID_P256Kyber768Draft00);
|
||||||
|
|
||||||
|
#[cfg(feature = "post-quantum")]
|
||||||
|
pub const X25519_KYBER768_DRAFT00: SslCurve = SslCurve(ffi::NID_X25519Kyber768Draft00);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A standard implementation of protocol selection for Application Layer Protocol Negotiation
|
/// A standard implementation of protocol selection for Application Layer Protocol Negotiation
|
||||||
|
|
@ -656,8 +676,65 @@ pub fn select_next_proto<'a>(server: &[u8], client: &'a [u8]) -> Option<&'a [u8]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
extern "C" fn rpk_verify_failure_callback(
|
||||||
|
_ssl: *mut ffi::SSL,
|
||||||
|
_out_alert: *mut u8,
|
||||||
|
) -> ffi::ssl_verify_result_t {
|
||||||
|
// Always verify the peer.
|
||||||
|
ffi::ssl_verify_result_t::ssl_verify_invalid
|
||||||
|
}
|
||||||
|
|
||||||
/// A builder for `SslContext`s.
|
/// A builder for `SslContext`s.
|
||||||
pub struct SslContextBuilder(SslContext);
|
pub struct SslContextBuilder {
|
||||||
|
ctx: SslContext,
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
is_rpk: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
impl SslContextBuilder {
|
||||||
|
/// Creates a new `SslContextBuilder` to be used with Raw Public Key.
|
||||||
|
///
|
||||||
|
/// This corresponds to [`SSL_CTX_new`].
|
||||||
|
///
|
||||||
|
/// [`SSL_CTX_new`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_new.html
|
||||||
|
pub fn new_rpk() -> Result<SslContextBuilder, ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
init();
|
||||||
|
let ctx = cvt_p(ffi::SSL_CTX_new(SslMethod::tls_with_buffer().as_ptr()))?;
|
||||||
|
|
||||||
|
Ok(SslContextBuilder::from_ptr(ctx, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets raw public key certificate in DER format.
|
||||||
|
pub fn set_rpk_certificate(&mut self, cert: &[u8]) -> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt(ffi::SSL_CTX_set_server_raw_public_key_certificate(
|
||||||
|
self.as_ptr(),
|
||||||
|
cert.as_ptr(),
|
||||||
|
cert.len() as u32,
|
||||||
|
))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets RPK null chain private key.
|
||||||
|
pub fn set_null_chain_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
|
||||||
|
where
|
||||||
|
T: HasPrivate,
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
cvt(ffi::SSL_CTX_set_nullchain_and_key(
|
||||||
|
self.as_ptr(),
|
||||||
|
key.as_ptr(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SslContextBuilder {
|
impl SslContextBuilder {
|
||||||
/// Creates a new `SslContextBuilder`.
|
/// Creates a new `SslContextBuilder`.
|
||||||
|
|
@ -670,7 +747,15 @@ impl SslContextBuilder {
|
||||||
init();
|
init();
|
||||||
let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
|
let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
|
||||||
|
|
||||||
Ok(SslContextBuilder::from_ptr(ctx))
|
#[cfg(feature = "rpk")]
|
||||||
|
{
|
||||||
|
Ok(SslContextBuilder::from_ptr(ctx, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "rpk"))]
|
||||||
|
{
|
||||||
|
Ok(SslContextBuilder::from_ptr(ctx))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -679,13 +764,31 @@ impl SslContextBuilder {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The caller must ensure that the pointer is valid and uniquely owned by the builder.
|
/// The caller must ensure that the pointer is valid and uniquely owned by the builder.
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX, is_rpk: bool) -> SslContextBuilder {
|
||||||
|
let ctx = SslContext::from_ptr(ctx);
|
||||||
|
let mut builder = SslContextBuilder { ctx, is_rpk };
|
||||||
|
|
||||||
|
builder.set_ex_data(*RPK_FLAG_INDEX, is_rpk);
|
||||||
|
|
||||||
|
builder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The caller must ensure that the pointer is valid and uniquely owned by the builder.
|
||||||
|
#[cfg(not(feature = "rpk"))]
|
||||||
pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
|
pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
|
||||||
SslContextBuilder(SslContext::from_ptr(ctx))
|
SslContextBuilder {
|
||||||
|
ctx: SslContext::from_ptr(ctx),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a pointer to the raw OpenSSL value.
|
/// Returns a pointer to the raw OpenSSL value.
|
||||||
pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
|
pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
|
||||||
self.0.as_ptr()
|
self.ctx.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures the certificate verification method for new connections.
|
/// Configures the certificate verification method for new connections.
|
||||||
|
|
@ -694,6 +797,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_set_verify`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_verify.html
|
/// [`SSL_CTX_set_verify`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_verify.html
|
||||||
pub fn set_verify(&mut self, mode: SslVerifyMode) {
|
pub fn set_verify(&mut self, mode: SslVerifyMode) {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, None);
|
ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, None);
|
||||||
}
|
}
|
||||||
|
|
@ -713,6 +819,9 @@ impl SslContextBuilder {
|
||||||
where
|
where
|
||||||
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
|
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
|
||||||
{
|
{
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
|
self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
|
||||||
ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::<F>));
|
ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::<F>));
|
||||||
|
|
@ -757,6 +866,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_set_verify_depth`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_verify_depth.html
|
/// [`SSL_CTX_set_verify_depth`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_verify_depth.html
|
||||||
pub fn set_verify_depth(&mut self, depth: u32) {
|
pub fn set_verify_depth(&mut self, depth: u32) {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
|
ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
|
||||||
}
|
}
|
||||||
|
|
@ -768,6 +880,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_set0_verify_cert_store`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set0_verify_cert_store.html
|
/// [`SSL_CTX_set0_verify_cert_store`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set0_verify_cert_store.html
|
||||||
pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
|
pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = cert_store.as_ptr();
|
let ptr = cert_store.as_ptr();
|
||||||
cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
|
cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
|
||||||
|
|
@ -783,6 +898,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_set_cert_store`]: https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_cert_store.html
|
/// [`SSL_CTX_set_cert_store`]: https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_cert_store.html
|
||||||
pub fn set_cert_store(&mut self, cert_store: X509Store) {
|
pub fn set_cert_store(&mut self, cert_store: X509Store) {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
|
ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
|
||||||
mem::forget(cert_store);
|
mem::forget(cert_store);
|
||||||
|
|
@ -842,6 +960,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_set_default_verify_paths`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_default_verify_paths.html
|
/// [`SSL_CTX_set_default_verify_paths`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_default_verify_paths.html
|
||||||
pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
|
pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
|
unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -853,6 +974,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_load_verify_locations`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_load_verify_locations.html
|
/// [`SSL_CTX_load_verify_locations`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_load_verify_locations.html
|
||||||
pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
|
pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
|
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
cvt(ffi::SSL_CTX_load_verify_locations(
|
cvt(ffi::SSL_CTX_load_verify_locations(
|
||||||
|
|
@ -873,6 +997,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_set_client_CA_list`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_client_CA_list.html
|
/// [`SSL_CTX_set_client_CA_list`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_client_CA_list.html
|
||||||
pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
|
pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
|
ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
|
||||||
mem::forget(list);
|
mem::forget(list);
|
||||||
|
|
@ -886,6 +1013,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_add_client_CA`]: https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_client_CA_list.html
|
/// [`SSL_CTX_add_client_CA`]: https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_client_CA_list.html
|
||||||
pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
|
pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
|
unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -927,6 +1057,9 @@ impl SslContextBuilder {
|
||||||
file: P,
|
file: P,
|
||||||
file_type: SslFiletype,
|
file_type: SslFiletype,
|
||||||
) -> Result<(), ErrorStack> {
|
) -> Result<(), ErrorStack> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
|
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
cvt(ffi::SSL_CTX_use_certificate_file(
|
cvt(ffi::SSL_CTX_use_certificate_file(
|
||||||
|
|
@ -981,6 +1114,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_add_extra_chain_cert`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_add_extra_chain_cert.html
|
/// [`SSL_CTX_add_extra_chain_cert`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_add_extra_chain_cert.html
|
||||||
pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
|
pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
|
cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
|
||||||
mem::forget(cert);
|
mem::forget(cert);
|
||||||
|
|
@ -1261,6 +1397,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_get_cert_store`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_get_cert_store.html
|
/// [`SSL_CTX_get_cert_store`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_get_cert_store.html
|
||||||
pub fn cert_store(&self) -> &X509StoreBuilderRef {
|
pub fn cert_store(&self) -> &X509StoreBuilderRef {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
|
unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1270,6 +1409,9 @@ impl SslContextBuilder {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_get_cert_store`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_get_cert_store.html
|
/// [`SSL_CTX_get_cert_store`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_get_cert_store.html
|
||||||
pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
|
pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk, "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
|
unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1571,7 +1713,7 @@ impl SslContextBuilder {
|
||||||
|
|
||||||
/// Consumes the builder, returning a new `SslContext`.
|
/// Consumes the builder, returning a new `SslContext`.
|
||||||
pub fn build(self) -> SslContext {
|
pub fn build(self) -> SslContext {
|
||||||
self.0
|
self.ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1650,6 +1792,9 @@ impl SslContextRef {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_get0_certificate`]: https://www.openssl.org/docs/man1.1.0/ssl/ssl.html
|
/// [`SSL_CTX_get0_certificate`]: https://www.openssl.org/docs/man1.1.0/ssl/ssl.html
|
||||||
pub fn certificate(&self) -> Option<&X509Ref> {
|
pub fn certificate(&self) -> Option<&X509Ref> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk(), "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
|
let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
|
|
@ -1682,6 +1827,9 @@ impl SslContextRef {
|
||||||
///
|
///
|
||||||
/// [`SSL_CTX_get_cert_store`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_get_cert_store.html
|
/// [`SSL_CTX_get_cert_store`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_get_cert_store.html
|
||||||
pub fn cert_store(&self) -> &X509StoreRef {
|
pub fn cert_store(&self) -> &X509StoreRef {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk(), "This API is not supported for RPK");
|
||||||
|
|
||||||
unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
|
unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1764,9 +1912,18 @@ impl SslContextRef {
|
||||||
/// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
|
/// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
|
||||||
/// [`SSL_CTX_get_verify_mode`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_get_verify_mode.html
|
/// [`SSL_CTX_get_verify_mode`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_get_verify_mode.html
|
||||||
pub fn verify_mode(&self) -> SslVerifyMode {
|
pub fn verify_mode(&self) -> SslVerifyMode {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(!self.is_rpk(), "This API is not supported for RPK");
|
||||||
|
|
||||||
let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
|
let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
|
||||||
SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
|
SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if context was created for Raw Public Key verification
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
pub fn is_rpk(&self) -> bool {
|
||||||
|
self.ex_data(*RPK_FLAG_INDEX).copied().unwrap_or_default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "fips"))]
|
#[cfg(not(feature = "fips"))]
|
||||||
|
|
@ -2176,16 +2333,40 @@ impl Ssl {
|
||||||
where
|
where
|
||||||
S: Read + Write,
|
S: Read + Write,
|
||||||
{
|
{
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
{
|
||||||
|
let ctx = self.ssl_context();
|
||||||
|
|
||||||
|
if ctx.is_rpk() {
|
||||||
|
unsafe {
|
||||||
|
ffi::SSL_CTX_set_custom_verify(
|
||||||
|
ctx.as_ptr(),
|
||||||
|
SslVerifyMode::PEER.bits(),
|
||||||
|
Some(rpk_verify_failure_callback),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SslStreamBuilder::new(self, stream).accept()
|
SslStreamBuilder::new(self, stream).accept()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for SslRef {
|
impl fmt::Debug for SslRef {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt.debug_struct("Ssl")
|
let mut builder = fmt.debug_struct("Ssl");
|
||||||
.field("state", &self.state_string_long())
|
|
||||||
.field("verify_result", &self.verify_result())
|
builder.field("state", &self.state_string_long());
|
||||||
.finish()
|
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
if !self.ssl_context().is_rpk() {
|
||||||
|
builder.field("verify_result", &self.verify_result());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "rpk"))]
|
||||||
|
builder.field("verify_result", &self.verify_result());
|
||||||
|
|
||||||
|
builder.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2215,6 +2396,12 @@ impl SslRef {
|
||||||
/// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
|
/// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify
|
||||||
/// [`SSL_set_verify`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html
|
/// [`SSL_set_verify`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html
|
||||||
pub fn set_verify(&mut self, mode: SslVerifyMode) {
|
pub fn set_verify(&mut self, mode: SslVerifyMode) {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(
|
||||||
|
!self.ssl_context().is_rpk(),
|
||||||
|
"This API is not supported for RPK"
|
||||||
|
);
|
||||||
|
|
||||||
unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, None) }
|
unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, None) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2224,6 +2411,12 @@ impl SslRef {
|
||||||
///
|
///
|
||||||
/// [`SSL_get_verify_mode`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_get_verify_mode.html
|
/// [`SSL_get_verify_mode`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_get_verify_mode.html
|
||||||
pub fn verify_mode(&self) -> SslVerifyMode {
|
pub fn verify_mode(&self) -> SslVerifyMode {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(
|
||||||
|
!self.ssl_context().is_rpk(),
|
||||||
|
"This API is not supported for RPK"
|
||||||
|
);
|
||||||
|
|
||||||
let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
|
let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
|
||||||
SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
|
SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
|
||||||
}
|
}
|
||||||
|
|
@ -2238,6 +2431,12 @@ impl SslRef {
|
||||||
where
|
where
|
||||||
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
|
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
|
||||||
{
|
{
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(
|
||||||
|
!self.ssl_context().is_rpk(),
|
||||||
|
"This API is not supported for RPK"
|
||||||
|
);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// this needs to be in an Arc since the callback can register a new callback!
|
// this needs to be in an Arc since the callback can register a new callback!
|
||||||
self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
|
self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
|
||||||
|
|
@ -2356,6 +2555,12 @@ impl SslRef {
|
||||||
///
|
///
|
||||||
/// [`SSL_get_peer_certificate`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_get_peer_certificate.html
|
/// [`SSL_get_peer_certificate`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_get_peer_certificate.html
|
||||||
pub fn peer_certificate(&self) -> Option<X509> {
|
pub fn peer_certificate(&self) -> Option<X509> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(
|
||||||
|
!self.ssl_context().is_rpk(),
|
||||||
|
"This API is not supported for RPK"
|
||||||
|
);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
|
let ptr = ffi::SSL_get_peer_certificate(self.as_ptr());
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
|
|
@ -2375,6 +2580,12 @@ impl SslRef {
|
||||||
///
|
///
|
||||||
/// [`SSL_get_peer_cert_chain`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_get_peer_cert_chain.html
|
/// [`SSL_get_peer_cert_chain`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_get_peer_cert_chain.html
|
||||||
pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
|
pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(
|
||||||
|
!self.ssl_context().is_rpk(),
|
||||||
|
"This API is not supported for RPK"
|
||||||
|
);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
|
let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
|
|
@ -2391,6 +2602,12 @@ impl SslRef {
|
||||||
///
|
///
|
||||||
/// [`SslContext::certificate`]: struct.SslContext.html#method.certificate
|
/// [`SslContext::certificate`]: struct.SslContext.html#method.certificate
|
||||||
pub fn certificate(&self) -> Option<&X509Ref> {
|
pub fn certificate(&self) -> Option<&X509Ref> {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(
|
||||||
|
!self.ssl_context().is_rpk(),
|
||||||
|
"This API is not supported for RPK"
|
||||||
|
);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = ffi::SSL_get_certificate(self.as_ptr());
|
let ptr = ffi::SSL_get_certificate(self.as_ptr());
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
|
|
@ -2614,6 +2831,12 @@ impl SslRef {
|
||||||
///
|
///
|
||||||
/// [`SSL_get0_param`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_get0_param.html
|
/// [`SSL_get0_param`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_get0_param.html
|
||||||
pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
|
pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(
|
||||||
|
!self.ssl_context().is_rpk(),
|
||||||
|
"This API is not supported for RPK"
|
||||||
|
);
|
||||||
|
|
||||||
unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
|
unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2623,6 +2846,12 @@ impl SslRef {
|
||||||
///
|
///
|
||||||
/// [`SSL_get_verify_result`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_get_verify_result.html
|
/// [`SSL_get_verify_result`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_get_verify_result.html
|
||||||
pub fn verify_result(&self) -> X509VerifyResult {
|
pub fn verify_result(&self) -> X509VerifyResult {
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
assert!(
|
||||||
|
!self.ssl_context().is_rpk(),
|
||||||
|
"This API is not supported for RPK"
|
||||||
|
);
|
||||||
|
|
||||||
unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
|
unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
name = "hyper-boring"
|
name = "hyper-boring"
|
||||||
version = "2.1.2"
|
version = "2.1.2"
|
||||||
authors = ["Steven Fackler <sfackler@gmail.com>", "Ivan Nikulin <ifaaan@gmail.com>"]
|
authors = ["Steven Fackler <sfackler@gmail.com>", "Ivan Nikulin <ifaaan@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
description = "Hyper TLS support via BoringSSL"
|
description = "Hyper TLS support via BoringSSL"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
repository = "https://github.com/cloudflare/boring"
|
repository = "https://github.com/cloudflare/boring"
|
||||||
|
|
@ -14,8 +14,17 @@ exclude = ["test/*"]
|
||||||
default = ["runtime"]
|
default = ["runtime"]
|
||||||
|
|
||||||
runtime = ["hyper/runtime"]
|
runtime = ["hyper/runtime"]
|
||||||
|
|
||||||
|
# Use a FIPS-validated version of boringssl.
|
||||||
fips = ["tokio-boring/fips"]
|
fips = ["tokio-boring/fips"]
|
||||||
|
|
||||||
|
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
|
||||||
|
rpk = ["tokio-boring/rpk"]
|
||||||
|
|
||||||
|
# Enables post-quantum crypto (https://blog.cloudflare.com/post-quantum-for-all/)
|
||||||
|
post-quantum = ["tokio-boring/post-quantum"]
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
antidote = "1.0.0"
|
antidote = "1.0.0"
|
||||||
http = "0.2"
|
http = "0.2"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ name = "tokio-boring"
|
||||||
version = "2.1.5"
|
version = "2.1.5"
|
||||||
authors = ["Alex Crichton <alex@alexcrichton.com>", "Ivan Nikulin <ifaaan@gmail.com>"]
|
authors = ["Alex Crichton <alex@alexcrichton.com>", "Ivan Nikulin <ifaaan@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
repository = "https://github.com/cloudflare/boring"
|
repository = "https://github.com/cloudflare/boring"
|
||||||
homepage = "https://github.com/cloudflare/boring"
|
homepage = "https://github.com/cloudflare/boring"
|
||||||
documentation = "https://docs.rs/tokio-boring"
|
documentation = "https://docs.rs/tokio-boring"
|
||||||
|
|
@ -22,4 +22,11 @@ tokio = { version = "1", features = ["full"] }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
# Use a FIPS-validated version of boringssl.
|
||||||
fips = ["boring/fips"]
|
fips = ["boring/fips"]
|
||||||
|
|
||||||
|
# Enables Raw public key API (https://datatracker.ietf.org/doc/html/rfc7250)
|
||||||
|
rpk = ["boring/rpk"]
|
||||||
|
|
||||||
|
# Enables post-quantum crypto (https://blog.cloudflare.com/post-quantum-for-all/)
|
||||||
|
post-quantum = ["boring/post-quantum"]
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,106 @@
|
||||||
|
#[cfg(feature = "rpk")]
|
||||||
|
mod test_rpk {
|
||||||
|
use boring::pkey::PKey;
|
||||||
|
use boring::ssl::{SslAcceptor, SslConnector};
|
||||||
|
use futures::future;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio_boring::{HandshakeError, SslStream};
|
||||||
|
|
||||||
|
fn create_server() -> (
|
||||||
|
impl Future<Output = Result<SslStream<TcpStream>, HandshakeError<TcpStream>>>,
|
||||||
|
SocketAddr,
|
||||||
|
) {
|
||||||
|
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
|
|
||||||
|
listener.set_nonblocking(true).unwrap();
|
||||||
|
|
||||||
|
let listener = TcpListener::from_std(listener).unwrap();
|
||||||
|
let addr = listener.local_addr().unwrap();
|
||||||
|
|
||||||
|
let server = async move {
|
||||||
|
let mut acceptor = SslAcceptor::rpk().unwrap();
|
||||||
|
let pkey = std::fs::read("tests/key.pem").unwrap();
|
||||||
|
let pkey = PKey::private_key_from_pem(&pkey).unwrap();
|
||||||
|
let cert = std::fs::read("tests/pubkey.der").unwrap();
|
||||||
|
|
||||||
|
acceptor.set_rpk_certificate(&cert).unwrap();
|
||||||
|
acceptor.set_null_chain_private_key(&pkey).unwrap();
|
||||||
|
|
||||||
|
let acceptor = acceptor.build();
|
||||||
|
|
||||||
|
let stream = listener.accept().await.unwrap().0;
|
||||||
|
|
||||||
|
tokio_boring::accept(&acceptor, stream).await
|
||||||
|
};
|
||||||
|
|
||||||
|
(server, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn server_rpk() {
|
||||||
|
let (stream, addr) = create_server();
|
||||||
|
|
||||||
|
let server = async {
|
||||||
|
let mut stream = stream.await.unwrap();
|
||||||
|
let mut buf = [0; 4];
|
||||||
|
stream.read_exact(&mut buf).await.unwrap();
|
||||||
|
assert_eq!(&buf, b"asdf");
|
||||||
|
|
||||||
|
stream.write_all(b"jkl;").await.unwrap();
|
||||||
|
|
||||||
|
future::poll_fn(|ctx| Pin::new(&mut stream).poll_shutdown(ctx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
};
|
||||||
|
|
||||||
|
let client = async {
|
||||||
|
let mut connector = SslConnector::rpk_builder().unwrap();
|
||||||
|
let cert = std::fs::read("tests/pubkey.der").unwrap();
|
||||||
|
|
||||||
|
connector.set_rpk_certificate(&cert).unwrap();
|
||||||
|
let config = connector.build().configure().unwrap();
|
||||||
|
|
||||||
|
let stream = TcpStream::connect(&addr).await.unwrap();
|
||||||
|
let mut stream = tokio_boring::connect(config, "localhost", stream)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
stream.write_all(b"asdf").await.unwrap();
|
||||||
|
|
||||||
|
let mut buf = vec![];
|
||||||
|
stream.read_to_end(&mut buf).await.unwrap();
|
||||||
|
assert_eq!(buf, b"jkl;");
|
||||||
|
};
|
||||||
|
|
||||||
|
future::join(server, client).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn client_rpk_unknown_cert() {
|
||||||
|
let (stream, addr) = create_server();
|
||||||
|
|
||||||
|
let server = async {
|
||||||
|
assert!(stream.await.is_err());
|
||||||
|
};
|
||||||
|
|
||||||
|
let client = async {
|
||||||
|
let mut connector = SslConnector::rpk_builder().unwrap();
|
||||||
|
let cert = std::fs::read("tests/pubkey2.der").unwrap();
|
||||||
|
|
||||||
|
connector.set_rpk_certificate(&cert).unwrap();
|
||||||
|
let config = connector.build().configure().unwrap();
|
||||||
|
|
||||||
|
let stream = TcpStream::connect(&addr).await.unwrap();
|
||||||
|
|
||||||
|
assert!(tokio_boring::connect(config, "localhost", stream)
|
||||||
|
.await
|
||||||
|
.is_err());
|
||||||
|
};
|
||||||
|
|
||||||
|
future::join(server, client).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue