summaryrefslogtreecommitdiffstats
path: root/third_party/rust/neqo-crypto
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/neqo-crypto')
-rw-r--r--third_party/rust/neqo-crypto/.cargo-checksum.json2
-rw-r--r--third_party/rust/neqo-crypto/Cargo.toml40
-rw-r--r--third_party/rust/neqo-crypto/build.rs22
-rw-r--r--third_party/rust/neqo-crypto/src/aead.rs1
-rw-r--r--third_party/rust/neqo-crypto/src/agent.rs12
-rw-r--r--third_party/rust/neqo-crypto/src/agentio.rs9
-rw-r--r--third_party/rust/neqo-crypto/src/cert.rs18
-rw-r--r--third_party/rust/neqo-crypto/src/ech.rs10
-rw-r--r--third_party/rust/neqo-crypto/src/ext.rs4
-rw-r--r--third_party/rust/neqo-crypto/src/hkdf.rs23
-rw-r--r--third_party/rust/neqo-crypto/src/hp.rs8
-rw-r--r--third_party/rust/neqo-crypto/src/lib.rs132
-rw-r--r--third_party/rust/neqo-crypto/src/once.rs44
-rw-r--r--third_party/rust/neqo-crypto/src/p11.rs114
-rw-r--r--third_party/rust/neqo-crypto/src/replay.rs1
-rw-r--r--third_party/rust/neqo-crypto/src/selfencrypt.rs2
-rw-r--r--third_party/rust/neqo-crypto/src/time.rs74
-rw-r--r--third_party/rust/neqo-crypto/tests/aead.rs7
-rw-r--r--third_party/rust/neqo-crypto/tests/agent.rs9
-rw-r--r--third_party/rust/neqo-crypto/tests/ext.rs7
-rw-r--r--third_party/rust/neqo-crypto/tests/handshake.rs9
-rw-r--r--third_party/rust/neqo-crypto/tests/hkdf.rs7
-rw-r--r--third_party/rust/neqo-crypto/tests/hp.rs7
-rw-r--r--third_party/rust/neqo-crypto/tests/init.rs7
-rw-r--r--third_party/rust/neqo-crypto/tests/selfencrypt.rs8
25 files changed, 329 insertions, 248 deletions
diff --git a/third_party/rust/neqo-crypto/.cargo-checksum.json b/third_party/rust/neqo-crypto/.cargo-checksum.json
index ff4ab0fc66..5622e7f4ad 100644
--- a/third_party/rust/neqo-crypto/.cargo-checksum.json
+++ b/third_party/rust/neqo-crypto/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"7f7348b55033e19bbe51b07ee50313c87237fe09b56b338af9ab24e00aab32c6","bindings/bindings.toml":"0660c1661318b8a5094834c2f1bb12266287ef467307f66947eff7762528f70a","bindings/mozpkix.hpp":"77072c8bb0f6eb6bfe8cbadc111dcd92e0c79936d13f2e501aae1e5d289a6675","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"e712c16cb830a83eb4ea1f50dd341a4c30e1cce95d8c45af97030bc8ad0ae829","src/aead.rs":"b7cda4b89298cfd122cd2e1e94c462840e966c60f4832eb441106563ac332e00","src/aead_fuzzing.rs":"c3e590572314e0bb3fafa13dac3c831358b8a7b5570fe9cfe592752fce8cbdee","src/agent.rs":"c4fe47f9f5b0af20e3418da2e2ddce0ac2ca9665c0502115904f66a554e486ee","src/agentio.rs":"847ac63f6406e33bf20a861cadbfe6301ffa15bd73a5291298ffa93511b87dd5","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"6fc09012f994300ff4a7951bf8981aa266220521f58b8ff0989fee6dc1f27df9","src/constants.rs":"f22bf16bd8cb539862cb1e47138dbba79e93fe738f4b907e465891326f98883c","src/ech.rs":"58b7e0a1d2d52c59889cf8b735902577f7c3df93dfb89c72af2646b7aef29f39","src/err.rs":"fca0222167883231a5e0a569a593f44214501819adf5aadf814be27891c87c24","src/exp.rs":"cec59d61fc95914f9703d2fb6490a8507af993c9db710dde894f2f8fd38123c7","src/ext.rs":"c6ab9aefbbca531466dea938d853b1e42ed51816238afe400b20dbdb0111690b","src/hkdf.rs":"8e6cc5dce0f36efa4e13f5a24e2879bdbf10fb9a2b7dc8f13692e47d8959cdc8","src/hp.rs":"62ec073d99cf8bf3a123838c7d9b51bfdf68887148961f6307288e8dd56ac711","src/lib.rs":"40d9ac97c307c8161c2bf48156cc82377f81ad6e709f99cfd7dc0131dc192f86","src/once.rs":"b9850384899a1a016e839743d3489c0d4d916e1973746ef8c89872105d7d9736","src/p11.rs":"6c0f2f1b18e9bf9088a5ca5bdc99e789bb42234f7d2fe24d0b463bc957cb84a2","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"1ff4a12f6135ef2c42aef2b0947e26fd6241cd4b359020245608046452a7fcb0","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"4d2f4a6ea0fc94502130413ab5e2ea82612228f38a96a1865bf7d2b3f440620e","src/ssl.rs":"c83baa5518b81dd06f2e4072ea3c2d666ccdeb8b1ff6e3746eea9f1af47023a6","src/time.rs":"9204f3a384fb9dd2c3816c88666ad61ac3538f9e2f028954e81fd335a1479070","tests/aead.rs":"efdb92a060ca1957d890da1604513369559cb43195ee54149ed3ab47958dad59","tests/agent.rs":"0e55354595ae5f0e1ab83731564da57ba88a296e00692147c47df7067a0f416a","tests/ext.rs":"54657b45bd86d2561bb0f548736bc6f141bb664a5b043506f428422919ab95d4","tests/handshake.rs":"40701bc22f16d1ba9b9bd9683738e52b96faafee4119f7057437dae705f7867a","tests/hkdf.rs":"4160978b96505c1f1b7d6c4b5f43536ff7bd791c8746f9546c9fbc0fce5cf1c7","tests/hp.rs":"8eeee21a439e0f991145dff07b01283ae39ccd4b8dac4d011d43a464f73db670","tests/init.rs":"fc9e392b1efa0d8efb28952f73ffc05e5348e7b2b69207b60e375c3888a252a2","tests/selfencrypt.rs":"6edd0914b8466d79ecfb569c6d86995fd364b0dc71be2a0554e82f736ebd6b7c"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"6f1917fbd4cbf53cb4883c30e8fcb9c20f8ebe15e19576c7d37cb6ba0ab9e42b","bindings/bindings.toml":"0660c1661318b8a5094834c2f1bb12266287ef467307f66947eff7762528f70a","bindings/mozpkix.hpp":"77072c8bb0f6eb6bfe8cbadc111dcd92e0c79936d13f2e501aae1e5d289a6675","bindings/nspr_err.h":"2d5205d017b536c2d838bcf9bc4ec79f96dd50e7bb9b73892328781f1ee6629d","bindings/nspr_error.h":"e41c03c77b8c22046f8618832c9569fbcc7b26d8b9bbc35eea7168f35e346889","bindings/nspr_io.h":"085b289849ef0e77f88512a27b4d9bdc28252bd4d39c6a17303204e46ef45f72","bindings/nspr_time.h":"2e637fd338a5cf0fd3fb0070a47f474a34c2a7f4447f31b6875f5a9928d0a261","bindings/nss_ciphers.h":"95ec6344a607558b3c5ba8510f463b6295f3a2fb3f538a01410531045a5f62d1","bindings/nss_init.h":"ef49045063782fb612aff459172cc6a89340f15005808608ade5320ca9974310","bindings/nss_p11.h":"0b81e64fe6db49b2ecff94edd850be111ef99ec11220e88ceb1c67be90143a78","bindings/nss_secerr.h":"713e8368bdae5159af7893cfa517dabfe5103cede051dee9c9557c850a2defc6","bindings/nss_ssl.h":"af222fb957b989e392e762fa2125c82608a0053aff4fb97e556691646c88c335","bindings/nss_sslerr.h":"24b97f092183d8486f774cdaef5030d0249221c78343570d83a4ee5b594210ae","bindings/nss_sslopt.h":"b7807eb7abdad14db6ad7bc51048a46b065a0ea65a4508c95a12ce90e59d1eea","build.rs":"21d9a0140b2afd708583f58f2af0a4ba93ab07ec088680b4cbf0e184aeb8785b","src/aead.rs":"8f50e4557b7829edb67f57c80c777c6ae23c868e2b2eeaaae0736af04dc0d298","src/aead_fuzzing.rs":"c3e590572314e0bb3fafa13dac3c831358b8a7b5570fe9cfe592752fce8cbdee","src/agent.rs":"e995e9cc5108470594bae1b0d4e4bc6b7a8ac2b66488f71ea99e2836c0edbd7e","src/agentio.rs":"c4cb1b3cd92ef53eb0b4fb0b34a597068d82d78ba470dae5821670a0f06c9cda","src/auth.rs":"ced1a18f691894984244088020ea25dc1ee678603317f0c7dfc8b8842fa750b4","src/cert.rs":"8942cb3ce25a61f92b6ffc30fb286052ed6f56eeda3be12fd46ea76ceba6c1cf","src/constants.rs":"f22bf16bd8cb539862cb1e47138dbba79e93fe738f4b907e465891326f98883c","src/ech.rs":"9d322fcc01c0886f1dfe9bb6273cb9f88a746452ac9a802761b1816a05930c1f","src/err.rs":"fca0222167883231a5e0a569a593f44214501819adf5aadf814be27891c87c24","src/exp.rs":"cec59d61fc95914f9703d2fb6490a8507af993c9db710dde894f2f8fd38123c7","src/ext.rs":"cbf7d9f5ecabf4b8c9efd6c334637ab1596ec5266d38ab8d2d6ceae305283deb","src/hkdf.rs":"ef32f20e30a9bd7f094199536d19c87c4231b7fbbe4a9c54c70e84ca9c6575be","src/hp.rs":"644f1bed67f1c6189a67c8d02ab3358aaa7f63af4b913dd7395becbc01a84291","src/lib.rs":"23732c7799be038c0e0835b54e7c40cf6c6536113e0adb6ae3b41b216a6e5220","src/p11.rs":"e8c366def0df470101f3d120dcc4391f74f921fe59e2f3db2a56832e2852b855","src/prio.rs":"e5e169296c0ac69919c59fb6c1f8bd6bf079452eaa13d75da0edd41d435d3f6f","src/replay.rs":"96b7af8eff9e14313e79303092018b12e8834f780c96b8e247c497fdc680c696","src/result.rs":"0587cbb6aace71a7f9765ef7c01dcd9f73a49dcc6331e1d8fe4de2aef6ca65b6","src/secrets.rs":"4ffaa66f25df47dadf042063bff5953effa7bf2f4920cafe827757d6a659cb58","src/selfencrypt.rs":"ac65b13f5bade9d03ab4709364f9ec937fa4ca009965c77ca73b481534a0a470","src/ssl.rs":"c83baa5518b81dd06f2e4072ea3c2d666ccdeb8b1ff6e3746eea9f1af47023a6","src/time.rs":"3b2829a98a1648eb052db19bb470808b6b015a1eca27ab7be64b5d196c0271c0","tests/aead.rs":"3ac4fe4ab79922b5d0191a9717058fc8d0710380ce9b25448095f870f511844f","tests/agent.rs":"824735f88e487a3748200844e9481e81a72163ad74d82faa9aa16594d9b9bb25","tests/ext.rs":"1b047d23d9b224ad06eb65d8f3a7b351e263774e404c79bbcbe8f43790e29c18","tests/handshake.rs":"e892a2839b31414be16e96cdf3b1a65978716094700c1a4989229f7edbf578a0","tests/hkdf.rs":"1d2098dc8398395864baf13e4886cfd1da6d36118727c3b264f457ee3da6b048","tests/hp.rs":"b24fec53771c169be788772532d2617a5349196cf87d6444dc74214f7c73e92c","tests/init.rs":"44fe7626b75ab8c57adfee361bb70a83d5958797e1eb6c4531bb74988ba3a990","tests/selfencrypt.rs":"25813b0c6f32fc8383bb7685745feb750eb3fdc0a6a172a50d961c68d39f2a46"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/neqo-crypto/Cargo.toml b/third_party/rust/neqo-crypto/Cargo.toml
index 73c1fcb364..499921e531 100644
--- a/third_party/rust/neqo-crypto/Cargo.toml
+++ b/third_party/rust/neqo-crypto/Cargo.toml
@@ -10,16 +10,21 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
-rust-version = "1.70.0"
+edition = "2021"
+rust-version = "1.74.0"
name = "neqo-crypto"
-version = "0.7.0"
-authors = ["Martin Thomson <mt@lowentropy.net>"]
+version = "0.7.2"
+authors = ["The Neqo Authors <necko@mozilla.com>"]
build = "build.rs"
+homepage = "https://github.com/mozilla/neqo/"
license = "MIT OR Apache-2.0"
+repository = "https://github.com/mozilla/neqo/"
+
+[lib]
+bench = false
[dependencies.log]
-version = "~0.4.17"
+version = "0.4"
default-features = false
[dependencies.neqo-common]
@@ -28,21 +33,32 @@ path = "../neqo-common"
[dev-dependencies.test-fixture]
path = "../test-fixture"
-[build-dependencies]
-serde = "1.0.195"
-serde_derive = "1.0.195"
-toml = "0.5.11"
-
[build-dependencies.bindgen]
-version = "0.69.1"
+version = "0.69"
features = ["runtime"]
default-features = false
[build-dependencies.mozbuild]
version = "0.1"
optional = true
+default-features = false
+
+[build-dependencies.serde]
+version = "1.0"
+default-features = false
+
+[build-dependencies.serde_derive]
+version = "1.0"
+default-features = false
+
+[build-dependencies.toml]
+version = "0.5"
+default-features = false
[features]
-deny-warnings = []
fuzzing = []
gecko = ["mozbuild"]
+
+[lints.clippy.pedantic]
+level = "warn"
+priority = -1
diff --git a/third_party/rust/neqo-crypto/build.rs b/third_party/rust/neqo-crypto/build.rs
index a63c34dedb..c4c2a73e75 100644
--- a/third_party/rust/neqo-crypto/build.rs
+++ b/third_party/rust/neqo-crypto/build.rs
@@ -4,9 +4,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(clippy::pedantic)]
-
use std::{
collections::HashMap,
env, fs,
@@ -37,7 +34,7 @@ struct Bindings {
opaque: Vec<String>,
/// enumerations that are turned into a module (without this, the enum is
/// mapped using the default, which means that the individual values are
- /// formed with an underscore as <enum_type>_<enum_value_name>).
+ /// formed with an underscore as <`enum_type`>_<`enum_value_name`>).
#[serde(default)]
enums: Vec<String>,
@@ -53,9 +50,10 @@ struct Bindings {
}
fn is_debug() -> bool {
- env::var("DEBUG")
- .map(|d| d.parse::<bool>().unwrap_or(false))
- .unwrap_or(false)
+ // Check the build profile and not whether debug symbols are enabled (i.e.,
+ // `env::var("DEBUG")`), because we enable those for benchmarking/profiling and still want
+ // to build NSS in release mode.
+ env::var("PROFILE").unwrap_or_default() == "debug"
}
// bindgen needs access to libclang.
@@ -126,7 +124,7 @@ fn nss_dir() -> PathBuf {
}
dir
};
- assert!(dir.is_dir(), "NSS_DIR {:?} doesn't exist", dir);
+ assert!(dir.is_dir(), "NSS_DIR {dir:?} doesn't exist");
// Note that this returns a relative path because UNC
// paths on windows cause certain tools to explode.
dir
@@ -150,10 +148,10 @@ fn build_nss(dir: PathBuf) {
let mut build_nss = vec![
String::from("./build.sh"),
String::from("-Ddisable_tests=1"),
+ // Generate static libraries in addition to shared libraries.
+ String::from("--static"),
];
- if is_debug() {
- build_nss.push(String::from("--static"));
- } else {
+ if !is_debug() {
build_nss.push(String::from("-o"));
}
if let Ok(d) = env::var("NSS_JOBS") {
@@ -318,7 +316,7 @@ fn setup_standalone() -> Vec<String> {
"cargo:rustc-link-search=native={}",
nsslibdir.to_str().unwrap()
);
- if is_debug() {
+ if is_debug() || env::consts::OS == "windows" {
static_link();
} else {
dynamic_link();
diff --git a/third_party/rust/neqo-crypto/src/aead.rs b/third_party/rust/neqo-crypto/src/aead.rs
index a2f009a403..bf7d7fe9d7 100644
--- a/third_party/rust/neqo-crypto/src/aead.rs
+++ b/third_party/rust/neqo-crypto/src/aead.rs
@@ -5,7 +5,6 @@
// except according to those terms.
use std::{
- convert::{TryFrom, TryInto},
fmt,
ops::{Deref, DerefMut},
os::raw::{c_char, c_uint},
diff --git a/third_party/rust/neqo-crypto/src/agent.rs b/third_party/rust/neqo-crypto/src/agent.rs
index cd0bb4cb12..82a6dacd48 100644
--- a/third_party/rust/neqo-crypto/src/agent.rs
+++ b/third_party/rust/neqo-crypto/src/agent.rs
@@ -6,7 +6,6 @@
use std::{
cell::RefCell,
- convert::TryFrom,
ffi::{CStr, CString},
mem::{self, MaybeUninit},
ops::{Deref, DerefMut},
@@ -33,6 +32,7 @@ use crate::{
ech,
err::{is_blocked, secstatus_to_res, Error, PRErrorCode, Res},
ext::{ExtensionHandler, ExtensionTracker},
+ null_safe_slice,
p11::{self, PrivateKey, PublicKey},
prio,
replay::AntiReplay,
@@ -897,7 +897,7 @@ impl Client {
let resumption = arg.cast::<Vec<ResumptionToken>>().as_mut().unwrap();
let len = usize::try_from(len).unwrap();
let mut v = Vec::with_capacity(len);
- v.extend_from_slice(std::slice::from_raw_parts(token, len));
+ v.extend_from_slice(null_safe_slice(token, len));
qinfo!(
[format!("{fd:p}")],
"Got resumption token {}",
@@ -1015,7 +1015,7 @@ pub enum ZeroRttCheckResult {
Accept,
/// Reject 0-RTT, but continue the handshake normally.
Reject,
- /// Send HelloRetryRequest (probably not needed for QUIC).
+ /// Send `HelloRetryRequest` (probably not needed for QUIC).
HelloRetryRequest(Vec<u8>),
/// Fail the handshake.
Fail,
@@ -1105,11 +1105,7 @@ impl Server {
}
let check_state = arg.cast::<ZeroRttCheckState>().as_mut().unwrap();
- let token = if client_token.is_null() {
- &[]
- } else {
- std::slice::from_raw_parts(client_token, usize::try_from(client_token_len).unwrap())
- };
+ let token = null_safe_slice(client_token, usize::try_from(client_token_len).unwrap());
match check_state.checker.check(token) {
ZeroRttCheckResult::Accept => ssl::SSLHelloRetryRequestAction::ssl_hello_retry_accept,
ZeroRttCheckResult::Fail => ssl::SSLHelloRetryRequestAction::ssl_hello_retry_fail,
diff --git a/third_party/rust/neqo-crypto/src/agentio.rs b/third_party/rust/neqo-crypto/src/agentio.rs
index 2bcc540530..7c57a0ef45 100644
--- a/third_party/rust/neqo-crypto/src/agentio.rs
+++ b/third_party/rust/neqo-crypto/src/agentio.rs
@@ -6,13 +6,11 @@
use std::{
cmp::min,
- convert::{TryFrom, TryInto},
fmt, mem,
ops::Deref,
os::raw::{c_uint, c_void},
pin::Pin,
ptr::{null, null_mut},
- vec::Vec,
};
use neqo_common::{hex, hex_with_len, qtrace};
@@ -20,7 +18,7 @@ use neqo_common::{hex, hex_with_len, qtrace};
use crate::{
constants::{ContentType, Epoch},
err::{nspr, Error, PR_SetError, Res},
- prio, ssl,
+ null_safe_slice, prio, ssl,
};
// Alias common types.
@@ -100,7 +98,7 @@ impl RecordList {
) -> ssl::SECStatus {
let records = arg.cast::<Self>().as_mut().unwrap();
- let slice = std::slice::from_raw_parts(data, len as usize);
+ let slice = null_safe_slice(data, len);
records.append(epoch, ContentType::try_from(ct).unwrap(), slice);
ssl::SECSuccess
}
@@ -178,6 +176,7 @@ impl AgentIoInput {
return Err(Error::NoDataAvailable);
}
+ #[allow(clippy::disallowed_methods)] // We just checked if this was empty.
let src = unsafe { std::slice::from_raw_parts(self.input, amount) };
qtrace!([self], "read {}", hex(src));
let dst = unsafe { std::slice::from_raw_parts_mut(buf, amount) };
@@ -232,7 +231,7 @@ impl AgentIo {
// Stage output from TLS into the output buffer.
fn save_output(&mut self, buf: *const u8, count: usize) {
- let slice = unsafe { std::slice::from_raw_parts(buf, count) };
+ let slice = unsafe { null_safe_slice(buf, count) };
qtrace!([self], "save output {}", hex(slice));
self.output.extend_from_slice(slice);
}
diff --git a/third_party/rust/neqo-crypto/src/cert.rs b/third_party/rust/neqo-crypto/src/cert.rs
index 64e63ec71a..2836b5237c 100644
--- a/third_party/rust/neqo-crypto/src/cert.rs
+++ b/third_party/rust/neqo-crypto/src/cert.rs
@@ -4,16 +4,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::{
- convert::TryFrom,
- ptr::{addr_of, NonNull},
- slice,
-};
+use std::ptr::{addr_of, NonNull};
use neqo_common::qerror;
use crate::{
err::secstatus_to_res,
+ null_safe_slice,
p11::{CERTCertListNode, CERT_GetCertificateDer, CertList, Item, SECItem, SECItemArray},
ssl::{
PRFileDesc, SSL_PeerCertificateChain, SSL_PeerSignedCertTimestamps,
@@ -24,7 +21,7 @@ use crate::{
pub struct CertificateInfo {
certs: CertList,
cursor: *const CERTCertListNode,
- /// stapled_ocsp_responses and signed_cert_timestamp are properties
+ /// `stapled_ocsp_responses` and `signed_cert_timestamp` are properties
/// associated with each of the certificates. Right now, NSS only
/// reports the value for the end-entity certificate (the first).
stapled_ocsp_responses: Option<Vec<Vec<u8>>>,
@@ -52,7 +49,7 @@ fn stapled_ocsp_responses(fd: *mut PRFileDesc) -> Option<Vec<Vec<u8>>> {
};
for idx in 0..len {
let itemp: *const SECItem = unsafe { ocsp_ptr.as_ref().items.offset(idx).cast() };
- let item = unsafe { slice::from_raw_parts((*itemp).data, (*itemp).len as usize) };
+ let item = unsafe { null_safe_slice((*itemp).data, (*itemp).len) };
ocsp_helper.push(item.to_owned());
}
Some(ocsp_helper)
@@ -68,9 +65,8 @@ fn signed_cert_timestamp(fd: *mut PRFileDesc) -> Option<Vec<u8>> {
if unsafe { sct_ptr.as_ref().len == 0 || sct_ptr.as_ref().data.is_null() } {
Some(Vec::new())
} else {
- let sct_slice = unsafe {
- slice::from_raw_parts(sct_ptr.as_ref().data, sct_ptr.as_ref().len as usize)
- };
+ let sct_slice =
+ unsafe { null_safe_slice(sct_ptr.as_ref().data, sct_ptr.as_ref().len) };
Some(sct_slice.to_owned())
}
}
@@ -105,7 +101,7 @@ impl<'a> Iterator for &'a mut CertificateInfo {
let cert = unsafe { *self.cursor }.cert;
secstatus_to_res(unsafe { CERT_GetCertificateDer(cert, &mut item) })
.expect("getting DER from certificate should work");
- Some(unsafe { std::slice::from_raw_parts(item.data, item.len as usize) })
+ Some(unsafe { null_safe_slice(item.data, item.len) })
}
}
diff --git a/third_party/rust/neqo-crypto/src/ech.rs b/third_party/rust/neqo-crypto/src/ech.rs
index 1f54c4592e..4ff2cda7e8 100644
--- a/third_party/rust/neqo-crypto/src/ech.rs
+++ b/third_party/rust/neqo-crypto/src/ech.rs
@@ -5,7 +5,6 @@
// except according to those terms.
use std::{
- convert::TryFrom,
ffi::CString,
os::raw::{c_char, c_uint},
ptr::{addr_of_mut, null_mut},
@@ -15,7 +14,7 @@ use neqo_common::qtrace;
use crate::{
err::{ssl::SSL_ERROR_ECH_RETRY_WITH_ECH, Error, Res},
- experimental_api,
+ experimental_api, null_safe_slice,
p11::{
self, Item, PrivateKey, PublicKey, SECITEM_FreeItem, SECItem, SECKEYPrivateKey,
SECKEYPublicKey, Slot,
@@ -76,7 +75,7 @@ pub fn convert_ech_error(fd: *mut PRFileDesc, err: Error) -> Error {
return Error::InternalError;
}
let buf = unsafe {
- let slc = std::slice::from_raw_parts(item.data, usize::try_from(item.len).unwrap());
+ let slc = null_safe_slice(item.data, item.len);
let buf = Vec::from(slc);
SECITEM_FreeItem(&mut item, PRBool::from(false));
buf
@@ -101,8 +100,7 @@ pub fn generate_keys() -> Res<(PrivateKey, PublicKey)> {
let oid_data = unsafe { p11::SECOID_FindOIDByTag(p11::SECOidTag::SEC_OID_CURVE25519) };
let oid = unsafe { oid_data.as_ref() }.ok_or(Error::InternalError)?;
- let oid_slc =
- unsafe { std::slice::from_raw_parts(oid.oid.data, usize::try_from(oid.oid.len).unwrap()) };
+ let oid_slc = unsafe { null_safe_slice(oid.oid.data, oid.oid.len) };
let mut params: Vec<u8> = Vec::with_capacity(oid_slc.len() + 2);
params.push(u8::try_from(p11::SEC_ASN1_OBJECT_ID).unwrap());
params.push(u8::try_from(oid.oid.len).unwrap());
@@ -113,7 +111,6 @@ pub fn generate_keys() -> Res<(PrivateKey, PublicKey)> {
// If we have tracing on, try to ensure that key data can be read.
let insensitive_secret_ptr = if log::log_enabled!(log::Level::Trace) {
- #[allow(clippy::useless_conversion)] // TODO: Remove when we bump the MSRV to 1.74.0.
unsafe {
p11::PK11_GenerateKeyPairWithOpFlags(
*slot,
@@ -131,7 +128,6 @@ pub fn generate_keys() -> Res<(PrivateKey, PublicKey)> {
};
assert_eq!(insensitive_secret_ptr.is_null(), public_ptr.is_null());
let secret_ptr = if insensitive_secret_ptr.is_null() {
- #[allow(clippy::useless_conversion)] // TODO: Remove when we bump the MSRV to 1.74.0.
unsafe {
p11::PK11_GenerateKeyPairWithOpFlags(
*slot,
diff --git a/third_party/rust/neqo-crypto/src/ext.rs b/third_party/rust/neqo-crypto/src/ext.rs
index 310e87a1b7..02ee6340c1 100644
--- a/third_party/rust/neqo-crypto/src/ext.rs
+++ b/third_party/rust/neqo-crypto/src/ext.rs
@@ -6,7 +6,6 @@
use std::{
cell::RefCell,
- convert::TryFrom,
os::raw::{c_uint, c_void},
pin::Pin,
rc::Rc,
@@ -16,6 +15,7 @@ use crate::{
agentio::as_c_void,
constants::{Extension, HandshakeMessage, TLS_HS_CLIENT_HELLO, TLS_HS_ENCRYPTED_EXTENSIONS},
err::Res,
+ null_safe_slice,
ssl::{
PRBool, PRFileDesc, SECFailure, SECStatus, SECSuccess, SSLAlertDescription,
SSLExtensionHandler, SSLExtensionWriter, SSLHandshakeType,
@@ -105,7 +105,7 @@ impl ExtensionTracker {
alert: *mut SSLAlertDescription,
arg: *mut c_void,
) -> SECStatus {
- let d = std::slice::from_raw_parts(data, len as usize);
+ let d = null_safe_slice(data, len);
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
Self::wrap_handler_call(arg, |handler| {
// Cast is safe here because the message type is always part of the enum
diff --git a/third_party/rust/neqo-crypto/src/hkdf.rs b/third_party/rust/neqo-crypto/src/hkdf.rs
index e3cf77418c..3706be6c3b 100644
--- a/third_party/rust/neqo-crypto/src/hkdf.rs
+++ b/third_party/rust/neqo-crypto/src/hkdf.rs
@@ -5,7 +5,6 @@
// except according to those terms.
use std::{
- convert::TryFrom,
os::raw::{c_char, c_uint},
ptr::null_mut,
};
@@ -17,9 +16,10 @@ use crate::{
},
err::{Error, Res},
p11::{
- random, Item, PK11Origin, PK11SymKey, PK11_ImportDataKey, Slot, SymKey, CKA_DERIVE,
+ Item, PK11Origin, PK11SymKey, PK11_ImportDataKey, Slot, SymKey, CKA_DERIVE,
CKM_HKDF_DERIVE, CK_ATTRIBUTE_TYPE, CK_MECHANISM_TYPE,
},
+ random,
};
experimental_api!(SSL_HkdfExtract(
@@ -40,24 +40,32 @@ experimental_api!(SSL_HkdfExpandLabel(
secret: *mut *mut PK11SymKey,
));
-fn key_size(version: Version, cipher: Cipher) -> Res<usize> {
+const MAX_KEY_SIZE: usize = 48;
+const fn key_size(version: Version, cipher: Cipher) -> Res<usize> {
if version != TLS_VERSION_1_3 {
return Err(Error::UnsupportedVersion);
}
- Ok(match cipher {
+ let size = match cipher {
TLS_AES_128_GCM_SHA256 | TLS_CHACHA20_POLY1305_SHA256 => 32,
TLS_AES_256_GCM_SHA384 => 48,
_ => return Err(Error::UnsupportedCipher),
- })
+ };
+ debug_assert!(size <= MAX_KEY_SIZE);
+ Ok(size)
}
/// Generate a random key of the right size for the given suite.
///
/// # Errors
///
-/// Only if NSS fails.
+/// If the ciphersuite or protocol version is not supported.
pub fn generate_key(version: Version, cipher: Cipher) -> Res<SymKey> {
- import_key(version, &random(key_size(version, cipher)?))
+ // With generic_const_expr, this becomes:
+ // import_key(version, &random::<{ key_size(version, cipher) }>())
+ import_key(
+ version,
+ &random::<MAX_KEY_SIZE>()[0..key_size(version, cipher)?],
+ )
}
/// Import a symmetric key for use with HKDF.
@@ -70,7 +78,6 @@ pub fn import_key(version: Version, buf: &[u8]) -> Res<SymKey> {
return Err(Error::UnsupportedVersion);
}
let slot = Slot::internal()?;
- #[allow(clippy::useless_conversion)] // TODO: Remove when we bump the MSRV to 1.74.0.
let key_ptr = unsafe {
PK11_ImportDataKey(
*slot,
diff --git a/third_party/rust/neqo-crypto/src/hp.rs b/third_party/rust/neqo-crypto/src/hp.rs
index 2479eff8f5..1eba6a9cb5 100644
--- a/third_party/rust/neqo-crypto/src/hp.rs
+++ b/third_party/rust/neqo-crypto/src/hp.rs
@@ -6,7 +6,6 @@
use std::{
cell::RefCell,
- convert::TryFrom,
fmt::{self, Debug},
os::raw::{c_char, c_int, c_uint},
ptr::{addr_of_mut, null, null_mut},
@@ -46,7 +45,7 @@ pub enum HpKey {
/// track references using `Rc`. `PK11Context` can't be used with `PK11_CloneContext`
/// as that is not supported for these contexts.
Aes(Rc<RefCell<Context>>),
- /// The ChaCha20 mask has to invoke a new PK11_Encrypt every time as it needs to
+ /// The `ChaCha20` mask has to invoke a new `PK11_Encrypt` every time as it needs to
/// change the counter and nonce on each invocation.
Chacha(SymKey),
}
@@ -76,7 +75,6 @@ impl HpKey {
let l = label.as_bytes();
let mut secret: *mut PK11SymKey = null_mut();
- #[allow(clippy::useless_conversion)] // TODO: Remove when we bump the MSRV to 1.74.0.
let (mech, key_size) = match cipher {
TLS_AES_128_GCM_SHA256 => (CK_MECHANISM_TYPE::from(CKM_AES_ECB), 16),
TLS_AES_256_GCM_SHA384 => (CK_MECHANISM_TYPE::from(CKM_AES_ECB), 32),
@@ -104,8 +102,6 @@ impl HpKey {
let res = match cipher {
TLS_AES_128_GCM_SHA256 | TLS_AES_256_GCM_SHA384 => {
- // TODO: Remove when we bump the MSRV to 1.74.0.
- #[allow(clippy::useless_conversion)]
let context_ptr = unsafe {
PK11_CreateContextBySymKey(
mech,
@@ -181,8 +177,6 @@ impl HpKey {
};
let mut output_len: c_uint = 0;
let mut param_item = Item::wrap_struct(&params);
- // TODO: Remove when we bump the MSRV to 1.74.0.
- #[allow(clippy::useless_conversion)]
secstatus_to_res(unsafe {
PK11_Encrypt(
**key,
diff --git a/third_party/rust/neqo-crypto/src/lib.rs b/third_party/rust/neqo-crypto/src/lib.rs
index 05424ee1f3..2ec1b4a3ea 100644
--- a/third_party/rust/neqo-crypto/src/lib.rs
+++ b/third_party/rust/neqo-crypto/src/lib.rs
@@ -4,13 +4,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(clippy::pedantic)]
-// Bindgen auto generated code
-// won't adhere to the clippy rules below
-#![allow(clippy::module_name_repetitions)]
-#![allow(clippy::unseparated_literal_suffix)]
-#![allow(clippy::used_underscore_binding)]
+#![allow(clippy::module_name_repetitions)] // This lint doesn't work here.
+#![allow(clippy::unseparated_literal_suffix, clippy::used_underscore_binding)] // For bindgen code.
mod aead;
#[cfg(feature = "fuzzing")]
@@ -27,7 +22,6 @@ mod exp;
pub mod ext;
pub mod hkdf;
pub mod hp;
-mod once;
#[macro_use]
mod p11;
mod prio;
@@ -37,11 +31,7 @@ pub mod selfencrypt;
mod ssl;
mod time;
-use std::{
- ffi::CString,
- path::{Path, PathBuf},
- ptr::null,
-};
+use std::{ffi::CString, path::PathBuf, ptr::null, sync::OnceLock};
#[cfg(not(feature = "fuzzing"))]
pub use self::aead::RealAead as Aead;
@@ -49,7 +39,6 @@ pub use self::aead::RealAead as Aead;
pub use self::aead::RealAead;
#[cfg(feature = "fuzzing")]
pub use self::aead_fuzzing::FuzzingAead as Aead;
-use self::once::OnceResult;
pub use self::{
agent::{
Agent, AllowZeroRtt, Client, HandshakeState, Record, RecordList, ResumptionToken,
@@ -64,7 +53,7 @@ pub use self::{
},
err::{Error, PRErrorCode, Res},
ext::{ExtensionHandler, ExtensionHandlerResult, ExtensionWriterResult},
- p11::{random, PrivateKey, PublicKey, SymKey},
+ p11::{random, randomize, PrivateKey, PublicKey, SymKey},
replay::AntiReplay,
secrets::SecretDirection,
ssl::Opt,
@@ -87,7 +76,7 @@ fn secstatus_to_res(code: nss::SECStatus) -> Res<()> {
enum NssLoaded {
External,
NoDb,
- Db(Box<Path>),
+ Db,
}
impl Drop for NssLoaded {
@@ -100,7 +89,7 @@ impl Drop for NssLoaded {
}
}
-static mut INITIALIZED: OnceResult<NssLoaded> = OnceResult::new();
+static INITIALIZED: OnceLock<NssLoaded> = OnceLock::new();
fn already_initialized() -> bool {
unsafe { nss::NSS_IsInitialized() != 0 }
@@ -124,19 +113,18 @@ fn version_check() {
pub fn init() {
// Set time zero.
time::init();
- unsafe {
- INITIALIZED.call_once(|| {
- version_check();
- if already_initialized() {
- return NssLoaded::External;
- }
+ _ = INITIALIZED.get_or_init(|| {
+ version_check();
+ if already_initialized() {
+ return NssLoaded::External;
+ }
- secstatus_to_res(nss::NSS_NoDB_Init(null())).expect("NSS_NoDB_Init failed");
- secstatus_to_res(nss::NSS_SetDomesticPolicy()).expect("NSS_SetDomesticPolicy failed");
+ secstatus_to_res(unsafe { nss::NSS_NoDB_Init(null()) }).expect("NSS_NoDB_Init failed");
+ secstatus_to_res(unsafe { nss::NSS_SetDomesticPolicy() })
+ .expect("NSS_SetDomesticPolicy failed");
- NssLoaded::NoDb
- });
- }
+ NssLoaded::NoDb
+ });
}
/// This enables SSLTRACE by calling a simple, harmless function to trigger its
@@ -158,51 +146,71 @@ fn enable_ssl_trace() {
/// If NSS cannot be initialized.
pub fn init_db<P: Into<PathBuf>>(dir: P) {
time::init();
- unsafe {
- INITIALIZED.call_once(|| {
- version_check();
- if already_initialized() {
- return NssLoaded::External;
- }
+ _ = INITIALIZED.get_or_init(|| {
+ version_check();
+ if already_initialized() {
+ return NssLoaded::External;
+ }
- let path = dir.into();
- assert!(path.is_dir());
- let pathstr = path.to_str().expect("path converts to string").to_string();
- let dircstr = CString::new(pathstr).unwrap();
- let empty = CString::new("").unwrap();
- secstatus_to_res(nss::NSS_Initialize(
+ let path = dir.into();
+ assert!(path.is_dir());
+ let pathstr = path.to_str().expect("path converts to string").to_string();
+ let dircstr = CString::new(pathstr).unwrap();
+ let empty = CString::new("").unwrap();
+ secstatus_to_res(unsafe {
+ nss::NSS_Initialize(
dircstr.as_ptr(),
empty.as_ptr(),
empty.as_ptr(),
nss::SECMOD_DB.as_ptr().cast(),
nss::NSS_INIT_READONLY,
- ))
- .expect("NSS_Initialize failed");
-
- secstatus_to_res(nss::NSS_SetDomesticPolicy()).expect("NSS_SetDomesticPolicy failed");
- secstatus_to_res(ssl::SSL_ConfigServerSessionIDCache(
- 1024,
- 0,
- 0,
- dircstr.as_ptr(),
- ))
- .expect("SSL_ConfigServerSessionIDCache failed");
-
- #[cfg(debug_assertions)]
- enable_ssl_trace();
-
- NssLoaded::Db(path.into_boxed_path())
- });
- }
+ )
+ })
+ .expect("NSS_Initialize failed");
+
+ secstatus_to_res(unsafe { nss::NSS_SetDomesticPolicy() })
+ .expect("NSS_SetDomesticPolicy failed");
+ secstatus_to_res(unsafe {
+ ssl::SSL_ConfigServerSessionIDCache(1024, 0, 0, dircstr.as_ptr())
+ })
+ .expect("SSL_ConfigServerSessionIDCache failed");
+
+ #[cfg(debug_assertions)]
+ enable_ssl_trace();
+
+ NssLoaded::Db
+ });
}
/// # Panics
///
/// If NSS isn't initialized.
pub fn assert_initialized() {
- unsafe {
- INITIALIZED.call_once(|| {
- panic!("NSS not initialized with init or init_db");
- });
+ INITIALIZED
+ .get()
+ .expect("NSS not initialized with init or init_db");
+}
+
+/// NSS tends to return empty "slices" with a null pointer, which will cause
+/// `std::slice::from_raw_parts` to panic if passed directly. This wrapper avoids
+/// that issue. It also performs conversion for lengths, as a convenience.
+///
+/// # Panics
+/// If the provided length doesn't fit into a `usize`.
+///
+/// # Safety
+/// The caller must adhere to the safety constraints of `std::slice::from_raw_parts`,
+/// except that this will accept a null value for `data`.
+unsafe fn null_safe_slice<'a, T>(data: *const u8, len: T) -> &'a [u8]
+where
+ usize: TryFrom<T>,
+{
+ if data.is_null() {
+ &[]
+ } else if let Ok(len) = usize::try_from(len) {
+ #[allow(clippy::disallowed_methods)]
+ std::slice::from_raw_parts(data, len)
+ } else {
+ panic!("null_safe_slice: size overflow");
}
}
diff --git a/third_party/rust/neqo-crypto/src/once.rs b/third_party/rust/neqo-crypto/src/once.rs
deleted file mode 100644
index 80657cfe26..0000000000
--- a/third_party/rust/neqo-crypto/src/once.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::sync::Once;
-
-#[allow(clippy::module_name_repetitions)]
-pub struct OnceResult<T> {
- once: Once,
- v: Option<T>,
-}
-
-impl<T> OnceResult<T> {
- #[must_use]
- pub const fn new() -> Self {
- Self {
- once: Once::new(),
- v: None,
- }
- }
-
- pub fn call_once<F: FnOnce() -> T>(&mut self, f: F) -> &T {
- let v = &mut self.v;
- self.once.call_once(|| {
- *v = Some(f());
- });
- self.v.as_ref().unwrap()
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::OnceResult;
-
- static mut STATIC_ONCE_RESULT: OnceResult<u64> = OnceResult::new();
-
- #[test]
- fn static_update() {
- assert_eq!(*unsafe { STATIC_ONCE_RESULT.call_once(|| 23) }, 23);
- assert_eq!(*unsafe { STATIC_ONCE_RESULT.call_once(|| 24) }, 23);
- }
-}
diff --git a/third_party/rust/neqo-crypto/src/p11.rs b/third_party/rust/neqo-crypto/src/p11.rs
index 508d240062..5552882e2e 100644
--- a/third_party/rust/neqo-crypto/src/p11.rs
+++ b/third_party/rust/neqo-crypto/src/p11.rs
@@ -10,7 +10,7 @@
#![allow(non_snake_case)]
use std::{
- convert::TryFrom,
+ cell::RefCell,
mem,
ops::{Deref, DerefMut},
os::raw::{c_int, c_uint},
@@ -19,7 +19,10 @@ use std::{
use neqo_common::hex_with_len;
-use crate::err::{secstatus_to_res, Error, Res};
+use crate::{
+ err::{secstatus_to_res, Error, Res},
+ null_safe_slice,
+};
#[allow(clippy::upper_case_acronyms)]
#[allow(clippy::unreadable_literal)]
@@ -139,7 +142,6 @@ impl PrivateKey {
/// When the values are too large to fit. So never.
pub fn key_data(&self) -> Res<Vec<u8>> {
let mut key_item = Item::make_empty();
- #[allow(clippy::useless_conversion)] // TODO: Remove when we bump the MSRV to 1.74.0.
secstatus_to_res(unsafe {
PK11_ReadRawAttribute(
PK11ObjectType::PK11_TypePrivKey,
@@ -148,9 +150,7 @@ impl PrivateKey {
&mut key_item,
)
})?;
- let slc = unsafe {
- std::slice::from_raw_parts(key_item.data, usize::try_from(key_item.len).unwrap())
- };
+ let slc = unsafe { null_safe_slice(key_item.data, key_item.len) };
let key = Vec::from(slc);
// The data that `key_item` refers to needs to be freed, but we can't
// use the scoped `Item` implementation. This is OK as long as nothing
@@ -206,7 +206,7 @@ impl SymKey {
// This is accessing a value attached to the key, so we can treat this as a borrow.
match unsafe { key_item.as_mut() } {
None => Err(Error::InternalError),
- Some(key) => Ok(unsafe { std::slice::from_raw_parts(key.data, key.len as usize) }),
+ Some(key) => Ok(unsafe { null_safe_slice(key.data, key.len) }),
}
}
}
@@ -285,36 +285,112 @@ impl Item {
let b = self.ptr.as_ref().unwrap();
// Sanity check the type, as some types don't count bytes in `Item::len`.
assert_eq!(b.type_, SECItemType::siBuffer);
- let slc = std::slice::from_raw_parts(b.data, usize::try_from(b.len).unwrap());
+ let slc = null_safe_slice(b.data, b.len);
Vec::from(slc)
}
}
-/// Generate a randomized buffer.
+/// Fill a buffer with randomness.
///
/// # Panics
///
/// When `size` is too large or NSS fails.
-#[must_use]
-pub fn random(size: usize) -> Vec<u8> {
- let mut buf = vec![0; size];
- secstatus_to_res(unsafe {
- PK11_GenerateRandom(buf.as_mut_ptr(), c_int::try_from(buf.len()).unwrap())
- })
- .unwrap();
+pub fn randomize<B: AsMut<[u8]>>(mut buf: B) -> B {
+ let m_buf = buf.as_mut();
+ let len = c_int::try_from(m_buf.len()).unwrap();
+ secstatus_to_res(unsafe { PK11_GenerateRandom(m_buf.as_mut_ptr(), len) }).unwrap();
buf
}
+struct RandomCache {
+ cache: [u8; Self::SIZE],
+ used: usize,
+}
+
+impl RandomCache {
+ const SIZE: usize = 256;
+ const CUTOFF: usize = 32;
+
+ fn new() -> Self {
+ RandomCache {
+ cache: [0; Self::SIZE],
+ used: Self::SIZE,
+ }
+ }
+
+ fn randomize<B: AsMut<[u8]>>(&mut self, mut buf: B) -> B {
+ let m_buf = buf.as_mut();
+ debug_assert!(m_buf.len() <= Self::CUTOFF);
+ let avail = Self::SIZE - self.used;
+ if m_buf.len() <= avail {
+ m_buf.copy_from_slice(&self.cache[self.used..self.used + m_buf.len()]);
+ self.used += m_buf.len();
+ } else {
+ if avail > 0 {
+ m_buf[..avail].copy_from_slice(&self.cache[self.used..]);
+ }
+ randomize(&mut self.cache[..]);
+ self.used = m_buf.len() - avail;
+ m_buf[avail..].copy_from_slice(&self.cache[..self.used]);
+ }
+ buf
+ }
+}
+
+/// Generate a randomized array.
+///
+/// # Panics
+///
+/// When `size` is too large or NSS fails.
+#[must_use]
+pub fn random<const N: usize>() -> [u8; N] {
+ thread_local!(static CACHE: RefCell<RandomCache> = RefCell::new(RandomCache::new()));
+
+ let buf = [0; N];
+ if N <= RandomCache::CUTOFF {
+ CACHE.with_borrow_mut(|c| c.randomize(buf))
+ } else {
+ randomize(buf)
+ }
+}
+
#[cfg(test)]
mod test {
use test_fixture::fixture_init;
- use super::random;
+ use super::RandomCache;
+ use crate::{random, randomize};
#[test]
fn randomness() {
fixture_init();
- // If this ever fails, there is either a bug, or it's time to buy a lottery ticket.
- assert_ne!(random(16), random(16));
+ // If any of these ever fail, there is either a bug, or it's time to buy a lottery ticket.
+ assert_ne!(random::<16>(), randomize([0; 16]));
+ assert_ne!([0; 16], random::<16>());
+ assert_ne!([0; 64], random::<64>());
+ }
+
+ #[test]
+ fn cache_random_lengths() {
+ const ZERO: [u8; 256] = [0; 256];
+
+ fixture_init();
+ let mut cache = RandomCache::new();
+ let mut buf = [0; 256];
+ let bits = usize::BITS - (RandomCache::CUTOFF - 1).leading_zeros();
+ let mask = 0xff >> (u8::BITS - bits);
+
+ for _ in 0..100 {
+ let len = loop {
+ let len = usize::from(random::<1>()[0] & mask) + 1;
+ if len <= RandomCache::CUTOFF {
+ break len;
+ }
+ };
+ buf.fill(0);
+ if len >= 16 {
+ assert_ne!(&cache.randomize(&mut buf[..len])[..len], &ZERO[..len]);
+ }
+ }
}
}
diff --git a/third_party/rust/neqo-crypto/src/replay.rs b/third_party/rust/neqo-crypto/src/replay.rs
index d4d3677f5c..5fd6fd1250 100644
--- a/third_party/rust/neqo-crypto/src/replay.rs
+++ b/third_party/rust/neqo-crypto/src/replay.rs
@@ -5,7 +5,6 @@
// except according to those terms.
use std::{
- convert::{TryFrom, TryInto},
ops::{Deref, DerefMut},
os::raw::c_uint,
ptr::null_mut,
diff --git a/third_party/rust/neqo-crypto/src/selfencrypt.rs b/third_party/rust/neqo-crypto/src/selfencrypt.rs
index b8a63153fd..1130c35250 100644
--- a/third_party/rust/neqo-crypto/src/selfencrypt.rs
+++ b/third_party/rust/neqo-crypto/src/selfencrypt.rs
@@ -82,7 +82,7 @@ impl SelfEncrypt {
// opaque aead_encrypted(plaintext)[length as expanded];
// };
// AAD covers the entire header, plus the value of the AAD parameter that is provided.
- let salt = random(Self::SALT_LENGTH);
+ let salt = random::<{ Self::SALT_LENGTH }>();
let cipher = self.make_aead(&self.key, &salt)?;
let encoded_len = 2 + salt.len() + plaintext.len() + cipher.expansion();
diff --git a/third_party/rust/neqo-crypto/src/time.rs b/third_party/rust/neqo-crypto/src/time.rs
index 84dbfdb4a5..0e59c4f5e2 100644
--- a/third_party/rust/neqo-crypto/src/time.rs
+++ b/third_party/rust/neqo-crypto/src/time.rs
@@ -7,18 +7,16 @@
#![allow(clippy::upper_case_acronyms)]
use std::{
- boxed::Box,
- convert::{TryFrom, TryInto},
ops::Deref,
os::raw::c_void,
pin::Pin,
+ sync::OnceLock,
time::{Duration, Instant},
};
use crate::{
agentio::as_c_void,
err::{Error, Res},
- once::OnceResult,
ssl::{PRFileDesc, SSLTimeFunc},
};
@@ -67,14 +65,13 @@ impl TimeZero {
}
}
-static mut BASE_TIME: OnceResult<TimeZero> = OnceResult::new();
+static BASE_TIME: OnceLock<TimeZero> = OnceLock::new();
fn get_base() -> &'static TimeZero {
- let f = || TimeZero {
+ BASE_TIME.get_or_init(|| TimeZero {
instant: Instant::now(),
prtime: unsafe { PR_Now() },
- };
- unsafe { BASE_TIME.call_once(f) }
+ })
}
pub(crate) fn init() {
@@ -97,9 +94,8 @@ impl Deref for Time {
impl From<Instant> for Time {
/// Convert from an Instant into a Time.
fn from(t: Instant) -> Self {
- // Call `TimeZero::baseline(t)` so that time zero can be set.
- let f = || TimeZero::baseline(t);
- _ = unsafe { BASE_TIME.call_once(f) };
+ // Initialize `BASE_TIME` using `TimeZero::baseline(t)`.
+ BASE_TIME.get_or_init(|| TimeZero::baseline(t));
Self { t }
}
}
@@ -108,14 +104,17 @@ impl TryFrom<PRTime> for Time {
type Error = Error;
fn try_from(prtime: PRTime) -> Res<Self> {
let base = get_base();
- if let Some(delta) = prtime.checked_sub(base.prtime) {
- let d = Duration::from_micros(delta.try_into()?);
- base.instant
- .checked_add(d)
- .map_or(Err(Error::TimeTravelError), |t| Ok(Self { t }))
+ let delta = prtime
+ .checked_sub(base.prtime)
+ .ok_or(Error::TimeTravelError)?;
+ let d = Duration::from_micros(u64::try_from(delta.abs())?);
+ let t = if delta >= 0 {
+ base.instant.checked_add(d)
} else {
- Err(Error::TimeTravelError)
- }
+ base.instant.checked_sub(d)
+ };
+ let t = t.ok_or(Error::TimeTravelError)?;
+ Ok(Self { t })
}
}
@@ -123,14 +122,21 @@ impl TryInto<PRTime> for Time {
type Error = Error;
fn try_into(self) -> Res<PRTime> {
let base = get_base();
- let delta = self
- .t
- .checked_duration_since(base.instant)
- .ok_or(Error::TimeTravelError)?;
- if let Ok(d) = PRTime::try_from(delta.as_micros()) {
- d.checked_add(base.prtime).ok_or(Error::TimeTravelError)
+
+ if let Some(delta) = self.t.checked_duration_since(base.instant) {
+ if let Ok(d) = PRTime::try_from(delta.as_micros()) {
+ d.checked_add(base.prtime).ok_or(Error::TimeTravelError)
+ } else {
+ Err(Error::TimeTravelError)
+ }
} else {
- Err(Error::TimeTravelError)
+ // Try to go backwards from the base time.
+ let backwards = base.instant - self.t; // infallible
+ if let Ok(d) = PRTime::try_from(backwards.as_micros()) {
+ base.prtime.checked_sub(d).ok_or(Error::TimeTravelError)
+ } else {
+ Err(Error::TimeTravelError)
+ }
}
}
}
@@ -207,10 +213,7 @@ impl Default for TimeHolder {
#[cfg(test)]
mod test {
- use std::{
- convert::{TryFrom, TryInto},
- time::{Duration, Instant},
- };
+ use std::time::{Duration, Instant};
use super::{get_base, init, Interval, PRTime, Time};
use crate::err::Res;
@@ -228,16 +231,23 @@ mod test {
}
#[test]
- fn past_time() {
+ fn past_prtime() {
+ const DELTA: Duration = Duration::from_secs(1);
init();
let base = get_base();
- assert!(Time::try_from(base.prtime - 1).is_err());
+ let delta_micros = PRTime::try_from(DELTA.as_micros()).unwrap();
+ println!("{} - {}", base.prtime, delta_micros);
+ let t = Time::try_from(base.prtime - delta_micros).unwrap();
+ assert_eq!(Instant::from(t) + DELTA, base.instant);
}
#[test]
- fn negative_time() {
+ fn past_instant() {
+ const DELTA: Duration = Duration::from_secs(1);
init();
- assert!(Time::try_from(-1).is_err());
+ let base = get_base();
+ let t = Time::from(base.instant.checked_sub(DELTA).unwrap());
+ assert_eq!(Instant::from(t) + DELTA, base.instant);
}
#[test]
diff --git a/third_party/rust/neqo-crypto/tests/aead.rs b/third_party/rust/neqo-crypto/tests/aead.rs
index 0ee1e66c38..5cf0034aec 100644
--- a/third_party/rust/neqo-crypto/tests/aead.rs
+++ b/third_party/rust/neqo-crypto/tests/aead.rs
@@ -1,4 +1,9 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
#![warn(clippy::pedantic)]
#![cfg(not(feature = "fuzzing"))]
diff --git a/third_party/rust/neqo-crypto/tests/agent.rs b/third_party/rust/neqo-crypto/tests/agent.rs
index c2c83c467c..80bf816930 100644
--- a/third_party/rust/neqo-crypto/tests/agent.rs
+++ b/third_party/rust/neqo-crypto/tests/agent.rs
@@ -1,7 +1,8 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(clippy::pedantic)]
-
-use std::boxed::Box;
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
use neqo_crypto::{
generate_ech_keys, AuthenticationStatus, Client, Error, HandshakeState, SecretAgentPreInfo,
diff --git a/third_party/rust/neqo-crypto/tests/ext.rs b/third_party/rust/neqo-crypto/tests/ext.rs
index 9ae81133f5..c8732dd014 100644
--- a/third_party/rust/neqo-crypto/tests/ext.rs
+++ b/third_party/rust/neqo-crypto/tests/ext.rs
@@ -1,5 +1,8 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(clippy::pedantic)]
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
use std::{cell::RefCell, rc::Rc};
diff --git a/third_party/rust/neqo-crypto/tests/handshake.rs b/third_party/rust/neqo-crypto/tests/handshake.rs
index b2d8b9cc34..3cb31337fd 100644
--- a/third_party/rust/neqo-crypto/tests/handshake.rs
+++ b/third_party/rust/neqo-crypto/tests/handshake.rs
@@ -1,4 +1,12 @@
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
#![allow(dead_code)]
+#![allow(clippy::missing_panics_doc)]
+#![allow(clippy::missing_errors_doc)]
use std::{mem, time::Instant};
@@ -127,6 +135,7 @@ fn zero_rtt_setup(
}
}
+#[must_use]
pub fn resumption_setup(mode: Resumption) -> (Option<AntiReplay>, ResumptionToken) {
fixture_init();
diff --git a/third_party/rust/neqo-crypto/tests/hkdf.rs b/third_party/rust/neqo-crypto/tests/hkdf.rs
index b4dde482f8..acb5bbdda8 100644
--- a/third_party/rust/neqo-crypto/tests/hkdf.rs
+++ b/third_party/rust/neqo-crypto/tests/hkdf.rs
@@ -1,5 +1,8 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(clippy::pedantic)]
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
use neqo_crypto::{
constants::{
diff --git a/third_party/rust/neqo-crypto/tests/hp.rs b/third_party/rust/neqo-crypto/tests/hp.rs
index 43b96869d8..da7df2cc19 100644
--- a/third_party/rust/neqo-crypto/tests/hp.rs
+++ b/third_party/rust/neqo-crypto/tests/hp.rs
@@ -1,5 +1,8 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(clippy::pedantic)]
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
use std::mem;
diff --git a/third_party/rust/neqo-crypto/tests/init.rs b/third_party/rust/neqo-crypto/tests/init.rs
index 21291ceebb..13218cc340 100644
--- a/third_party/rust/neqo-crypto/tests/init.rs
+++ b/third_party/rust/neqo-crypto/tests/init.rs
@@ -1,5 +1,8 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(clippy::pedantic)]
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
// This uses external interfaces to neqo_crypto rather than being a module
// inside of lib.rs. Because all other code uses the test_fixture module,
diff --git a/third_party/rust/neqo-crypto/tests/selfencrypt.rs b/third_party/rust/neqo-crypto/tests/selfencrypt.rs
index fd9d4ea1ea..4c574a3ae9 100644
--- a/third_party/rust/neqo-crypto/tests/selfencrypt.rs
+++ b/third_party/rust/neqo-crypto/tests/selfencrypt.rs
@@ -1,5 +1,9 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
-#![warn(clippy::pedantic)]
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
#![cfg(not(feature = "fuzzing"))]
use neqo_crypto::{