Project import generated by Copybara.
GitOrigin-RevId: d155d244483601de47cc7fa92377e0c0f64ee50f
Change-Id: I1e5ee744d3750f570848892200c4b610455a08c4
diff --git a/nearby/Cargo.lock b/nearby/Cargo.lock
index 31aaf06..25a6104 100644
--- a/nearby/Cargo.lock
+++ b/nearby/Cargo.lock
@@ -74,9 +74,9 @@
[[package]]
name = "anstream"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450"
+checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -123,9 +123,9 @@
[[package]]
name = "anyhow"
-version = "1.0.70"
+version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "array_ref"
@@ -221,9 +221,9 @@
[[package]]
name = "bumpalo"
-version = "3.12.1"
+version = "3.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
+checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b"
[[package]]
name = "byteorder"
@@ -272,9 +272,9 @@
[[package]]
name = "ciborium"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f"
+checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
dependencies = [
"ciborium-io",
"ciborium-ll",
@@ -283,15 +283,15 @@
[[package]]
name = "ciborium-io"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369"
+checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
[[package]]
name = "ciborium-ll"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b"
+checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
dependencies = [
"ciborium-io",
"half",
@@ -309,9 +309,9 @@
[[package]]
name = "clap"
-version = "3.2.23"
+version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
+checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"bitflags",
"clap_lex 0.2.4",
@@ -321,9 +321,9 @@
[[package]]
name = "clap"
-version = "4.2.4"
+version = "4.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62"
+checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938"
dependencies = [
"clap_builder",
"clap_derive",
@@ -332,9 +332,9 @@
[[package]]
name = "clap_builder"
-version = "4.2.4"
+version = "4.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749"
+checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd"
dependencies = [
"anstream",
"anstyle",
@@ -420,7 +420,7 @@
"atty",
"cast",
"ciborium",
- "clap 3.2.23",
+ "clap 3.2.25",
"criterion-plot",
"itertools",
"lazy_static",
@@ -491,9 +491,9 @@
[[package]]
name = "crypto-bigint"
-version = "0.5.1"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c2538c4e68e52548bacb3e83ac549f903d44f011ac9d5abb5e132e67d0808f7"
+checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15"
dependencies = [
"generic-array",
"rand_core 0.6.4",
@@ -519,15 +519,9 @@
"criterion",
"crypto_provider_openssl",
"crypto_provider_rustcrypto",
- "hex",
"hex-literal",
"rand",
"rand_ext",
- "rstest",
- "rstest_reuse",
- "sha2",
- "test_helper",
- "wycheproof",
]
[[package]]
@@ -556,6 +550,7 @@
dependencies = [
"cfg-if",
"crypto_provider",
+ "crypto_provider_test",
"hex-literal",
"openssl",
"ouroboros",
@@ -573,6 +568,7 @@
"cfg-if",
"crypto_provider",
"crypto_provider_rustcrypto",
+ "crypto_provider_test",
"ctr",
"ed25519-dalek",
"hex",
@@ -596,6 +592,21 @@
]
[[package]]
+name = "crypto_provider_test"
+version = "0.1.0"
+dependencies = [
+ "crypto_provider",
+ "hex",
+ "hex-literal",
+ "rand",
+ "rand_ext",
+ "rstest",
+ "rstest_reuse",
+ "test_helper",
+ "wycheproof",
+]
+
+[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -621,9 +632,9 @@
[[package]]
name = "der"
-version = "0.7.4"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b14af2045fa69ed2b7a48934bebb842d0f33e73e96e78766ecb14bb5347a11"
+checksum = "05e58dffcdcc8ee7b22f0c1f71a69243d7c2d9ad87b5a14361f2424a1565c219"
dependencies = [
"const-oid",
"zeroize",
@@ -754,9 +765,9 @@
[[package]]
name = "flate2"
-version = "1.0.25"
+version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -1082,9 +1093,9 @@
[[package]]
name = "js-sys"
-version = "0.3.61"
+version = "0.3.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5"
dependencies = [
"wasm-bindgen",
]
@@ -1106,7 +1117,7 @@
"anyhow",
"base64 0.21.0",
"blake2",
- "clap 4.2.4",
+ "clap 4.2.7",
"criterion",
"crypto_provider",
"crypto_provider_default",
@@ -1158,9 +1169,9 @@
[[package]]
name = "libc"
-version = "0.2.142"
+version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
[[package]]
name = "libm"
@@ -1170,9 +1181,9 @@
[[package]]
name = "linux-raw-sys"
-version = "0.3.4"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf"
+checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
[[package]]
name = "lock_api"
@@ -1216,9 +1227,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.6.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
@@ -1310,9 +1321,9 @@
[[package]]
name = "openssl"
-version = "0.10.51"
+version = "0.10.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97ea2d98598bf9ada7ea6ee8a30fb74f9156b63bbe495d64ec2b87c269d2dda3"
+checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56"
dependencies = [
"bitflags",
"cfg-if",
@@ -1336,9 +1347,9 @@
[[package]]
name = "openssl-sys"
-version = "0.9.86"
+version = "0.9.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "992bac49bdbab4423199c654a5515bd2a6c6a23bf03f2dd3bdb7e5ae6259bc69"
+checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
dependencies = [
"bssl-sys",
"cc",
@@ -1420,9 +1431,9 @@
[[package]]
name = "pkg-config"
-version = "0.3.26"
+version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
+checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "platforms"
@@ -1571,9 +1582,9 @@
[[package]]
name = "quote"
-version = "1.0.26"
+version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
dependencies = [
"proc-macro2",
]
@@ -1642,6 +1653,12 @@
]
[[package]]
+name = "raw-parts"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1e22ce49f28be0887a992cf42172c8c75facdb74e3e1a7eb0f459cf2fcc95d7"
+
+[[package]]
name = "rayon"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1738,9 +1755,9 @@
[[package]]
name = "rustix"
-version = "0.37.14"
+version = "0.37.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b864d3c18a5785a05953adeed93e2dca37ed30f18e69bba9f30079d51f363f"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
dependencies = [
"bitflags",
"errno",
@@ -1792,18 +1809,18 @@
[[package]]
name = "serde"
-version = "1.0.160"
+version = "1.0.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
+checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.160"
+version = "1.0.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
+checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
dependencies = [
"proc-macro2",
"quote",
@@ -1864,9 +1881,9 @@
[[package]]
name = "spki"
-version = "0.7.1"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e"
+checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
dependencies = [
"base64ct",
"der",
@@ -1980,6 +1997,7 @@
"log",
"rand",
"rand_chacha",
+ "raw-parts",
"spin 0.9.8",
"ukey2_connections",
"ukey2_rs",
@@ -2047,7 +2065,7 @@
name = "ukey2_shell"
version = "0.1.0"
dependencies = [
- "clap 4.2.4",
+ "clap 4.2.7",
"crypto_provider_rustcrypto",
"ukey2_connections",
"ukey2_rs",
@@ -2105,9 +2123,9 @@
[[package]]
name = "wasm-bindgen"
-version = "0.2.84"
+version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -2115,24 +2133,24 @@
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.84"
+version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.15",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.84"
+version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2140,28 +2158,28 @@
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.84"
+version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.15",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.84"
+version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb"
[[package]]
name = "web-sys"
-version = "0.3.61"
+version = "0.3.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
+checksum = "16b5f940c7edfdc6d12126d98c9ef4d1b3d470011c47c76a6581df47ad9ba721"
dependencies = [
"js-sys",
"wasm-bindgen",
diff --git a/nearby/Cargo.toml b/nearby/Cargo.toml
index 8ede0df..3cd9715 100644
--- a/nearby/Cargo.toml
+++ b/nearby/Cargo.toml
@@ -6,7 +6,6 @@
"connections/ukey2/ukey2_jni",
"connections/ukey2/ukey2_proto",
"connections/ukey2/ukey2_shell",
- # placeholder bssl-crypto crate
"crypto/bssl-crypto",
"crypto/crypto_provider",
"crypto/crypto_provider_openssl",
@@ -36,6 +35,7 @@
crypto_provider_rustcrypto = { path = "crypto/crypto_provider_rustcrypto" }
crypto_provider_stubs = { path = "crypto/crypto_provider_stubs" }
crypto_provider_default = {path = "crypto/crypto_provider_default" }
+crypto_provider_test = { path = "crypto/crypto_provider_test" }
rand_core_05_adapter = { path = "crypto/rand_core_05_adapter" }
rand_ext = { path = "presence/rand_ext" }
test_helper = { path = "presence/test_helper" }
@@ -84,6 +84,9 @@
hdrhistogram = "7.5.0"
regex = "1.7.0"
xts-mode = "0.5.1"
+rstest = "0.16.0"
+rstest_reuse = "0.5.0"
+wycheproof = "0.4.0"
[workspace.package]
version = "0.1.0"
diff --git a/nearby/Dockerfile b/nearby/Dockerfile
index 7a32b21..b4fdab0 100644
--- a/nearby/Dockerfile
+++ b/nearby/Dockerfile
@@ -31,7 +31,9 @@
--rev f6affa68e950275f9fd773f2646ab7ee4db82897 \
--color never 2>&1
# needed for generating boringssl bindings
-RUN cargo install bindgen-cli
+# Must use 0.64.0, as version >= 0.65.0 removes the option "--size_t-is-usize", an option
+# used by boringssl when generating rust bindings
+RUN cargo install bindgen-cli --version 0.64.0
RUN rustup toolchain add nightly
RUN curl -L https://go.dev/dl/go1.20.2.linux-amd64.tar.gz | tar -C /usr/local -xz
ENV PATH="$PATH:/usr/local/go/bin"
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml b/nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml
index ec58e9a..9a9e43a 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml
+++ b/nearby/connections/ukey2/ukey2_c_ffi/Cargo.toml
@@ -16,6 +16,7 @@
rand.workspace = true
rand_chacha.workspace = true
spin.workspace = true
+raw-parts = "1.1.2"
[features]
default = ["rustcrypto"]
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/CMakeLists.txt b/nearby/connections/ukey2/ukey2_c_ffi/cpp/CMakeLists.txt
new file mode 100644
index 0000000..79cdcac
--- /dev/null
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/CMakeLists.txt
@@ -0,0 +1,62 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.14)
+
+enable_testing()
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/ukey2_c_ffi/cpp/)
+
+include(ExternalProject)
+set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/target/tmp)
+ExternalProject_Add(
+ ukey2_c_ffi
+ DOWNLOAD_COMMAND ""
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND cargo build COMMAND cargo build --release --lib
+ BINARY_DIR "${CMAKE_SOURCE_DIR}/ukey2_c_ffi"
+ INSTALL_COMMAND "")
+
+# GoogleTest requires at least C++14
+set(CMAKE_CXX_STANDARD 14)
+add_compile_options(-Wall -Werror -Wextra -Wimplicit-fallthrough -Wextra-semi
+ -Wunreachable-code-aggressive -Wthread-safety
+ -Wno-missing-field-initializers -Wno-unused-parameter -Wno-psabi
+ -Wloop-analysis -Wno-unneeded-internal-declaration
+ -Wenum-compare-conditional -Wno-ignored-pragma-optimize
+ -Wno-bitfield-constant-conversion -Wno-deprecated-this-capture -Wshadow
+ -Wsign-compare)
+
+include(FetchContent)
+FetchContent_Declare(
+ googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG release-1.12.1
+)
+FetchContent_MakeAvailable(googletest)
+
+add_executable(ffi_test
+ ukey2_test.cc
+ ukey2_glue.cc
+ ukey2_ffi.h
+ ukey2_bindings.h)
+
+target_link_libraries(ffi_test
+ "${CMAKE_SOURCE_DIR}/../../../../target/release/libukey2_c_ffi${CMAKE_SHARED_LIBRARY_SUFFIX}"
+ GTest::gtest_main
+ dl pthread)
+
+include(GoogleTest)
+gtest_discover_tests(ffi_test)
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/Makefile b/nearby/connections/ukey2/ukey2_c_ffi/cpp/Makefile
deleted file mode 100644
index b5fd106..0000000
--- a/nearby/connections/ukey2/ukey2_c_ffi/cpp/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2023 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-C_SRCS := ukey2_glue.cc
-CC = clang++
-UNAME := $(shell uname -s)
-ifeq ($(UNAME),Darwin)
- FFI_LIB = ../../../../target/release/libukey2_c_ffi.dylib
-else
- FFI_LIB = ../../../../target/release/libukey2_c_ffi.so
-endif
-ukey2:
- cargo build --release
- rm -rf build
- mkdir build
- $(CC) $(C_SRCS) $(FFI_LIB) -o build/ukey2
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h
index a0cb87f..b14450c 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_bindings.h
@@ -29,6 +29,7 @@
typedef struct {
uint8_t* handle;
size_t len;
+ size_t cap;
} RustFFIByteArray;
typedef struct {
@@ -59,7 +60,6 @@
// Common handshake methods
bool is_handshake_complete(Ukey2HandshakeContextHandle handle);
RustFFIByteArray get_next_handshake_message(Ukey2HandshakeContextHandle handle);
-bool can_send_payload_in_handshake_message(Ukey2HandshakeContextHandle handle);
RustFFIByteArray parse_handshake_message(Ukey2HandshakeContextHandle handle, CFFIByteArray message);
Ukey2ConnectionContextHandle to_connection_context(Ukey2HandshakeContextHandle handle);
RustFFIByteArray get_verification_string(Ukey2HandshakeContextHandle handle, size_t output_length);
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h
index e96ae1c..2beae24 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_ffi.h
@@ -50,7 +50,7 @@
private:
friend class Ukey2Handshake;
- D2DConnectionContextV1(Ukey2ConnectionContextHandle handle) : handle_(handle) {};
+ D2DConnectionContextV1(Ukey2ConnectionContextHandle handle) : handle_(handle) {}
const Ukey2ConnectionContextHandle handle_;
};
@@ -68,12 +68,10 @@
static Ukey2Handshake ForInitiator();
// Returns true if the handshake is complete, false otherwise.
bool IsHandshakeComplete();
- // Return if the handshake message can carry a payload.
- bool CanSendPayloadInHandshakeMessage();
// Returns raw byte data with the message to send over the wire.
std::string GetNextHandshakeMessage();
// Parses the raw handshake message received over the wire.
- std::string ParseHandshakeMessage(std::string message);
+ void ParseHandshakeMessage(std::string message);
// Returns the authentication string of length output_length to be confirmed on both devices.
std::string GetVerificationString(size_t output_length);
// Turns this Ukey2Handshake instance into a D2DConnectionContextV1. This method once called,
@@ -81,6 +79,6 @@
D2DConnectionContextV1 ToConnectionContext();
private:
- Ukey2Handshake(Ukey2HandshakeContextHandle handle) : handle_(handle) {};
+ Ukey2Handshake(Ukey2HandshakeContextHandle handle) : handle_(handle) {}
const Ukey2HandshakeContextHandle handle_;
};
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc
index e013b2a..6f4a396 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_glue.cc
@@ -15,17 +15,10 @@
#include "ukey2_bindings.h"
#include "ukey2_ffi.h"
+#include <cassert>
#include <cstring>
-#include <iostream>
#include <string>
-CFFIByteArray messageToByteArray(const std::string message) {
- return {
- .handle = (uint8_t*) (new std::string(message))->c_str(),
- .len = message.length(),
- };
-}
-
CFFIByteArray nullByteArray() {
return {
.handle = nullptr,
@@ -46,10 +39,6 @@
return is_handshake_complete(handle_);
}
-bool Ukey2Handshake::CanSendPayloadInHandshakeMessage() {
- return can_send_payload_in_handshake_message(handle_);
-}
-
std::string Ukey2Handshake::GetNextHandshakeMessage() {
RustFFIByteArray array = get_next_handshake_message(handle_);
std::string ret = std::string((const char*) array.handle, array.len);
@@ -57,11 +46,12 @@
return ret;
}
-std::string Ukey2Handshake::ParseHandshakeMessage(std::string message) {
- RustFFIByteArray array = parse_handshake_message(handle_, messageToByteArray(message));
- std::string ret = std::string((const char*) array.handle, array.len);
- rust_dealloc_ffi_byte_array(array);
- return ret;
+void Ukey2Handshake::ParseHandshakeMessage(std::string message) {
+ CFFIByteArray messageRaw{
+ .handle = (uint8_t*)message.c_str(),
+ .len = message.length(),
+ };
+ parse_handshake_message(handle_, messageRaw);
}
std::string Ukey2Handshake::GetVerificationString(size_t output_length) {
@@ -77,14 +67,35 @@
}
std::string D2DConnectionContextV1::DecodeMessageFromPeer(std::string message, std::string associated_data) {
- RustFFIByteArray array = decode_message_from_peer(handle_, messageToByteArray(message), messageToByteArray(associated_data));
+ CFFIByteArray messageRaw{
+ .handle = (uint8_t*)message.c_str(),
+ .len = message.length(),
+ };
+ CFFIByteArray associatedDataRaw{
+ .handle = (uint8_t*)associated_data.c_str(),
+ .len = associated_data.length(),
+ };
+ RustFFIByteArray array =
+ decode_message_from_peer(handle_, messageRaw, associatedDataRaw);
+ if (array.handle == nullptr) {
+ return "";
+ }
std::string ret = std::string((const char*) array.handle, array.len);
rust_dealloc_ffi_byte_array(array);
return ret;
}
std::string D2DConnectionContextV1::EncodeMessageToPeer(std::string message, std::string associated_data) {
- RustFFIByteArray array = encode_message_to_peer(handle_, messageToByteArray(message), messageToByteArray(associated_data));
+ CFFIByteArray messageRaw{
+ .handle = (uint8_t*)message.c_str(),
+ .len = message.length(),
+ };
+ CFFIByteArray associatedDataRaw{
+ .handle = (uint8_t*)associated_data.c_str(),
+ .len = associated_data.length(),
+ };
+ RustFFIByteArray array =
+ encode_message_to_peer(handle_, messageRaw, associatedDataRaw);
std::string ret = std::string((const char*) array.handle, array.len);
rust_dealloc_ffi_byte_array(array);
return ret;
@@ -113,7 +124,11 @@
}
D2DRestoreConnectionContextV1Result D2DConnectionContextV1::FromSavedSession(std::string data) {
- auto result = from_saved_session(messageToByteArray(data));
+ CFFIByteArray arr{
+ .handle = (uint8_t*)data.c_str(),
+ .len = data.length(),
+ };
+ auto result = from_saved_session(arr);
return {
D2DConnectionContextV1(result.handle),
result.status,
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_test.cc b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_test.cc
new file mode 100644
index 0000000..98ea07e
--- /dev/null
+++ b/nearby/connections/ukey2/ukey2_c_ffi/cpp/ukey2_test.cc
@@ -0,0 +1,90 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+
+#include <gtest/gtest.h>
+#include "ukey2_ffi.h"
+
+namespace {
+TEST(Ukey2RustTest, HandshakeStartsIncomplete) {
+ Ukey2Handshake responder_handle = Ukey2Handshake::ForResponder();
+ Ukey2Handshake initiator_handle = Ukey2Handshake::ForInitiator();
+ ASSERT_FALSE(responder_handle.IsHandshakeComplete());
+ ASSERT_FALSE(initiator_handle.IsHandshakeComplete());
+}
+
+TEST(Ukey2RustTest, HandshakeComplete) {
+ Ukey2Handshake responder_handle = Ukey2Handshake::ForResponder();
+ Ukey2Handshake initiator_handle = Ukey2Handshake::ForInitiator();
+ responder_handle.ParseHandshakeMessage(
+ initiator_handle.GetNextHandshakeMessage());
+ initiator_handle.ParseHandshakeMessage(
+ responder_handle.GetNextHandshakeMessage());
+ responder_handle.ParseHandshakeMessage(
+ initiator_handle.GetNextHandshakeMessage());
+ ASSERT_TRUE(responder_handle.IsHandshakeComplete());
+ ASSERT_TRUE(initiator_handle.IsHandshakeComplete());
+}
+
+TEST(Ukey2RustTest, CanSendReceiveMessage) {
+ Ukey2Handshake responder_handle = Ukey2Handshake::ForResponder();
+ Ukey2Handshake initiator_handle = Ukey2Handshake::ForInitiator();
+ responder_handle.ParseHandshakeMessage(
+ initiator_handle.GetNextHandshakeMessage());
+ initiator_handle.ParseHandshakeMessage(
+ responder_handle.GetNextHandshakeMessage());
+ responder_handle.ParseHandshakeMessage(
+ initiator_handle.GetNextHandshakeMessage());
+ ASSERT_TRUE(responder_handle.IsHandshakeComplete());
+ ASSERT_TRUE(initiator_handle.IsHandshakeComplete());
+ D2DConnectionContextV1 responder_connection =
+ responder_handle.ToConnectionContext();
+ D2DConnectionContextV1 initiator_connection =
+ initiator_handle.ToConnectionContext();
+ std::string message = "hello world";
+ auto encoded = responder_connection.EncodeMessageToPeer(message, "assocdata");
+ ASSERT_NE(encoded, "");
+ auto decoded =
+ initiator_connection.DecodeMessageFromPeer(encoded, "assocdata");
+ EXPECT_EQ(message, decoded);
+}
+
+TEST(Ukey2RustTest, TestSaveRestoreSession) {
+ Ukey2Handshake responder_handle = Ukey2Handshake::ForResponder();
+ Ukey2Handshake initiator_handle = Ukey2Handshake::ForInitiator();
+ responder_handle.ParseHandshakeMessage(
+ initiator_handle.GetNextHandshakeMessage());
+ initiator_handle.ParseHandshakeMessage(
+ responder_handle.GetNextHandshakeMessage());
+ responder_handle.ParseHandshakeMessage(
+ initiator_handle.GetNextHandshakeMessage());
+ ASSERT_TRUE(responder_handle.IsHandshakeComplete());
+ ASSERT_TRUE(initiator_handle.IsHandshakeComplete());
+ D2DConnectionContextV1 responder_connection =
+ responder_handle.ToConnectionContext();
+ D2DConnectionContextV1 initiator_connection =
+ initiator_handle.ToConnectionContext();
+ auto saved_responder = responder_connection.SaveSession();
+ D2DRestoreConnectionContextV1Result restore_result =
+ D2DConnectionContextV1::FromSavedSession(saved_responder);
+ ASSERT_EQ(restore_result.status,
+ CD2DRestoreConnectionContextV1Status::STATUS_GOOD);
+ auto new_responder = restore_result.handle;
+ std::string encoded = new_responder.EncodeMessageToPeer("hello world", "");
+ std::string decoded = initiator_connection.DecodeMessageFromPeer(encoded, "");
+ EXPECT_EQ("hello world", decoded);
+}
+
+} // namespace
diff --git a/nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs b/nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs
index 68d42c9..a044471 100644
--- a/nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs
+++ b/nearby/connections/ukey2/ukey2_c_ffi/src/lib.rs
@@ -13,13 +13,13 @@
// limitations under the License.
use std::collections::HashMap;
-use std::ffi::CString;
use std::ptr::null_mut;
use lazy_static::lazy_static;
use rand::Rng;
use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng;
+use raw_parts::RawParts;
use spin::Mutex;
use ukey2_connections::{
@@ -38,6 +38,7 @@
pub struct RustFFIByteArray {
ptr: *mut u8,
len: usize,
+ cap: usize,
}
#[repr(C)]
@@ -83,7 +84,12 @@
#[no_mangle]
pub unsafe extern "C" fn rust_dealloc_ffi_byte_array(arr: RustFFIByteArray) {
if !arr.ptr.is_null() {
- let _ = Vec::from_raw_parts(arr.ptr, arr.len, arr.len);
+ let raw_parts = RawParts {
+ ptr: arr.ptr,
+ length: arr.len,
+ capacity: arr.cap,
+ };
+ let _ = RawParts::into_vec(raw_parts);
}
}
@@ -104,16 +110,21 @@
.get(&handle)
.and_then(|c| c.get_next_handshake_message());
if let Some(msg) = opt_msg {
- let ret_len = msg.len();
- let data: CString = unsafe { CString::from_vec_unchecked(msg) };
+ let RawParts {
+ ptr,
+ length,
+ capacity,
+ } = RawParts::from_vec(msg);
RustFFIByteArray {
- ptr: data.into_raw() as *mut u8,
- len: ret_len,
+ ptr,
+ len: length,
+ cap: capacity,
}
} else {
RustFFIByteArray {
ptr: null_mut(),
len: usize::MAX,
+ cap: usize::MAX,
}
}
}
@@ -125,19 +136,20 @@
handle: u64,
arr: CFFIByteArray,
) -> RustFFIByteArray {
- let msg = Vec::<u8>::from_raw_parts(arr.ptr, arr.len, arr.len);
+ let msg = std::slice::from_raw_parts(arr.ptr, arr.len);
// TODO error handling
let result = HANDLE_MAPPING
.lock()
.get_mut(&handle)
.unwrap()
- .handle_handshake_message(msg.as_slice());
+ .handle_handshake_message(msg);
if let Err(error) = result {
log::error!("{:?}", error);
}
RustFFIByteArray {
ptr: null_mut(),
len: usize::MAX,
+ cap: usize::MAX,
}
}
@@ -153,10 +165,15 @@
.auth_string::<CryptoProvider>()
.derive_vec(length)
.unwrap();
- let vec_len = auth_vec.len();
+ let RawParts {
+ ptr,
+ length,
+ capacity,
+ } = RawParts::from_vec(auth_vec);
RustFFIByteArray {
- ptr: auth_vec.leak().as_mut_ptr(),
- len: vec_len,
+ ptr,
+ len: length,
+ cap: capacity,
}
})
.unwrap()
@@ -213,6 +230,7 @@
return RustFFIByteArray {
ptr: null_mut(),
len: usize::MAX,
+ cap: usize::MAX,
};
}
let msg = std::slice::from_raw_parts(msg.ptr, msg.len);
@@ -229,16 +247,22 @@
.get_mut(&handle)
.map(|c| c.encode_message_to_peer::<CryptoProvider, _>(msg, associated_data));
if let Some(msg) = ret {
- let len = msg.len();
+ let RawParts {
+ ptr,
+ length,
+ capacity,
+ } = RawParts::from_vec(msg);
RustFFIByteArray {
- ptr: msg.leak().as_mut_ptr(),
- len,
+ ptr,
+ len: length,
+ cap: capacity,
}
} else {
log::error!("Was unable to find handle!");
RustFFIByteArray {
ptr: null_mut(),
len: usize::MAX,
+ cap: usize::MAX,
}
}
}
@@ -248,13 +272,14 @@
#[no_mangle]
pub unsafe extern "C" fn decode_message_from_peer(
handle: u64,
- msg: RustFFIByteArray,
+ msg: CFFIByteArray,
associated_data: CFFIByteArray,
) -> RustFFIByteArray {
if msg.len == 0 {
return RustFFIByteArray {
ptr: null_mut(),
len: usize::MAX,
+ cap: usize::MAX,
};
}
let msg = std::slice::from_raw_parts(msg.ptr, msg.len);
@@ -272,15 +297,21 @@
.unwrap()
.decode_message_from_peer::<CryptoProvider, _>(msg, associated_data);
if let Ok(decoded) = ret {
- let len = decoded.len();
+ let RawParts {
+ ptr,
+ length,
+ capacity,
+ } = RawParts::from_vec(decoded);
RustFFIByteArray {
- ptr: decoded.leak().as_mut_ptr(),
- len,
+ ptr,
+ len: length,
+ cap: capacity,
}
} else {
RustFFIByteArray {
ptr: null_mut(),
len: usize::MAX,
+ cap: usize::MAX,
}
}
}
@@ -292,10 +323,15 @@
.get(&handle)
.unwrap()
.get_session_unique::<CryptoProvider>();
- let handle_size = session_unique_bytes.len();
+ let RawParts {
+ ptr,
+ length,
+ capacity,
+ } = RawParts::from_vec(session_unique_bytes);
RustFFIByteArray {
- ptr: session_unique_bytes.leak().as_mut_ptr(),
- len: handle_size,
+ ptr,
+ len: length,
+ cap: capacity,
}
}
@@ -324,10 +360,15 @@
.get(&handle)
.unwrap()
.save_session();
- let handle_size = key.len();
+ let RawParts {
+ ptr,
+ length,
+ capacity,
+ } = RawParts::from_vec(key);
RustFFIByteArray {
- ptr: key.leak().as_mut_ptr(),
- len: handle_size,
+ ptr,
+ len: length,
+ cap: capacity,
}
}
diff --git a/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock b/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock
index 5c10cb6..2e61f80 100644
--- a/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock
+++ b/nearby/connections/ukey2/ukey2_connections/fuzz/Cargo.lock
@@ -197,9 +197,9 @@
[[package]]
name = "clap"
-version = "3.2.23"
+version = "3.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
+checksum = "eef2b3ded6a26dfaec672a742c93c8cf6b689220324da509ec5caa20de55dc83"
dependencies = [
"bitflags",
"clap_lex",
@@ -386,9 +386,9 @@
[[package]]
name = "der"
-version = "0.7.4"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b14af2045fa69ed2b7a48934bebb842d0f33e73e96e78766ecb14bb5347a11"
+checksum = "bc906908ea6458456e5eaa160a9c08543ec3d1e6f71e2235cedd660cb65f9df0"
dependencies = [
"const-oid",
"zeroize",
@@ -456,9 +456,9 @@
[[package]]
name = "elliptic-curve"
-version = "0.13.4"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7"
+checksum = "6ea5a92946e8614bb585254898bb7dd1ddad241ace60c52149e3765e34cc039d"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -521,9 +521,9 @@
[[package]]
name = "generic-array"
-version = "0.14.7"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
@@ -820,9 +820,9 @@
[[package]]
name = "p256"
-version = "0.13.2"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+checksum = "7270da3e5caa82afd3deb054cc237905853813aea3859544bc082c3fe55b8d47"
dependencies = [
"elliptic-curve",
"primeorder",
@@ -892,9 +892,9 @@
[[package]]
name = "primeorder"
-version = "0.13.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf8d3875361e28f7753baefef104386e7aa47642c93023356d97fdef4003bfb5"
+checksum = "7613fdcc0831c10060fa69833ea8fa2caa94b6456f51e25356a885b530a2e3d0"
dependencies = [
"elliptic-curve",
]
@@ -1083,9 +1083,9 @@
[[package]]
name = "sec1"
-version = "0.7.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
+checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e"
dependencies = [
"base16ct",
"der",
diff --git a/nearby/crypto/crypto_provider/Cargo.toml b/nearby/crypto/crypto_provider/Cargo.toml
index 69f7572..53eb974 100644
--- a/nearby/crypto/crypto_provider/Cargo.toml
+++ b/nearby/crypto/crypto_provider/Cargo.toml
@@ -4,42 +4,19 @@
edition.workspace = true
publish.workspace = true
-[dependencies]
-hex-literal = { workspace = true, optional = true }
-rand = { workspace = true, optional = true }
-rstest = { version = "0.16.0", optional = true }
-rstest_reuse = { version = "0.5.0", optional = true }
-wycheproof = { version = "0.4.0", optional = true }
-hex = { workspace = true, optional = true }
-test_helper = { workspace = true, optional = true }
-
[dev-dependencies]
+criterion.workspace = true
+hex-literal.workspace = true
crypto_provider_openssl.workspace = true
crypto_provider_rustcrypto.workspace = true
-wycheproof = "0.4.0"
-hex-literal.workspace = true
-sha2.workspace = true
-criterion.workspace = true
rand_ext.workspace = true
-hex.workspace = true
+rand.workspace = true
[features]
default = ["alloc", "gcm_siv"]
std = []
alloc = []
gcm_siv = []
-testing = [
- "dep:hex-literal",
- "dep:rstest",
- "dep:rstest_reuse",
- "dep:wycheproof",
- "dep:test_helper",
- "std",
- "rand",
- "rand/std",
- "rand/std_rng",
- "dep:hex",
-]
[[bench]]
name = "hmac_bench"
diff --git a/nearby/crypto/crypto_provider/src/aes/cbc.rs b/nearby/crypto/crypto_provider/src/aes/cbc.rs
index d4211a6..e32c588 100644
--- a/nearby/crypto/crypto_provider/src/aes/cbc.rs
+++ b/nearby/crypto/crypto_provider/src/aes/cbc.rs
@@ -43,56 +43,3 @@
/// correctly. Exposing padding errors can cause a padding oracle vulnerability.
BadPadding,
}
-
-/// Module for testing implementations of this crate.
-#[cfg(feature = "testing")]
-pub mod testing {
- use super::{Aes256Key, AesCbcIv, AesCbcPkcs7Padded};
- pub use crate::testing::prelude::*;
- use core::marker::PhantomData;
- use hex_literal::hex;
- use rstest_reuse::template;
-
- /// Tests for AES-256-CBC encryption
- pub fn aes_256_cbc_test_encrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
- // http://google3/third_party/wycheproof/testvectors/aes_cbc_pkcs5_test.json;l=1492;rcl=264817632
- let key: Aes256Key =
- hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into();
- let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb");
- let msg = hex!("3f56935def3f");
- let expected_ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48");
- assert_eq!(A::encrypt(&key, &iv, &msg), expected_ciphertext);
- }
-
- /// Tests for AES-256-CBC decryption
- pub fn aes_256_cbc_test_decrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
- // http://google3/third_party/wycheproof/testvectors/aes_cbc_pkcs5_test.json;l=1492;rcl=264817632
- let key: Aes256Key =
- hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into();
- let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb");
- let ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48");
- let expected_msg = hex!("3f56935def3f");
- assert_eq!(A::decrypt(&key, &iv, &ciphertext).unwrap(), expected_msg);
- }
-
- /// Generates the test cases to validate the AES-256-CBC implementation.
- /// For example, to test `MyAesCbc256Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::cbc::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_256_cbc_test_cases)]
- /// fn aes_256_cbc_tests(
- /// testcase: CryptoProviderTestCases<PhantomData<MyAesCbc256Impl>>) {
- /// testcase(PhantomData);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::encrypt(aes_256_cbc_test_encrypt)]
- #[case::decrypt(aes_256_cbc_test_decrypt)]
- fn aes_256_cbc_test_cases<A: AesCbcPkcs7Padded>(#[case] testcase: CryptoProviderTestCases<F>) {}
-}
diff --git a/nearby/crypto/crypto_provider/src/aes/ctr.rs b/nearby/crypto/crypto_provider/src/aes/ctr.rs
index c7f5d5f..acfe4ef 100644
--- a/nearby/crypto/crypto_provider/src/aes/ctr.rs
+++ b/nearby/crypto/crypto_provider/src/aes/ctr.rs
@@ -33,178 +33,3 @@
/// Decrypt the data in place, advancing the counter state appropriately.
fn decrypt(&mut self, data: &mut [u8]);
}
-
-/// Module for testing implementations of this crate.
-#[cfg(feature = "testing")]
-pub mod testing {
- use super::AesCtr;
- use crate::aes::{Aes128Key, Aes256Key};
- pub use crate::testing::prelude;
- use core::marker;
- use hex_literal::hex;
- use rstest_reuse::template;
-
- /// Test AES-128-CTR encryption
- pub fn aes_128_ctr_test_encrypt<A: AesCtr<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
- // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.1
- let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
- let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
- let mut block: [u8; 16];
- let mut cipher = A::new(&key, iv);
-
- block = hex!("6bc1bee22e409f96e93d7e117393172a");
- cipher.encrypt(&mut block);
- let expected_ciphertext_1 = hex!("874d6191b620e3261bef6864990db6ce");
- assert_eq!(expected_ciphertext_1, block);
-
- block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
- cipher.encrypt(&mut block);
- let expected_ciphertext_2 = hex!("9806f66b7970fdff8617187bb9fffdff");
- assert_eq!(expected_ciphertext_2, block);
-
- block = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
- cipher.encrypt(&mut block);
- let expected_ciphertext_3 = hex!("5ae4df3edbd5d35e5b4f09020db03eab");
- assert_eq!(expected_ciphertext_3, block);
-
- block = hex!("f69f2445df4f9b17ad2b417be66c3710");
- cipher.encrypt(&mut block);
- let expected_ciphertext_3 = hex!("1e031dda2fbe03d1792170a0f3009cee");
- assert_eq!(expected_ciphertext_3, block);
- }
-
- /// Test AES-128-CTR decryption
- pub fn aes_128_ctr_test_decrypt<A: AesCtr<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
- // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.2
- let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
- let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
- let mut block: [u8; 16];
- let mut cipher = A::new(&key, iv);
-
- block = hex!("874d6191b620e3261bef6864990db6ce");
- cipher.encrypt(&mut block);
- let expected_plaintext_1 = hex!("6bc1bee22e409f96e93d7e117393172a");
- assert_eq!(expected_plaintext_1, block);
-
- block = hex!("9806f66b7970fdff8617187bb9fffdff");
- cipher.encrypt(&mut block);
- let expected_plaintext_2 = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
- assert_eq!(expected_plaintext_2, block);
-
- block = hex!("5ae4df3edbd5d35e5b4f09020db03eab");
- cipher.encrypt(&mut block);
- let expected_plaintext_3 = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
- assert_eq!(expected_plaintext_3, block);
-
- block = hex!("1e031dda2fbe03d1792170a0f3009cee");
- cipher.encrypt(&mut block);
- let expected_plaintext_3 = hex!("f69f2445df4f9b17ad2b417be66c3710");
- assert_eq!(expected_plaintext_3, block);
- }
-
- /// Test AES-256-CTR encryption
- pub fn aes_256_ctr_test_encrypt<A: AesCtr<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
- // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.5
- let key: Aes256Key =
- hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
- let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
- let mut block: [u8; 16];
- let mut cipher = A::new(&key, iv);
-
- block = hex!("6bc1bee22e409f96e93d7e117393172a");
- cipher.encrypt(&mut block);
- let expected_ciphertext_1 = hex!("601ec313775789a5b7a7f504bbf3d228");
- assert_eq!(expected_ciphertext_1, block);
-
- block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
- cipher.encrypt(&mut block);
- let expected_ciphertext_2 = hex!("f443e3ca4d62b59aca84e990cacaf5c5");
- assert_eq!(expected_ciphertext_2, block);
-
- block = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
- cipher.encrypt(&mut block);
- let expected_ciphertext_3 = hex!("2b0930daa23de94ce87017ba2d84988d");
- assert_eq!(expected_ciphertext_3, block);
-
- block = hex!("f69f2445df4f9b17ad2b417be66c3710");
- cipher.encrypt(&mut block);
- let expected_ciphertext_3 = hex!("dfc9c58db67aada613c2dd08457941a6");
- assert_eq!(expected_ciphertext_3, block);
- }
-
- /// Test AES-256-CTR decryption
- pub fn aes_256_ctr_test_decrypt<A: AesCtr<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
- // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.6
- let key: Aes256Key =
- hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
- let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
- let mut block: [u8; 16];
- let mut cipher = A::new(&key, iv);
-
- block = hex!("601ec313775789a5b7a7f504bbf3d228");
- cipher.encrypt(&mut block);
- let expected_plaintext_1 = hex!("6bc1bee22e409f96e93d7e117393172a");
- assert_eq!(expected_plaintext_1, block);
-
- block = hex!("f443e3ca4d62b59aca84e990cacaf5c5");
- cipher.encrypt(&mut block);
- let expected_plaintext_2 = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
- assert_eq!(expected_plaintext_2, block);
-
- block = hex!("2b0930daa23de94ce87017ba2d84988d");
- cipher.encrypt(&mut block);
- let expected_plaintext_3 = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
- assert_eq!(expected_plaintext_3, block);
-
- block = hex!("dfc9c58db67aada613c2dd08457941a6");
- cipher.encrypt(&mut block);
- let expected_plaintext_3 = hex!("f69f2445df4f9b17ad2b417be66c3710");
- assert_eq!(expected_plaintext_3, block);
- }
-
- /// Generates the test cases to validate the AES-128-CTR implementation.
- /// For example, to test `MyAesCtr128Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::ctr::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_128_ctr_test_cases)]
- /// fn aes_128_ctr_tests(testcase: CryptoProviderTestCase<MyAesCtr128Impl>) {
- /// testcase(MyAesCtr128Impl);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::encrypt(aes_128_ctr_test_encrypt)]
- #[case::decrypt(aes_128_ctr_test_decrypt)]
- fn aes_128_ctr_test_cases<F: AesCtrFactory<Key = Aes128Key>>(
- #[case] testcase: CryptoProviderTestCase<F>,
- ) {
- }
-
- /// Generates the test cases to validate the AES-256-CTR implementation.
- /// For example, to test `MyAesCtr256Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::ctr::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_256_ctr_test_cases_impl)]
- /// fn aes_256_ctr_tests(testcase: CryptoProviderTestCase<MyAesCtr256Impl>) {
- /// testcase(MyAesCtr256Impl);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::encrypt(aes_256_ctr_test_encrypt)]
- #[case::decrypt(aes_256_ctr_test_decrypt)]
- fn aes_256_ctr_test_cases<F: AesCtrFactory<Key = Aes256Key>>(
- #[case] testcase: CryptoProviderTestCase<F>,
- ) {
- }
-}
diff --git a/nearby/crypto/crypto_provider/src/aes/gcm_siv.rs b/nearby/crypto/crypto_provider/src/aes/gcm_siv.rs
index 2d683b2..dabb10d 100644
--- a/nearby/crypto/crypto_provider/src/aes/gcm_siv.rs
+++ b/nearby/crypto/crypto_provider/src/aes/gcm_siv.rs
@@ -46,119 +46,3 @@
/// in order to properly decrypt the message.
fn decrypt(&self, data: &mut Vec<u8>, aad: &[u8], nonce: &[u8]) -> Result<(), GcmSivError>;
}
-
-/// Module for testing implementations of this crate.
-#[cfg(feature = "testing")]
-pub mod testing {
- extern crate alloc;
-
- use alloc::vec::Vec;
- use core::marker;
-
- use hex_literal::hex;
- use rstest_reuse::template;
-
- use crate::aes::{Aes128Key, Aes256Key};
- pub use crate::testing::prelude;
-
- use super::AesGcmSiv;
-
- /// Test AES-GCM-SIV-128 encryption/decryption
- pub fn aes_128_gcm_siv_test<A: AesGcmSiv<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
- // https://github.com/google/wycheproof/blob/master/testvectors/aes_gcm_siv_test.json
- // TC1
- let test_key = hex!("01000000000000000000000000000000");
- let nonce = hex!("030000000000000000000000");
- let aes = A::new(&test_key.into());
- let msg = hex!("");
- let mut buf = Vec::from(msg.as_slice());
- let tag = hex!("dc20e2d83f25705bb49e439eca56de25");
- assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
- assert_eq!(&buf[..], &tag);
- // TC2
- let msg = hex!("0100000000000000");
- let ct = hex!("b5d839330ac7b786");
- let tag = hex!("578782fff6013b815b287c22493a364c");
- let mut buf = Vec::from(msg.as_slice());
- assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
- assert_eq!(&buf[..8], &ct);
- assert_eq!(&buf[8..], &tag);
- assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
- assert_eq!(&buf[..], &msg);
- }
-
- /// Test AES-256-GCM-SIV encryption/decryption
- pub fn aes_256_gcm_siv_test<A: AesGcmSiv<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
- // https://github.com/google/wycheproof/blob/master/testvectors/aes_gcm_siv_test.json
- // TC77
- let test_key = hex!("0100000000000000000000000000000000000000000000000000000000000000");
- let nonce = hex!("030000000000000000000000");
- let aes = A::new(&test_key.into());
- let msg = hex!("0100000000000000");
- let mut buf = Vec::new();
- buf.extend_from_slice(&msg);
- let ct = hex!("c2ef328e5c71c83b");
- let tag = hex!("843122130f7364b761e0b97427e3df28");
- assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
- assert_eq!(&buf[..8], &ct);
- assert_eq!(&buf[8..], &tag);
- assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
- assert_eq!(&buf[..], &msg);
- // TC78
- let msg = hex!("010000000000000000000000");
- let ct = hex!("9aab2aeb3faa0a34aea8e2b1");
- let tag = hex!("8ca50da9ae6559e48fd10f6e5c9ca17e");
- let mut buf = Vec::from(msg.as_slice());
- assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
- assert_eq!(&buf[..12], &ct);
- assert_eq!(&buf[12..], &tag);
- assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
- assert_eq!(&buf[..], &msg);
- }
-
- /// Generates the test cases to validate the AES-128-GCM-SIV implementation.
- /// For example, to test `MyAesGcmSiv128Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::gcm_siv::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_128_gcm_siv_test_cases)]
- /// fn aes_128_gcm_siv_tests(testcase: CryptoProviderTestCase<MyAesGcmSivImpl>) {
- /// testcase(MyAesGcmSiv128Impl);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::encrypt(aes_128_gcm_siv_test)]
- #[case::decrypt(aes_128_gcm_siv_test)]
- fn aes_128_gcm_siv_test_cases<F: AesGcmSivFactory<Key = Aes128Key>>(
- #[case] testcase: CryptoProviderTestCase<F>,
- ) {
- }
-
- /// Generates the test cases to validate the AES-256-GCM-SIV implementation.
- /// For example, to test `MyAesGcmSiv256Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::gcm_siv::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_256_gcm_siv_test_cases)]
- /// fn aes_256_gcm_siv_tests(testcase: CryptoProviderTestCase<MyAesGcmSiv256Impl>) {
- /// testcase(MyAesGcmSiv256Impl);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::encrypt(aes_256_gcm_siv_test)]
- #[case::decrypt(aes_256_gcm_siv_test)]
- fn aes_256_gcm_siv_test_cases<F: AesGcmSivFactory<Key = Aes256Key>>(
- #[case] testcase: CryptoProviderTestCase<F>,
- ) {
- }
-}
diff --git a/nearby/crypto/crypto_provider/src/aes/mod.rs b/nearby/crypto/crypto_provider/src/aes/mod.rs
index 240f11d..9526488 100644
--- a/nearby/crypto/crypto_provider/src/aes/mod.rs
+++ b/nearby/crypto/crypto_provider/src/aes/mod.rs
@@ -161,207 +161,3 @@
Self { key: arr }
}
}
-
-/// Module for testing implementations of this crate.
-#[cfg(feature = "testing")]
-pub mod testing {
- use super::*;
- pub use crate::testing::prelude::*;
- use core::marker;
- use hex_literal::hex;
- use rstest_reuse::template;
-
- /// Test encryption with AES-128
- pub fn aes_128_test_encrypt<A: AesEncryptCipher<Key = Aes128Key>>(
- _marker: marker::PhantomData<A>,
- ) {
- // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.1
- let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
- let mut block = [0_u8; 16];
- let enc_cipher = A::new(&key);
-
- block.copy_from_slice(&hex!("6bc1bee22e409f96e93d7e117393172a"));
- enc_cipher.encrypt(&mut block);
- assert_eq!(hex!("3ad77bb40d7a3660a89ecaf32466ef97"), block);
-
- block.copy_from_slice(&hex!("ae2d8a571e03ac9c9eb76fac45af8e51"));
- enc_cipher.encrypt(&mut block);
- assert_eq!(hex!("f5d3d58503b9699de785895a96fdbaaf"), block);
-
- block.copy_from_slice(&hex!("30c81c46a35ce411e5fbc1191a0a52ef"));
- enc_cipher.encrypt(&mut block);
- assert_eq!(hex!("43b1cd7f598ece23881b00e3ed030688"), block);
-
- block.copy_from_slice(&hex!("f69f2445df4f9b17ad2b417be66c3710"));
- enc_cipher.encrypt(&mut block);
- assert_eq!(hex!("7b0c785e27e8ad3f8223207104725dd4"), block);
- }
-
- /// Test decryption with AES-128
- pub fn aes_128_test_decrypt<A: AesDecryptCipher<Key = Aes128Key>>(
- _marker: marker::PhantomData<A>,
- ) {
- // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.2
- let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
- let mut block = [0_u8; 16];
- let dec_cipher = A::new(&key);
-
- block.copy_from_slice(&hex!("3ad77bb40d7a3660a89ecaf32466ef97"));
- dec_cipher.decrypt(&mut block);
- assert_eq!(hex!("6bc1bee22e409f96e93d7e117393172a"), block);
-
- block.copy_from_slice(&hex!("f5d3d58503b9699de785895a96fdbaaf"));
- dec_cipher.decrypt(&mut block);
- assert_eq!(hex!("ae2d8a571e03ac9c9eb76fac45af8e51"), block);
-
- block.copy_from_slice(&hex!("43b1cd7f598ece23881b00e3ed030688"));
- dec_cipher.decrypt(&mut block);
- assert_eq!(hex!("30c81c46a35ce411e5fbc1191a0a52ef"), block);
-
- block.copy_from_slice(&hex!("7b0c785e27e8ad3f8223207104725dd4"));
- dec_cipher.decrypt(&mut block);
- assert_eq!(hex!("f69f2445df4f9b17ad2b417be66c3710"), block);
- }
-
- /// Test encryption with AES-256
- pub fn aes_256_test_encrypt<A: AesEncryptCipher<Key = Aes256Key>>(
- _marker: marker::PhantomData<A>,
- ) {
- // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.5
- let key: Aes256Key =
- hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
- let mut block: [u8; 16];
- let enc_cipher = A::new(&key);
-
- block = hex!("6bc1bee22e409f96e93d7e117393172a");
- enc_cipher.encrypt(&mut block);
- assert_eq!(hex!("f3eed1bdb5d2a03c064b5a7e3db181f8"), block);
-
- block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
- enc_cipher.encrypt(&mut block);
- assert_eq!(hex!("591ccb10d410ed26dc5ba74a31362870"), block);
-
- block = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
- enc_cipher.encrypt(&mut block);
- assert_eq!(hex!("b6ed21b99ca6f4f9f153e7b1beafed1d"), block);
-
- block = hex!("f69f2445df4f9b17ad2b417be66c3710");
- enc_cipher.encrypt(&mut block);
- assert_eq!(hex!("23304b7a39f9f3ff067d8d8f9e24ecc7"), block);
- }
-
- /// Test decryption with AES-256
- pub fn aes_256_test_decrypt<A: AesDecryptCipher<Key = Aes256Key>>(
- _marker: marker::PhantomData<A>,
- ) {
- // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.6
- let key: Aes256Key =
- hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
- let mut block: [u8; 16];
- let dec_cipher = A::new(&key);
-
- block = hex!("f3eed1bdb5d2a03c064b5a7e3db181f8");
- dec_cipher.decrypt(&mut block);
- assert_eq!(hex!("6bc1bee22e409f96e93d7e117393172a"), block);
-
- block = hex!("591ccb10d410ed26dc5ba74a31362870");
- dec_cipher.decrypt(&mut block);
- assert_eq!(hex!("ae2d8a571e03ac9c9eb76fac45af8e51"), block);
-
- block = hex!("b6ed21b99ca6f4f9f153e7b1beafed1d");
- dec_cipher.decrypt(&mut block);
- assert_eq!(hex!("30c81c46a35ce411e5fbc1191a0a52ef"), block);
-
- block = hex!("23304b7a39f9f3ff067d8d8f9e24ecc7");
- dec_cipher.decrypt(&mut block);
- assert_eq!(hex!("f69f2445df4f9b17ad2b417be66c3710"), block);
- }
-
- /// Generates the test cases to validate the AES-128 implementation.
- /// For example, to test `MyAes128Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_128_encrypt_test_cases)]
- /// fn aes_128_tests(f: CryptoProviderTestCase<MyAes128Impl>) {
- /// f(MyAes128Impl);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::encrypt(aes_128_test_encrypt)]
- fn aes_128_encrypt_test_cases<A: AesFactory<Key = Aes128Key>>(
- #[case] testcase: CryptoProviderTestCase<F>,
- ) {
- }
-
- /// Generates the test cases to validate the AES-128 implementation.
- /// For example, to test `MyAes128Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_128_decrypt_test_cases)]
- /// fn aes_128_tests(f: CryptoProviderTestCase<MyAes128Impl>) {
- /// f(MyAes128Impl);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::decrypt(aes_128_test_decrypt)]
- fn aes_128_decrypt_test_cases<F: AesFactory<Key = Aes128Key>>(
- #[case] testcase: CryptoProviderTestCase<F>,
- ) {
- }
-
- /// Generates the test cases to validate the AES-256 implementation.
- /// For example, to test `MyAes256Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_256_encrypt_test_cases)]
- /// fn aes_256_tests(f: CryptoProviderTestCase<MyAes256Impl>) {
- /// f(MyAes256Impl);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::encrypt(aes_256_test_encrypt)]
- fn aes_256_encrypt_test_cases<F: AesFactory<Key = Aes256Key>>(
- #[case] testcase: CryptoProviderTestCase<F>,
- ) {
- }
-
- /// Generates the test cases to validate the AES-256 implementation.
- /// For example, to test `MyAes256Impl`:
- ///
- /// ```
- /// use crypto_provider::aes::testing::*;
- ///
- /// mod tests {
- /// #[apply(aes_256_decrypt_test_cases)]
- /// fn aes_256_tests(f: CryptoProviderTestCase<MyAes256Impl>) {
- /// f(MyAes256Impl);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::decrypt(aes_256_test_decrypt)]
- fn aes_256_decrypt_test_cases<F: AesFactory<Key = Aes256Key>>(
- #[case] testcase: CryptoProviderTestCase<F>,
- ) {
- }
-}
diff --git a/nearby/crypto/crypto_provider/src/ed25519.rs b/nearby/crypto/crypto_provider/src/ed25519.rs
index 4cee2da..e8fc176 100644
--- a/nearby/crypto/crypto_provider/src/ed25519.rs
+++ b/nearby/crypto/crypto_provider/src/ed25519.rs
@@ -112,146 +112,3 @@
/// Error returned if invalid signature bytes are provided
#[derive(Debug)]
pub struct InvalidSignature;
-
-#[cfg(feature = "testing")]
-/// Utilities for testing. Implementations can use the test cases and functions provided to test
-/// their implementation.
-pub mod testing {
- extern crate alloc;
- extern crate std;
-
- use crate::ed25519::{Ed25519Provider, KeyPair, PublicKey, Signature};
- use alloc::borrow::ToOwned;
- use alloc::string::String;
- use alloc::vec::Vec;
- use wycheproof::TestResult;
-
- // These are test vectors from the creators of Ed25519: https://ed25519.cr.yp.to/ which are referenced
- // as the SOT for the test vectors in the RFC: https://www.rfc-editor.org/rfc/rfc8032#section-7.1
- // The vectors have been formatted into a easily parsable/readable format by libgcrypt which is
- // also used for test cases in the above RFC:
- // https://dev.gnupg.org/source/libgcrypt/browse/master/tests/t-ed25519.inp
- const PATH_TO_RFC_VECTORS_FILE: &str =
- "crypto/crypto_provider/src/testdata/ecdsa/rfc_test_vectors.txt";
-
- /// Runs set of Ed25519 wycheproof test vectors against a provided ed25519 implementation
- /// Tests vectors from Project Wycheproof: <https://github.com/google/wycheproof>
- pub fn run_wycheproof_test_vectors<E>()
- where
- E: Ed25519Provider,
- {
- let test_set = wycheproof::eddsa::TestSet::load(wycheproof::eddsa::TestName::Ed25519)
- .expect("should be able to load test set");
-
- for test_group in test_set.test_groups {
- let key_pair = test_group.key;
- let public_key = key_pair.pk;
- let secret_key = key_pair.sk;
-
- for test in test_group.tests {
- let tc_id = test.tc_id;
- let comment = test.comment;
- let sig = test.sig;
- let msg = test.msg;
-
- let valid = match test.result {
- TestResult::Invalid => false,
- TestResult::Valid | TestResult::Acceptable => true,
- };
- let result = run_test::<E>(
- public_key.clone(),
- secret_key.clone(),
- sig.clone(),
- msg.clone(),
- );
- if valid {
- if let Err(desc) = result {
- panic!(
- "\n\
- Failed test {}: {}\n\
- msg:\t{:?}\n\
- sig:\t{:?}\n\
- comment:\t{:?}\n",
- tc_id, desc, msg, sig, comment,
- );
- }
- } else {
- assert!(result.is_err())
- }
- }
- }
- }
-
- /// Runs the RFC specified test vectors against an Ed25519 implementation
- pub fn run_rfc_test_vectors<E>()
- where
- E: Ed25519Provider,
- {
- let file_contents =
- std::fs::read_to_string(test_helper::get_data_file(PATH_TO_RFC_VECTORS_FILE))
- .expect("should be able to read file");
-
- let mut split_cases: Vec<&str> = file_contents.as_str().split("\n\n").collect();
- // remove the comments
- split_cases.remove(0);
- for case in split_cases {
- let test_case: Vec<&str> = case.split('\n').collect();
-
- let tc_id = extract_string(test_case[0]);
- let sk = extract_hex(test_case[1]);
- let pk = extract_hex(test_case[2]);
- let msg = extract_hex(test_case[3]);
- let sig = extract_hex(test_case[4]);
-
- let result = run_test::<E>(pk.clone(), sk.clone(), sig.clone(), msg.clone());
- if let Err(desc) = result {
- panic!(
- "\n\
- Failed test {}: {}\n\
- msg:\t{:?}\n\
- sig:\t{:?}\n\"",
- tc_id, desc, msg, sig,
- );
- }
- }
- }
-
- fn extract_hex(line: &str) -> Vec<u8> {
- test_helper::string_to_hex(extract_string(line).as_str())
- }
-
- fn extract_string(line: &str) -> String {
- line.split(':').collect::<Vec<&str>>()[1].trim().to_owned()
- }
-
- fn run_test<E>(
- pub_key: Vec<u8>,
- secret_key: Vec<u8>,
- sig: Vec<u8>,
- msg: Vec<u8>,
- ) -> Result<(), &'static str>
- where
- E: Ed25519Provider,
- {
- let kp_bytes: [u8; 64] = [secret_key.as_slice(), pub_key.as_slice()]
- .concat()
- .try_into()
- .map_err(|_| "invalid length keypair")?;
- let kp = E::KeyPair::from_bytes(kp_bytes)
- .map_err(|_| "Should be able to create Keypair from bytes")?;
-
- let sig_result = kp.sign(msg.as_slice());
- (sig.as_slice() == sig_result.to_bytes())
- .then_some(())
- .ok_or("sig not matching expected")?;
- let signature = E::Signature::from_bytes(sig.as_slice())
- .map_err(|_| "unable to parse sign from test case")?;
-
- let pub_key = kp.public();
- pub_key
- .verify_strict(msg.as_slice(), &signature)
- .map_err(|_| "verify failed")?;
-
- Ok(())
- }
-}
diff --git a/nearby/crypto/crypto_provider/src/elliptic_curve.rs b/nearby/crypto/crypto_provider/src/elliptic_curve.rs
index 75b12b1..d06a21d 100644
--- a/nearby/crypto/crypto_provider/src/elliptic_curve.rs
+++ b/nearby/crypto/crypto_provider/src/elliptic_curve.rs
@@ -57,18 +57,6 @@
) -> Result<<Self::Impl as EcdhProvider<C>>::SharedSecret, Self::Error>;
}
-/// Trait for an ephemeral secret for functions used in testing.
-#[cfg(feature = "testing")]
-pub trait EphemeralSecretForTesting<C: Curve>: EphemeralSecret<C> {
- /// Creates an ephemeral secret from the given private and public components.
- fn from_private_components(
- _private_bytes: &[u8; 32],
- _public_key: &<Self::Impl as EcdhProvider<C>>::PublicKey,
- ) -> Result<Self, Self::Error>
- where
- Self: Sized;
-}
-
/// Trait for a public key used for elliptic curve diffie hellman.
pub trait PublicKey<E: Curve>: Sized + PartialEq + Debug {
/// The error type associated with Public Key.
diff --git a/nearby/crypto/crypto_provider/src/hkdf.rs b/nearby/crypto/crypto_provider/src/hkdf.rs
index c905302..dab4e13 100644
--- a/nearby/crypto/crypto_provider/src/hkdf.rs
+++ b/nearby/crypto/crypto_provider/src/hkdf.rs
@@ -33,292 +33,3 @@
/// an invalid length
#[derive(Debug)]
pub struct InvalidLength;
-
-/// Test cases exported for testing specific hkdf implementations
-#[cfg(feature = "testing")]
-pub mod testing {
- extern crate alloc;
- use crate::hkdf::Hkdf;
- pub use crate::testing::prelude::*;
- use crate::CryptoProvider;
- use alloc::vec;
- use alloc::vec::Vec;
- use core::iter;
- use core::marker::PhantomData;
- use hex_literal::hex;
- use rstest_reuse::template;
-
- /// Generates the test cases to validate the hkdf implementation.
- /// For example, to test `MyCryptoProvider`:
- ///
- /// ```
- /// mod tests {
- /// use std::marker::PhantomData;
- /// use crypto_provider::testing::CryptoProviderTestCase;
- /// #[apply(hkdf_test_cases)]
- /// fn hkdf_tests(testcase: CryptoProviderTestCase<MyCryptoProvider>){
- /// testcase(PhantomData::<MyCryptoProvider>);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::basic_test_hkdf(basic_test_hkdf)]
- #[case::test_rfc5869_sha256(test_rfc5869_sha256)]
- #[case::test_lengths(test_lengths)]
- #[case::test_max_length(test_max_length)]
- #[case::test_max_length_exceeded(test_max_length_exceeded)]
- #[case::test_unsupported_length(test_unsupported_length)]
- #[case::test_expand_multi_info(test_expand_multi_info)]
- #[case::run_hkdf_sha256_vectors(run_hkdf_sha256_vectors)]
- #[case::run_hkdf_sha512_vectors(run_hkdf_sha512_vectors)]
- fn hkdf_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
-
- const MAX_SHA256_LENGTH: usize = 255 * (256 / 8); // =8160
-
- ///
- pub struct Test<'a> {
- ikm: &'a [u8],
- salt: &'a [u8],
- info: &'a [u8],
- okm: &'a [u8],
- }
-
- /// data taken from sample code in Readme of crates.io page
- pub fn basic_test_hkdf<C: CryptoProvider>(_: PhantomData<C>) {
- let ikm = hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
- let salt = hex!("000102030405060708090a0b0c");
- let info = hex!("f0f1f2f3f4f5f6f7f8f9");
-
- let hk = C::HkdfSha256::new(Some(&salt[..]), &ikm);
- let mut okm = [0u8; 42];
- hk.expand(&info, &mut okm)
- .expect("42 is a valid length for Sha256 to output");
-
- let expected = hex!(
- "
- 3cb25f25faacd57a90434f64d0362f2a
- 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
- 34007208d5b887185865
- "
- );
- assert_eq!(okm, expected);
- }
-
- // Test Vectors from https://tools.ietf.org/html/rfc5869.
- #[rustfmt::skip]
- ///
- pub fn test_rfc5869_sha256<C: CryptoProvider>(_: PhantomData<C>) {
- let tests = [
- Test {
- // Test Case 1
- ikm: &hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
- salt: &hex!("000102030405060708090a0b0c"),
- info: &hex!("f0f1f2f3f4f5f6f7f8f9"),
- okm: &hex!("
- 3cb25f25faacd57a90434f64d0362f2a
- 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
- 34007208d5b887185865
- "),
- },
- Test {
- // Test Case 2
- ikm: &hex!("
- 000102030405060708090a0b0c0d0e0f
- 101112131415161718191a1b1c1d1e1f
- 202122232425262728292a2b2c2d2e2f
- 303132333435363738393a3b3c3d3e3f
- 404142434445464748494a4b4c4d4e4f
- "),
- salt: &hex!("
- 606162636465666768696a6b6c6d6e6f
- 707172737475767778797a7b7c7d7e7f
- 808182838485868788898a8b8c8d8e8f
- 909192939495969798999a9b9c9d9e9f
- a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
- "),
- info: &hex!("
- b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
- c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
- d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
- e0e1e2e3e4e5e6e7e8e9eaebecedeeef
- f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
- "),
- okm: &hex!("
- b11e398dc80327a1c8e7f78c596a4934
- 4f012eda2d4efad8a050cc4c19afa97c
- 59045a99cac7827271cb41c65e590e09
- da3275600c2f09b8367793a9aca3db71
- cc30c58179ec3e87c14c01d5c1f3434f
- 1d87
- "),
- },
- Test {
- // Test Case 3
- ikm: &hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
- salt: &hex!(""),
- info: &hex!(""),
- okm: &hex!("
- 8da4e775a563c18f715f802a063c5a31
- b8a11f5c5ee1879ec3454e5f3c738d2d
- 9d201395faa4b61a96c8
- "),
- },
- ];
- for Test { ikm, salt, info, okm } in tests.iter() {
- let salt = if salt.is_empty() {
- None
- } else {
- Some(&salt[..])
- };
- let hkdf = C::HkdfSha256::new(salt, ikm);
- let mut okm2 = vec![0u8; okm.len()];
- assert!(hkdf.expand(&info[..], &mut okm2).is_ok());
- assert_eq!(okm2[..], okm[..]);
- }
- }
-
- ///
- pub fn test_lengths<C: CryptoProvider>(_: PhantomData<C>) {
- let hkdf = C::HkdfSha256::new(None, &[]);
- let mut longest = vec![0u8; MAX_SHA256_LENGTH];
- assert!(hkdf.expand(&[], &mut longest).is_ok());
- // Runtime is O(length), so exhaustively testing all legal lengths
- // would take too long (at least without --release). Only test a
- // subset: the first 500, the last 10, and every 100th in between.
- // 0 is an invalid key length for openssl, so start at 1
- let lengths = (1..MAX_SHA256_LENGTH + 1)
- .filter(|&len| !(500..=MAX_SHA256_LENGTH - 10).contains(&len) || len % 100 == 0);
-
- for length in lengths {
- let mut okm = vec![0u8; length];
-
- assert!(hkdf.expand(&[], &mut okm).is_ok());
- assert_eq!(okm.len(), length);
- assert_eq!(okm[..], longest[..length]);
- }
- }
-
- ///
- pub fn test_max_length<C: CryptoProvider>(_: PhantomData<C>) {
- let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
- let mut okm = vec![0u8; MAX_SHA256_LENGTH];
- assert!(hkdf.expand(&[], &mut okm).is_ok());
- }
-
- ///
- pub fn test_max_length_exceeded<C: CryptoProvider>(_: PhantomData<C>) {
- let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
- let mut okm = vec![0u8; MAX_SHA256_LENGTH + 1];
- assert!(hkdf.expand(&[], &mut okm).is_err());
- }
-
- ///
- pub fn test_unsupported_length<C: CryptoProvider>(_: PhantomData<C>) {
- let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
- let mut okm = vec![0u8; 90000];
- assert!(hkdf.expand(&[], &mut okm).is_err());
- }
-
- ///
- pub fn test_expand_multi_info<C: CryptoProvider>(_: PhantomData<C>) {
- let info_components = &[
- &b"09090909090909090909090909090909090909090909"[..],
- &b"8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a"[..],
- &b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0"[..],
- &b"4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4"[..],
- &b"1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d"[..],
- ];
-
- let hkdf = C::HkdfSha256::new(None, b"some ikm here");
-
- // Compute HKDF-Expand on the concatenation of all the info components
- let mut oneshot_res = [0u8; 16];
- hkdf.expand(&info_components.concat(), &mut oneshot_res)
- .unwrap();
-
- // Now iteratively join the components of info_components until it's all 1 component. The value
- // of HKDF-Expand should be the same throughout
- let mut num_concatted = 0;
- let mut info_head = Vec::new();
-
- while num_concatted < info_components.len() {
- info_head.extend(info_components[num_concatted]);
-
- // Build the new input to be the info head followed by the remaining components
- let input: Vec<&[u8]> = iter::once(info_head.as_slice())
- .chain(info_components.iter().cloned().skip(num_concatted + 1))
- .collect();
-
- // Compute and compare to the one-shot answer
- let mut multipart_res = [0u8; 16];
- hkdf.expand_multi_info(&input, &mut multipart_res).unwrap();
- assert_eq!(multipart_res, oneshot_res);
- num_concatted += 1;
- }
- }
-
- ///
- pub fn run_hkdf_sha256_vectors<C: CryptoProvider>(_: PhantomData<C>) {
- run_hkdf_test_vectors::<C::HkdfSha256>(HashAlg::Sha256)
- }
-
- ///
- pub fn run_hkdf_sha512_vectors<C: CryptoProvider>(_: PhantomData<C>) {
- run_hkdf_test_vectors::<C::HkdfSha512>(HashAlg::Sha512)
- }
-
- enum HashAlg {
- Sha256,
- Sha512,
- }
-
- ///
- fn run_hkdf_test_vectors<K: Hkdf>(hash: HashAlg) {
- let test_name = match hash {
- HashAlg::Sha256 => wycheproof::hkdf::TestName::HkdfSha256,
- HashAlg::Sha512 => wycheproof::hkdf::TestName::HkdfSha512,
- };
-
- let test_set =
- wycheproof::hkdf::TestSet::load(test_name).expect("should be able to load test set");
- for test_group in test_set.test_groups {
- for test in test_group.tests {
- let ikm = test.ikm;
- let salt = test.salt;
- let info = test.info;
- let okm = test.okm;
- let tc_id = test.tc_id;
- if let Some(desc) = run_test::<K>(
- ikm.as_slice(),
- salt.as_slice(),
- info.as_slice(),
- okm.as_slice(),
- ) {
- panic!(
- "\n\
- Failed test {tc_id}: {desc}\n\
- ikm:\t{ikm:?}\n\
- salt:\t{salt:?}\n\
- info:\t{info:?}\n\
- okm:\t{okm:?}\n"
- );
- }
- }
- }
- }
-
- fn run_test<K: Hkdf>(ikm: &[u8], salt: &[u8], info: &[u8], okm: &[u8]) -> Option<&'static str> {
- let prk = K::new(Some(salt), ikm);
- let mut got_okm = vec![0; okm.len()];
-
- if prk.expand(info, &mut got_okm).is_err() {
- return Some("prk expand");
- }
- if got_okm != okm {
- return Some("mismatch in okm");
- }
- None
- }
-}
diff --git a/nearby/crypto/crypto_provider/src/hmac.rs b/nearby/crypto/crypto_provider/src/hmac.rs
index 40be189..c5a9ae1 100644
--- a/nearby/crypto/crypto_provider/src/hmac.rs
+++ b/nearby/crypto/crypto_provider/src/hmac.rs
@@ -44,125 +44,3 @@
/// Error output when the provided key material length is invalid
#[derive(Debug)]
pub struct InvalidLength;
-
-/// Test cases exported for testing specific hmac implementations
-#[cfg(feature = "testing")]
-pub mod testing {
- use crate::hmac::Hmac;
- use crate::rstest_reuse::template;
- pub use crate::testing::prelude::*;
- use crate::CryptoProvider;
- use core::cmp::min;
- use core::marker::PhantomData;
- use wycheproof::TestResult;
-
- /// Generates the test cases to validate the hmac implementation.
- /// For example, to test `MyCryptoProvider`:
- ///
- /// ```
- /// mod tests {
- /// use std::marker::PhantomData;
- /// use crypto_provider::testing::CryptoProviderTestCase;
- /// #[apply(hmac_test_cases)]
- /// fn hmac_tests(testcase: CryptoProviderTestCase<MyCryptoProvider>){
- /// testcase(PhantomData::<MyCryptoProvider>);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::hmac_sha256_test_vectors(hmac_sha256_test_vectors)]
- #[case::hmac_sha512_test_vectors(hmac_sha512_test_vectors)]
- fn hmac_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
-
- /// Run wycheproof hmac sha256 test vectors on provided CryptoProvider
- pub fn hmac_sha256_test_vectors<C: CryptoProvider>(_: PhantomData<C>) {
- run_hmac_test_vectors::<32, C::HmacSha256>(HashAlg::Sha256)
- }
-
- /// Run wycheproof hmac sha512 test vectors on provided CryptoProvider
- pub fn hmac_sha512_test_vectors<C: CryptoProvider>(_: PhantomData<C>) {
- run_hmac_test_vectors::<64, C::HmacSha512>(HashAlg::Sha512)
- }
-
- enum HashAlg {
- Sha256,
- Sha512,
- }
-
- // Tests vectors from Project Wycheproof:
- // https://github.com/google/wycheproof
- fn run_hmac_test_vectors<const N: usize, H: Hmac<N>>(hash: HashAlg) {
- let test_name = match hash {
- HashAlg::Sha256 => wycheproof::mac::TestName::HmacSha256,
- HashAlg::Sha512 => wycheproof::mac::TestName::HmacSha512,
- };
- let test_set =
- wycheproof::mac::TestSet::load(test_name).expect("should be able to load test set");
-
- for test_group in test_set.test_groups {
- for test in test_group.tests {
- let key = test.key;
- let msg = test.msg;
- let tag = test.tag;
- let tc_id = test.tc_id;
- let valid = match test.result {
- TestResult::Valid | TestResult::Acceptable => true,
- TestResult::Invalid => false,
- };
-
- if let Some(desc) =
- run_test::<N, H>(key.as_slice(), msg.as_slice(), tag.as_slice(), valid)
- {
- panic!(
- "\n\
- Failed test {tc_id}: {desc}\n\
- key:\t{key:?}\n\
- msg:\t{msg:?}\n\
- tag:\t{tag:?}\n",
- );
- }
- }
- }
- }
-
- fn run_test<const N: usize, H: Hmac<N>>(
- key: &[u8],
- input: &[u8],
- tag: &[u8],
- valid_data: bool,
- ) -> Option<&'static str> {
- let mut mac = H::new_from_slice(key).unwrap();
- mac.update(input);
- let result = mac.finalize();
- let n = tag.len();
- let result_bytes = &result[..n];
-
- if valid_data {
- if result_bytes != tag {
- return Some("whole message");
- }
- } else {
- return if result_bytes == tag {
- Some("invalid should not match")
- } else {
- None
- };
- }
-
- // test reading different chunk sizes
- for chunk_size in 1..min(64, input.len()) {
- let mut mac = H::new_from_slice(key).unwrap();
- for chunk in input.chunks(chunk_size) {
- mac.update(chunk);
- }
- let res = mac.verify_truncated_left(tag);
- if res.is_err() {
- return Some("chunked message");
- }
- }
-
- None
- }
-}
diff --git a/nearby/crypto/crypto_provider/src/lib.rs b/nearby/crypto/crypto_provider/src/lib.rs
index 4eb5563..3ebaf9b 100644
--- a/nearby/crypto/crypto_provider/src/lib.rs
+++ b/nearby/crypto/crypto_provider/src/lib.rs
@@ -19,9 +19,6 @@
use core::fmt::Debug;
-#[cfg(feature = "testing")]
-pub use rstest_reuse;
-
use crate::aes::{Aes128Key, Aes256Key};
/// mod containing hmac trait
@@ -124,108 +121,3 @@
unimplemented!()
}
}
-
-/// Utilities for testing implementations of this crate.
-#[cfg(feature = "testing")]
-pub mod testing {
- extern crate alloc;
-
- use alloc::{format, string::String};
- use core::marker::PhantomData;
-
- use hex_literal::hex;
- use rand::{Rng, RngCore};
- use rstest_reuse::template;
-
- use crate::CryptoProvider;
-
- /// Common items that needs to be imported to use these test cases
- pub mod prelude {
- pub use rstest::rstest;
- pub use rstest_reuse;
- pub use rstest_reuse::apply;
-
- pub use super::CryptoProviderTestCase;
- }
-
- /// A test case for Crypto Provider. A test case is a function that panics if the test fails.
- pub type CryptoProviderTestCase<T> = fn(PhantomData<T>);
-
- #[derive(Debug)]
- pub(crate) struct TestError(String);
-
- impl TestError {
- pub(crate) fn new<D: core::fmt::Debug>(value: D) -> Self {
- Self(format!("{value:?}"))
- }
- }
-
- /// Test for `constant_time_eq` when the two inputs are equal.
- pub fn constant_time_eq_test_equal<C: CryptoProvider>(_marker: PhantomData<C>) {
- assert!(C::constant_time_eq(
- &hex!("00010203040506070809"),
- &hex!("00010203040506070809")
- ));
- }
-
- /// Test for `constant_time_eq` when the two inputs are not equal.
- pub fn constant_time_eq_test_not_equal<C: CryptoProvider>(_marker: PhantomData<C>) {
- assert!(!C::constant_time_eq(
- &hex!("00010203040506070809"),
- &hex!("00000000000000000000")
- ));
- }
-
- /// Random tests for `constant_time_eq`.
- pub fn constant_time_eq_random_test<C: CryptoProvider>(_marker: PhantomData<C>) {
- let mut rng = rand::thread_rng();
- for _ in 1..100 {
- // Test using "oracle" of ==, with possibly different lengths for a and b
- let mut a = alloc::vec![0; rng.gen_range(1..1000)];
- rng.fill_bytes(&mut a);
- let mut b = alloc::vec![0; rng.gen_range(1..1000)];
- rng.fill_bytes(&mut b);
- assert_eq!(C::constant_time_eq(&a, &b), a == b);
- }
-
- for _ in 1..10000 {
- // Test using "oracle" of ==, with same lengths for a and b
- let len = rng.gen_range(1..1000);
- let mut a = alloc::vec![0; len];
- rng.fill_bytes(&mut a);
- let mut b = alloc::vec![0; len];
- rng.fill_bytes(&mut b);
- assert_eq!(C::constant_time_eq(&a, &b), a == b);
- }
-
- for _ in 1..10000 {
- // Clones and the original should always be equal
- let mut a = alloc::vec![0; rng.gen_range(1..1000)];
- rng.fill_bytes(&mut a);
- assert!(C::constant_time_eq(&a, &a.clone()));
- }
- }
-
- /// Generates the test cases to validate the P256 implementation.
- /// For example, to test `MyCryptoProvider`:
- ///
- /// ```
- /// use crypto_provider::p256::testing::*;
- ///
- /// mod tests {
- /// #[apply(constant_time_eq_test_cases)]
- /// fn constant_time_eq_tests(
- /// testcase: CryptoProviderTestCase<MyCryptoProvider>) {
- /// testcase(PhantomData);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::constant_time_eq_test_not_equal(constant_time_eq_test_not_equal)]
- #[case::constant_time_eq_test_equal(constant_time_eq_test_equal)]
- #[case::constant_time_eq_random_test(constant_time_eq_random_test)]
- fn constant_time_eq_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {
- }
-}
diff --git a/nearby/crypto/crypto_provider/src/p256.rs b/nearby/crypto/crypto_provider/src/p256.rs
index be14a39..90d3542 100644
--- a/nearby/crypto/crypto_provider/src/p256.rs
+++ b/nearby/crypto/crypto_provider/src/p256.rs
@@ -74,236 +74,3 @@
{
type PublicKey = E::PublicKey;
}
-
-/// Utilities for testing. Implementations can use the test cases and functions provided to test
-/// their implementation.
-#[cfg(feature = "testing")]
-pub mod testing {
- extern crate std;
- use super::{P256PublicKey, P256};
- pub use crate::testing::prelude::*;
- use crate::{
- elliptic_curve::{EcdhProvider, EphemeralSecret, EphemeralSecretForTesting, PublicKey},
- testing::TestError,
- CryptoRng,
- };
- use core::marker::PhantomData;
- use hex_literal::hex;
- use rstest_reuse::template;
-
- /// An ECDH provider that provides associated types for testing purposes. This can be mostly
- /// considered "aliases" for the otherwise long fully-qualified associated types.
- pub trait EcdhProviderForP256Test {
- /// The ECDH Provider that is "wrapped" by this type.
- type EcdhProvider: EcdhProvider<
- P256,
- PublicKey = <Self as EcdhProviderForP256Test>::PublicKey,
- EphemeralSecret = <Self as EcdhProviderForP256Test>::EphemeralSecret,
- SharedSecret = <Self as EcdhProviderForP256Test>::SharedSecret,
- >;
- /// The public key type.
- type PublicKey: P256PublicKey;
- /// The ephemeral secret type.
- type EphemeralSecret: EphemeralSecretForTesting<P256, Impl = Self::EcdhProvider>;
- /// The shared secret type.
- type SharedSecret: Into<[u8; 32]>;
- }
-
- impl<E> EcdhProviderForP256Test for E
- where
- E: EcdhProvider<P256>,
- E::PublicKey: P256PublicKey,
- E::EphemeralSecret: EphemeralSecretForTesting<P256>,
- {
- type EcdhProvider = E;
- type PublicKey = E::PublicKey;
- type EphemeralSecret = E::EphemeralSecret;
- type SharedSecret = E::SharedSecret;
- }
-
- /// Test for P256PublicKey::to_bytes
- pub fn to_bytes_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
- let sec1_bytes = hex!(
- "04756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09f0b6da270d2a58a06022
- 8bbe76c6dc1643088107636deff8aa79e8002a157b92"
- );
- let key = E::PublicKey::from_sec1_bytes(&sec1_bytes).unwrap();
- let sec1_bytes_compressed =
- hex!("02756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09");
- assert_eq!(sec1_bytes_compressed.to_vec(), key.to_bytes());
- }
-
- /// Random test for P256PublicKey::to_bytes
- pub fn to_bytes_random_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
- for _ in 1..100 {
- let public_key_bytes =
- E::EphemeralSecret::generate_random(&mut <E::EphemeralSecret as EphemeralSecret<
- P256,
- >>::Rng::new())
- .public_key_bytes();
- let public_key = E::PublicKey::from_bytes(&public_key_bytes).unwrap();
- assert_eq!(
- E::PublicKey::from_bytes(&public_key.to_bytes()).unwrap(),
- public_key,
- "from_bytes should return the same key for `{public_key_bytes:?}`",
- );
- }
- }
-
- /// Test for P256PublicKey::from_affine_coordinates
- pub fn from_affine_coordinates_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
- // https://www.secg.org/sec1-v2.pdf, section 2.3.3
- let x = hex!("756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09");
- let y = hex!("f0b6da270d2a58a060228bbe76c6dc1643088107636deff8aa79e8002a157b92");
- let sec1 = hex!(
- "04756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09f0b6da270d2a58a06022
- 8bbe76c6dc1643088107636deff8aa79e8002a157b92"
- );
- let expected_key = E::PublicKey::from_sec1_bytes(&sec1).unwrap();
- assert!(
- E::PublicKey::from_affine_coordinates(&x, &y).unwrap() == expected_key,
- "Public key does not match"
- );
- }
-
- /// Test for P256PublicKey::from_affine_coordinates
- pub fn from_affine_coordinates_not_on_curve_test<E: EcdhProviderForP256Test>(
- _: PhantomData<E>,
- ) {
- // (Invalid) coordinate from wycheproof ecdh_secp256r1_ecpoint_test.json, tcId 193
- let x = hex!("0000000000000000000000000000000000000000000000000000000000000000");
- let y = hex!("0000000000000000000000000000000000000000000000000000000000000000");
- let result = E::PublicKey::from_affine_coordinates(&x, &y);
- assert!(
- result.is_err(),
- "Creating public key from invalid affine coordinate should fail"
- );
- }
-
- /// Test for P256PublicKey::from_sec1_bytes
- pub fn from_sec1_bytes_not_on_curve_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
- // (Invalid) sec1 encoding from wycheproof ecdh_secp256r1_ecpoint_test.json, tcId 193
- let sec1 = hex!(
- "04000000000000000000000000000000000000000000000000000000000000000000000000000000000000
- 00000000000000000000000000000000000000000000"
- );
- let result = E::PublicKey::from_sec1_bytes(&sec1);
- assert!(
- result.is_err(),
- "Creating public key from point not on curve should fail"
- );
- }
-
- /// Test for P256PublicKey::to_affine_coordinates
- pub fn public_key_to_affine_coordinates_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
- // https://www.secg.org/sec1-v2.pdf, section 2.3.3
- let expected_x = hex!("756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09");
- let expected_y = hex!("f0b6da270d2a58a060228bbe76c6dc1643088107636deff8aa79e8002a157b92");
- let sec1 = hex!(
- "04756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09f0b6da270d2a58a06022
- 8bbe76c6dc1643088107636deff8aa79e8002a157b92"
- );
- let public_key = E::PublicKey::from_sec1_bytes(&sec1).unwrap();
- let (actual_x, actual_y) = public_key.to_affine_coordinates().unwrap();
- assert_eq!(actual_x, expected_x);
- assert_eq!(actual_y, expected_y);
- }
-
- /// Test for P256 Diffie-Hellman key exchange.
- pub fn p256_ecdh_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
- // From wycheproof ecdh_secp256r1_ecpoint_test.json, tcId 1
- // http://google3/third_party/wycheproof/testvectors/ecdh_secp256r1_ecpoint_test.json;l=22;rcl=375894991
- // sec1 public key manually extracted from the ASN encoded test data
- let public_key_sec1 = hex!(
- "0462d5bd3372af75fe85a040715d0f502428e07046868b0bfdfa61d731afe44f
- 26ac333a93a9e70a81cd5a95b5bf8d13990eb741c8c38872b4a07d275a014e30cf"
- );
- let private = hex!("0612465c89a023ab17855b0a6bcebfd3febb53aef84138647b5352e02c10c346");
- let expected_shared_secret =
- hex!("53020d908b0219328b658b525f26780e3ae12bcd952bb25a93bc0895e1714285");
- let actual_shared_secret = p256_ecdh_test_impl::<E>(&public_key_sec1, &private).unwrap();
- assert_eq!(actual_shared_secret.into(), expected_shared_secret);
- }
-
- fn p256_ecdh_test_impl<E: EcdhProviderForP256Test>(
- public_key_sec1: &[u8],
- private: &[u8; 32],
- ) -> Result<E::SharedSecret, TestError> {
- let public_key = E::PublicKey::from_sec1_bytes(public_key_sec1).map_err(TestError::new)?;
- let ephemeral_secret = E::EphemeralSecret::from_private_components(private, &public_key)
- .map_err(TestError::new)?;
- ephemeral_secret
- .diffie_hellman(&public_key)
- .map_err(TestError::new)
- }
-
- /// Wycheproof test for P256 Diffie-Hellman.
- pub fn wycheproof_p256_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
- // Test cases from https://github.com/randombit/wycheproof-rs/blob/master/src/data/ecdh_secp256r1_ecpoint_test.json
- let test_set =
- wycheproof::ecdh::TestSet::load(wycheproof::ecdh::TestName::EcdhSecp256r1Ecpoint)
- .unwrap();
- for test_group in test_set.test_groups {
- for test in test_group.tests {
- if test.private_key.len() != 32 {
- // Some Wycheproof test cases have private key length that are not 32 bytes, but
- // the RustCrypto implementation doesn't support that (it always take 32 bytes
- // from the given RNG when generating a new key).
- continue;
- };
- std::println!("Testing {}", test.tc_id);
- let result = p256_ecdh_test_impl::<E>(
- &test.public_key,
- &test
- .private_key
- .try_into()
- .expect("Private key should be 32 bytes long"),
- );
- match test.result {
- wycheproof::TestResult::Valid => {
- let shared_secret =
- result.unwrap_or_else(|_| panic!("Test {} should succeed", test.tc_id));
- assert_eq!(test.shared_secret, shared_secret.into());
- }
- wycheproof::TestResult::Invalid => {
- result
- .err()
- .unwrap_or_else(|| panic!("Test {} should fail", test.tc_id));
- }
- wycheproof::TestResult::Acceptable => {
- if let Ok(shared_secret) = result {
- assert_eq!(test.shared_secret, shared_secret.into());
- }
- // Test passes if `result` is an error because this test is "acceptable"
- }
- }
- }
- }
- }
-
- /// Generates the test cases to validate the P256 implementation.
- /// For example, to test `MyCryptoProvider`:
- ///
- /// ```
- /// use crypto_provider::p256::testing::*;
- ///
- /// mod tests {
- /// #[apply(p256_test_cases)]
- /// fn p256_tests(testcase: CryptoProviderTestCase<MyCryptoProvider> {
- /// testcase(PhantomData::<MyCryptoProvider>);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::to_bytes(to_bytes_test)]
- #[case::to_bytes_random(to_bytes_random_test)]
- #[case::from_sec1_bytes_not_on_curve(from_sec1_bytes_not_on_curve_test)]
- #[case::from_affine_coordinates(from_affine_coordinates_test)]
- #[case::from_affine_coordinates_not_on_curve(from_affine_coordinates_not_on_curve_test)]
- #[case::public_key_to_affine_coordinates(public_key_to_affine_coordinates_test)]
- #[case::p256_ecdh(p256_ecdh_test)]
- #[case::wycheproof_p256(wycheproof_p256_test)]
- fn p256_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
-}
diff --git a/nearby/crypto/crypto_provider/src/sha2.rs b/nearby/crypto/crypto_provider/src/sha2.rs
index b742303..7af7c96 100644
--- a/nearby/crypto/crypto_provider/src/sha2.rs
+++ b/nearby/crypto/crypto_provider/src/sha2.rs
@@ -23,115 +23,3 @@
/// Computes the SHA2 512-bit hash.
fn sha512(input: &[u8]) -> [u8; 64];
}
-
-/// Utilities for testing. Implementations can use the test cases and functions provided to test
-/// their implementation.
-#[cfg(feature = "testing")]
-pub mod testing {
-
- extern crate alloc;
- extern crate std;
- use super::{Sha256, Sha512};
- pub use crate::testing::prelude::*;
- use crate::CryptoProvider;
- use alloc::vec::Vec;
- use core::{marker::PhantomData, str::FromStr};
- use hex::FromHex;
- pub use hex_literal::hex;
- use rstest_reuse::template;
-
- /// Test vectors from SHA256ShortMsg.rsp in
- /// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
- pub fn sha256_cavp_short_vector_test<C: CryptoProvider>(_marker: PhantomData<C>) {
- sha256_cavp_vector_test::<C>(include_str!("testdata/SHA256ShortMsg.rsp"));
- }
-
- /// Test vectors from SHA256LongMsg.rsp in
- /// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
- pub fn sha256_cavp_long_vector_test<C: CryptoProvider>(_marker: PhantomData<C>) {
- sha256_cavp_vector_test::<C>(include_str!("testdata/SHA256LongMsg.rsp"));
- }
-
- /// Test vectors from SHA512ShortMsg.rsp in
- /// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
- pub fn sha512_cavp_short_vector_test<C: CryptoProvider>(_marker: PhantomData<C>) {
- sha512_cavp_vector_test::<C>(include_str!("testdata/SHA512ShortMsg.rsp"));
- }
-
- /// Test vectors from SHA512LongMsg.rsp in
- /// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
- pub fn sha512_cavp_long_vector_test<C: CryptoProvider>(_marker: PhantomData<C>) {
- sha512_cavp_vector_test::<C>(include_str!("testdata/SHA512LongMsg.rsp"));
- }
-
- /// Test vectors an rsp file in
- /// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
- fn sha256_cavp_vector_test<C: CryptoProvider>(cavp_file_contents: &str) {
- sha_cavp_vector_test(<C::Sha256 as Sha256>::sha256, cavp_file_contents)
- }
-
- /// Test vectors an rsp file in
- /// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
- fn sha512_cavp_vector_test<C: CryptoProvider>(cavp_file_contents: &str) {
- sha_cavp_vector_test(<C::Sha512 as Sha512>::sha512, cavp_file_contents)
- }
-
- fn sha_cavp_vector_test<const N: usize>(
- hash_func: impl Fn(&[u8]) -> [u8; N],
- cavp_file_contents: &str,
- ) {
- let test_cases = cavp_file_contents.split("\n\n").filter_map(|chunk| {
- let mut len: Option<usize> = None;
- let mut msg: Option<Vec<u8>> = None;
- let mut md: Option<Vec<u8>> = None;
- for line in chunk.split('\n') {
- if line.starts_with('#') || line.is_empty() || line == std::format!("[L = {N}]") {
- continue;
- } else if let Some(len_str) = line.strip_prefix("Len = ") {
- len = Some(FromStr::from_str(len_str).unwrap());
- } else if let Some(hex_str) = line.strip_prefix("Msg = ") {
- msg = Some(Vec::<u8>::from_hex(hex_str).unwrap());
- } else if let Some(hex_str) = line.strip_prefix("MD = ") {
- md = Some(Vec::<u8>::from_hex(hex_str).unwrap());
- } else {
- panic!("Unexpected line in test file: `{}`", line);
- }
- }
- if let (Some(len), Some(msg), Some(md)) = (len, msg, md) {
- Some((len, msg, md))
- } else {
- None
- }
- });
- for (len, mut msg, md) in test_cases {
- if len == 0 {
- // Truncate len = 0, since the test file has "Msg = 00" in there that should be
- // ignored.
- msg.truncate(0);
- }
- assert_eq!(msg.len(), len / 8);
- let md_arr: [u8; N] = md.try_into().unwrap();
- assert_eq!(hash_func(&msg), md_arr);
- }
- }
-
- /// Generates the test cases to validate the SHA2 implementation.
- /// For example, to test `MyCryptoProvider`:
- ///
- /// ```
- /// use crypto_provider::sha2::testing::*;
- ///
- /// mod tests {
- /// #[apply(sha2_test_cases)]
- /// fn sha2_tests(testcase: CryptoProviderTestCase<MyCryptoProvider>) {
- /// testcase(PhantomData::<MyCryptoProvider>);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::sha256_cavp_short_vector(sha256_cavp_short_vector_test)]
- #[case::sha256_cavp_long_vector(sha256_cavp_long_vector_test)]
- fn sha2_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
-}
diff --git a/nearby/crypto/crypto_provider/src/x25519.rs b/nearby/crypto/crypto_provider/src/x25519.rs
index 0579159..f77a772 100644
--- a/nearby/crypto/crypto_provider/src/x25519.rs
+++ b/nearby/crypto/crypto_provider/src/x25519.rs
@@ -17,156 +17,3 @@
/// Marker type for X25519 implementation. This is used by EcdhProvider as its type parameter.
pub enum X25519 {}
impl Curve for X25519 {}
-
-/// Utilities for testing. Implementations can use the test cases and functions provided to test
-/// their implementation.
-#[cfg(feature = "testing")]
-pub mod testing {
- use super::X25519;
- pub use crate::testing::prelude::*;
- use crate::{
- elliptic_curve::{EcdhProvider, EphemeralSecret, EphemeralSecretForTesting, PublicKey},
- testing::TestError,
- CryptoRng,
- };
- use core::marker::PhantomData;
- use hex_literal::hex;
- use rstest_reuse::template;
-
- /// An ECDH provider that provides associated types for testing purposes. This can be mostly
- /// considered "aliases" for the otherwise long fully-qualified associated types.
- pub trait EcdhProviderForX25519Test {
- /// The ECDH Provider that is "wrapped" by this type.
- type EcdhProvider: EcdhProvider<
- X25519,
- PublicKey = <Self as EcdhProviderForX25519Test>::PublicKey,
- EphemeralSecret = <Self as EcdhProviderForX25519Test>::EphemeralSecret,
- SharedSecret = <Self as EcdhProviderForX25519Test>::SharedSecret,
- >;
- /// The public key type.
- type PublicKey: PublicKey<X25519>;
- /// The ephemeral secret type.
- type EphemeralSecret: EphemeralSecretForTesting<X25519, Impl = Self::EcdhProvider>;
- /// The shared secret type.
- type SharedSecret: Into<[u8; 32]>;
- }
-
- impl<E> EcdhProviderForX25519Test for E
- where
- E: EcdhProvider<X25519>,
- E::PublicKey: PublicKey<X25519>,
- E::EphemeralSecret: EphemeralSecretForTesting<X25519>,
- {
- type EcdhProvider = E;
- type PublicKey = E::PublicKey;
- type EphemeralSecret = E::EphemeralSecret;
- type SharedSecret = E::SharedSecret;
- }
-
- /// Test for `PublicKey<X25519>::to_bytes`
- pub fn x25519_to_bytes_test<E: EcdhProviderForX25519Test>(_: PhantomData<E>) {
- let public_key_bytes =
- hex!("504a36999f489cd2fdbc08baff3d88fa00569ba986cba22548ffde80f9806829");
- let public_key = E::PublicKey::from_bytes(&public_key_bytes).unwrap();
- assert_eq!(public_key_bytes.to_vec(), public_key.to_bytes());
- }
-
- /// Random test for `PublicKey<X25519>::to_bytes`
- pub fn x25519_to_bytes_random_test<E: EcdhProviderForX25519Test>(_: PhantomData<E>) {
- for _ in 1..100 {
- let public_key_bytes =
- E::EphemeralSecret::generate_random(&mut <E::EphemeralSecret as EphemeralSecret<
- X25519,
- >>::Rng::new())
- .public_key_bytes();
- let public_key = E::PublicKey::from_bytes(&public_key_bytes).unwrap();
- assert_eq!(
- E::PublicKey::from_bytes(&public_key.to_bytes()).unwrap(),
- public_key,
- "from_bytes should return the same key for `{public_key_bytes:?}`",
- );
- }
- }
-
- /// Test for X25519 Diffie-Hellman key exchange.
- pub fn x25519_ecdh_test<E: EcdhProviderForX25519Test>(_: PhantomData<E>) {
- // From wycheproof ecdh_secx25519r1_ecpoint_test.json, tcId 1
- // http://google3/third_party/wycheproof/testvectors/ecdh_secx25519r1_ecpoint_test.json;l=22;rcl=375894991
- // sec1 public key manually extracted from the ASN encoded test data
- let public_key = hex!("504a36999f489cd2fdbc08baff3d88fa00569ba986cba22548ffde80f9806829");
- let private = hex!("c8a9d5a91091ad851c668b0736c1c9a02936c0d3ad62670858088047ba057475");
- let expected_shared_secret =
- hex!("436a2c040cf45fea9b29a0cb81b1f41458f863d0d61b453d0a982720d6d61320");
- let result = x25519_ecdh_test_impl::<E>(&public_key, &private).unwrap();
- assert_eq!(expected_shared_secret, result.into());
- }
-
- fn x25519_ecdh_test_impl<E: EcdhProviderForX25519Test>(
- public_key: &[u8],
- private: &[u8; 32],
- ) -> Result<E::SharedSecret, TestError> {
- let public_key = E::PublicKey::from_bytes(public_key).map_err(TestError::new)?;
- let ephemeral_secret = E::EphemeralSecret::from_private_components(private, &public_key)
- .map_err(TestError::new)?;
- ephemeral_secret
- .diffie_hellman(&public_key)
- .map_err(TestError::new)
- }
-
- /// Wycheproof test for X25519 Diffie-Hellman.
- pub fn wycheproof_x25519_test<E: EcdhProviderForX25519Test>(_: PhantomData<E>) {
- // Test cases from https://github.com/randombit/wycheproof-rs/blob/master/src/data/x25519_test.json
- let test_set = wycheproof::xdh::TestSet::load(wycheproof::xdh::TestName::X25519).unwrap();
- for test_group in test_set.test_groups {
- for test in test_group.tests {
- let result = x25519_ecdh_test_impl::<E>(
- &test.public_key,
- &test
- .private_key
- .try_into()
- .expect("Private keys should be 32 bytes long"),
- );
- match test.result {
- wycheproof::TestResult::Valid => {
- let shared_secret =
- result.unwrap_or_else(|_| panic!("Test {} should succeed", test.tc_id));
- assert_eq!(&test.shared_secret, &shared_secret.into());
- }
- wycheproof::TestResult::Invalid => {
- result
- .err()
- .unwrap_or_else(|| panic!("Test {} should fail", test.tc_id));
- }
- wycheproof::TestResult::Acceptable => {
- if let Ok(shared_secret) = result {
- assert_eq!(test.shared_secret, shared_secret.into());
- }
- // Test passes if `result` is an error because this test is "acceptable"
- }
- }
- }
- }
- }
-
- /// Generates the test cases to validate the x25519 implementation.
- /// For example, to test `MyCryptoProvider`:
- ///
- /// ```
- /// use crypto_provider::x25519::testing::*;
- ///
- /// mod tests {
- /// #[apply(x25519_test_cases)]
- /// fn x25519_tests(testcase: CryptoProviderTestCase<MyCryptoProvider>) {
- /// testcase(PhantomData::<MyCryptoProvider>);
- /// }
- /// }
- /// ```
- #[template]
- #[export]
- #[rstest]
- #[case::x25519_to_bytes(x25519_to_bytes_test)]
- #[case::x25519_to_bytes_random(x25519_to_bytes_random_test)]
- #[case::x25519_ecdh(x25519_ecdh_test)]
- #[case::wycheproof_x25519(wycheproof_x25519_test)]
- fn x25519_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
-}
diff --git a/nearby/crypto/crypto_provider_boringssl/Cargo.lock b/nearby/crypto/crypto_provider_boringssl/Cargo.lock
index b1c65bd..7d097a6 100644
--- a/nearby/crypto/crypto_provider_boringssl/Cargo.lock
+++ b/nearby/crypto/crypto_provider_boringssl/Cargo.lock
@@ -27,15 +27,6 @@
[[package]]
name = "crypto_provider"
version = "0.1.0"
-dependencies = [
- "hex",
- "hex-literal",
- "rand",
- "rstest",
- "rstest_reuse",
- "test_helper",
- "wycheproof",
-]
[[package]]
name = "crypto_provider_boringssl"
@@ -44,6 +35,7 @@
"bssl-crypto",
"crypto_provider",
"crypto_provider_stubs",
+ "crypto_provider_test",
]
[[package]]
@@ -54,10 +46,25 @@
]
[[package]]
+name = "crypto_provider_test"
+version = "0.1.0"
+dependencies = [
+ "crypto_provider",
+ "hex",
+ "hex-literal",
+ "rand",
+ "rand_ext",
+ "rstest",
+ "rstest_reuse",
+ "test_helper",
+ "wycheproof",
+]
+
+[[package]]
name = "futures"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
+checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
@@ -70,9 +77,9 @@
[[package]]
name = "futures-channel"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
dependencies = [
"futures-core",
"futures-sink",
@@ -80,15 +87,15 @@
[[package]]
name = "futures-core"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
+checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
@@ -97,32 +104,32 @@
[[package]]
name = "futures-io"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
+checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-macro"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
+checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.15",
]
[[package]]
name = "futures-sink"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
+checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]]
name = "futures-task"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]]
name = "futures-timer"
@@ -132,9 +139,9 @@
[[package]]
name = "futures-util"
-version = "0.3.27"
+version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [
"futures-channel",
"futures-core",
@@ -150,9 +157,9 @@
[[package]]
name = "getrandom"
-version = "0.2.8"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
dependencies = [
"cfg-if",
"libc",
@@ -179,9 +186,18 @@
[[package]]
name = "libc"
-version = "0.2.140"
+version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
[[package]]
name = "memchr"
@@ -209,18 +225,18 @@
[[package]]
name = "proc-macro2"
-version = "1.0.53"
+version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.26"
+version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
dependencies = [
"proc-macro2",
]
@@ -256,6 +272,25 @@
]
[[package]]
+name = "rand_ext"
+version = "0.1.0"
+dependencies = [
+ "crypto_provider",
+ "log",
+ "rand",
+ "rand_pcg",
+]
+
+[[package]]
+name = "rand_pcg"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
name = "rstest"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -316,29 +351,29 @@
[[package]]
name = "serde"
-version = "1.0.158"
+version = "1.0.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
+checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.158"
+version = "1.0.162"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
+checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.6",
+ "syn 2.0.15",
]
[[package]]
name = "serde_json"
-version = "1.0.94"
+version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
dependencies = [
"itoa",
"ryu",
@@ -367,9 +402,9 @@
[[package]]
name = "syn"
-version = "2.0.6"
+version = "2.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ece519cfaf36269ea69d16c363fa1d59ceba8296bbfbfc003c3176d01f2816ee"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
dependencies = [
"proc-macro2",
"quote",
diff --git a/nearby/crypto/crypto_provider_boringssl/Cargo.toml b/nearby/crypto/crypto_provider_boringssl/Cargo.toml
index 6a62172..24ce66c 100644
--- a/nearby/crypto/crypto_provider_boringssl/Cargo.toml
+++ b/nearby/crypto/crypto_provider_boringssl/Cargo.toml
@@ -12,4 +12,4 @@
bssl-crypto = {path = "../bssl-crypto"}
[dev-dependencies]
-crypto_provider = {path = "../crypto_provider", features = ["std", "alloc", "testing"]}
+crypto_provider_test = {path = "../crypto_provider_test"}
diff --git a/nearby/crypto/crypto_provider_boringssl/src/aes.rs b/nearby/crypto/crypto_provider_boringssl/src/aes.rs
index a4f275e..fc97db2 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/aes.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/aes.rs
@@ -113,7 +113,7 @@
mod tests {
use super::*;
use core::marker::PhantomData;
- use crypto_provider::aes::testing::*;
+ use crypto_provider_test::aes::*;
#[apply(aes_128_encrypt_test_cases)]
fn aes_128_encrypt_test(testcase: CryptoProviderTestCase<Aes128EncryptCipher>) {
diff --git a/nearby/crypto/crypto_provider_boringssl/src/hkdf.rs b/nearby/crypto/crypto_provider_boringssl/src/hkdf.rs
index 4ab0ad4..3672bb1 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/hkdf.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/hkdf.rs
@@ -54,7 +54,7 @@
mod tests {
use crate::Boringssl;
use core::marker::PhantomData;
- use crypto_provider::hkdf::testing::*;
+ use crypto_provider_test::hkdf::*;
#[apply(hkdf_test_cases)]
fn hkdf_tests(testcase: CryptoProviderTestCase<Boringssl>) {
diff --git a/nearby/crypto/crypto_provider_boringssl/src/hmac.rs b/nearby/crypto/crypto_provider_boringssl/src/hmac.rs
index 3459c3b..7a5e867 100644
--- a/nearby/crypto/crypto_provider_boringssl/src/hmac.rs
+++ b/nearby/crypto/crypto_provider_boringssl/src/hmac.rs
@@ -84,7 +84,7 @@
mod tests {
use crate::Boringssl;
use core::marker::PhantomData;
- use crypto_provider::hmac::testing::*;
+ use crypto_provider_test::hmac::*;
#[apply(hmac_test_cases)]
fn hmac_tests(testcase: CryptoProviderTestCase<Boringssl>) {
diff --git a/nearby/crypto/crypto_provider_default/Cargo.toml b/nearby/crypto/crypto_provider_default/Cargo.toml
index 9eff7ea..f78ad8e 100644
--- a/nearby/crypto/crypto_provider_default/Cargo.toml
+++ b/nearby/crypto/crypto_provider_default/Cargo.toml
@@ -12,6 +12,7 @@
cfg-if.workspace = true
[features]
+std = ["crypto_provider_rustcrypto/std"]
default = ["rustcrypto"]
rustcrypto = ["crypto_provider_rustcrypto"]
boringssl = ["crypto_provider_boringssl"]
diff --git a/nearby/crypto/crypto_provider_openssl/Cargo.toml b/nearby/crypto/crypto_provider_openssl/Cargo.toml
index 78c6cf3..8fa6faa 100644
--- a/nearby/crypto/crypto_provider_openssl/Cargo.toml
+++ b/nearby/crypto/crypto_provider_openssl/Cargo.toml
@@ -16,6 +16,6 @@
boringssl = ["openssl/unstable_boringssl", "crypto_provider/gcm_siv"]
[dev-dependencies]
-crypto_provider = { path = "../crypto_provider", default-features = false, features = ["testing"] }
-rstest = "0.16.0"
+crypto_provider_test.workspace = true
+rstest.workspace = true
hex-literal.workspace = true
diff --git a/nearby/crypto/crypto_provider_openssl/src/aes.rs b/nearby/crypto/crypto_provider_openssl/src/aes.rs
index ded187f..55a3dd2 100644
--- a/nearby/crypto/crypto_provider_openssl/src/aes.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/aes.rs
@@ -290,9 +290,9 @@
mod tests {
use core::marker::PhantomData;
- use crypto_provider::aes::cbc::testing::*;
- use crypto_provider::aes::ctr::testing::*;
- use crypto_provider::aes::testing::*;
+ use crypto_provider_test::aes::cbc::*;
+ use crypto_provider_test::aes::ctr::*;
+ use crypto_provider_test::aes::*;
use super::*;
diff --git a/nearby/crypto/crypto_provider_openssl/src/ed25519.rs b/nearby/crypto/crypto_provider_openssl/src/ed25519.rs
index cb37b6f..1384a06 100644
--- a/nearby/crypto/crypto_provider_openssl/src/ed25519.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/ed25519.rs
@@ -126,7 +126,7 @@
#[cfg(test)]
mod tests {
use crate::ed25519::Ed25519;
- use crypto_provider::ed25519::testing::{run_rfc_test_vectors, run_wycheproof_test_vectors};
+ use crypto_provider_test::ed25519::{run_rfc_test_vectors, run_wycheproof_test_vectors};
#[test]
fn wycheproof_test_ed25519_openssl() {
diff --git a/nearby/crypto/crypto_provider_openssl/src/hkdf_boringssl.rs b/nearby/crypto/crypto_provider_openssl/src/hkdf_boringssl.rs
index f6c106d..eb23b3b 100644
--- a/nearby/crypto/crypto_provider_openssl/src/hkdf_boringssl.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/hkdf_boringssl.rs
@@ -67,7 +67,7 @@
mod tests {
use crate::Openssl;
use core::marker::PhantomData;
- use crypto_provider::hkdf::testing::*;
+ use crypto_provider_test::hkdf::*;
#[apply(hkdf_test_cases)]
fn hkdf_tests(testcase: CryptoProviderTestCase<Openssl>) {
diff --git a/nearby/crypto/crypto_provider_openssl/src/hkdf_openssl.rs b/nearby/crypto/crypto_provider_openssl/src/hkdf_openssl.rs
index 605cff1..c578ed7 100644
--- a/nearby/crypto/crypto_provider_openssl/src/hkdf_openssl.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/hkdf_openssl.rs
@@ -65,7 +65,7 @@
mod tests {
use crate::Openssl;
use core::marker::PhantomData;
- use crypto_provider::hkdf::testing::*;
+ use crypto_provider_test::hkdf::*;
#[apply(hkdf_test_cases)]
fn hkdf_tests(testcase: CryptoProviderTestCase<Openssl>) {
diff --git a/nearby/crypto/crypto_provider_openssl/src/hmac_boringssl.rs b/nearby/crypto/crypto_provider_openssl/src/hmac_boringssl.rs
index af728b3..2202d7e 100644
--- a/nearby/crypto/crypto_provider_openssl/src/hmac_boringssl.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/hmac_boringssl.rs
@@ -102,7 +102,7 @@
mod tests {
use crate::Openssl;
use core::marker::PhantomData;
- use crypto_provider::hmac::testing::*;
+ use crypto_provider_test::hmac::*;
#[apply(hmac_test_cases)]
fn hmac_tests(testcase: CryptoProviderTestCase<Openssl>) {
diff --git a/nearby/crypto/crypto_provider_openssl/src/hmac_openssl.rs b/nearby/crypto/crypto_provider_openssl/src/hmac_openssl.rs
index d99ee3e..3cff10f 100644
--- a/nearby/crypto/crypto_provider_openssl/src/hmac_openssl.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/hmac_openssl.rs
@@ -180,7 +180,7 @@
mod tests {
use crate::Openssl;
use core::marker::PhantomData;
- use crypto_provider::hmac::testing::*;
+ use crypto_provider_test::hmac::*;
#[apply(hmac_test_cases)]
fn hmac_tests(testcase: CryptoProviderTestCase<Openssl>) {
diff --git a/nearby/crypto/crypto_provider_openssl/src/lib.rs b/nearby/crypto/crypto_provider_openssl/src/lib.rs
index db926f0..41c4642 100644
--- a/nearby/crypto/crypto_provider_openssl/src/lib.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/lib.rs
@@ -112,8 +112,8 @@
mod tests {
use core::marker::PhantomData;
- use crypto_provider::sha2::testing::*;
- use crypto_provider::testing::*;
+ use crypto_provider_test::sha2::*;
+ use crypto_provider_test::*;
use crate::Openssl;
diff --git a/nearby/crypto/crypto_provider_openssl/src/p256.rs b/nearby/crypto/crypto_provider_openssl/src/p256.rs
index a0c5072..5efd123 100644
--- a/nearby/crypto/crypto_provider_openssl/src/p256.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/p256.rs
@@ -132,7 +132,7 @@
}
#[cfg(test)]
-impl crypto_provider::elliptic_curve::EphemeralSecretForTesting<P256> for P256EphemeralSecret {
+impl crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<P256> for P256EphemeralSecret {
fn from_private_components(
private_bytes: &[u8; 32],
public_key: &P256PublicKey,
@@ -160,7 +160,7 @@
mod tests {
use super::P256Ecdh;
use core::marker::PhantomData;
- use crypto_provider::p256::testing::*;
+ use crypto_provider_test::p256::*;
#[apply(p256_test_cases)]
fn p256_tests(testcase: CryptoProviderTestCase<P256Ecdh>) {
diff --git a/nearby/crypto/crypto_provider_openssl/src/x25519.rs b/nearby/crypto/crypto_provider_openssl/src/x25519.rs
index 0745c0b..ff6f3b0 100644
--- a/nearby/crypto/crypto_provider_openssl/src/x25519.rs
+++ b/nearby/crypto/crypto_provider_openssl/src/x25519.rs
@@ -72,7 +72,7 @@
}
#[cfg(test)]
-impl crypto_provider::elliptic_curve::EphemeralSecretForTesting<X25519> for X25519PrivateKey {
+impl crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<X25519> for X25519PrivateKey {
fn from_private_components(
private_bytes: &[u8; 32],
_public_key: &<Self::Impl as EcdhProvider<X25519>>::PublicKey,
@@ -93,7 +93,7 @@
#[cfg(test)]
mod tests {
use core::marker::PhantomData;
- use crypto_provider::x25519::testing::*;
+ use crypto_provider_test::x25519::*;
use super::X25519Ecdh;
diff --git a/nearby/crypto/crypto_provider_rustcrypto/Cargo.toml b/nearby/crypto/crypto_provider_rustcrypto/Cargo.toml
index 2ab5354..cd4cf4a 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/Cargo.toml
+++ b/nearby/crypto/crypto_provider_rustcrypto/Cargo.toml
@@ -26,7 +26,7 @@
[dev-dependencies]
hex.workspace = true
-crypto_provider = { workspace = true, features = ["testing"] }
+crypto_provider_test.workspace = true
crypto_provider_rustcrypto = { path = ".", features = ["std"] }
[features]
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aes/cbc.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aes/cbc.rs
index b43876c..06d7224 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/aes/cbc.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aes/cbc.rs
@@ -44,7 +44,7 @@
mod tests {
use super::AesCbcPkcs7Padded;
use core::marker::PhantomData;
- use crypto_provider::aes::cbc::testing::*;
+ use crypto_provider_test::aes::cbc::*;
#[apply(aes_256_cbc_test_cases)]
fn aes_256_cbc_test(testcase: CryptoProviderTestCase<AesCbcPkcs7Padded>) {
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aes/gcm_siv.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aes/gcm_siv.rs
index 98eca08..c31e09a 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/aes/gcm_siv.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aes/gcm_siv.rs
@@ -67,8 +67,8 @@
mod tests {
use core::marker::PhantomData;
- use crypto_provider::aes::gcm_siv::testing::*;
- use crypto_provider::aes::testing::*;
+ use crypto_provider_test::aes::gcm_siv::*;
+ use crypto_provider_test::aes::*;
use super::*;
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/aes/mod.rs b/nearby/crypto/crypto_provider_rustcrypto/src/aes/mod.rs
index a351b81..bd37458 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/aes/mod.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/aes/mod.rs
@@ -154,8 +154,8 @@
mod tests {
use core::marker::PhantomData;
- use crypto_provider::aes::ctr::testing::*;
- use crypto_provider::aes::testing::*;
+ use crypto_provider_test::aes::ctr::*;
+ use crypto_provider_test::aes::*;
use super::*;
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs b/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
index df5c5de..b971268 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/ed25519.rs
@@ -110,7 +110,7 @@
#[cfg(test)]
mod tests {
- use crypto_provider::ed25519::testing::{run_rfc_test_vectors, run_wycheproof_test_vectors};
+ use crypto_provider_test::ed25519::{run_rfc_test_vectors, run_wycheproof_test_vectors};
use crate::ed25519::Ed25519;
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/hkdf_rc.rs b/nearby/crypto/crypto_provider_rustcrypto/src/hkdf_rc.rs
index 8ff5d7b..79379e2 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/hkdf_rc.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/hkdf_rc.rs
@@ -76,7 +76,7 @@
mod tests {
use crate::RustCrypto;
use core::marker::PhantomData;
- use crypto_provider::hkdf::testing::*;
+ use crypto_provider_test::hkdf::*;
#[apply(hkdf_test_cases)]
fn hkdf_tests(testcase: CryptoProviderTestCase<RustCrypto>) {
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/hmac_rc.rs b/nearby/crypto/crypto_provider_rustcrypto/src/hmac_rc.rs
index 95254a5..6eb678c 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/hmac_rc.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/hmac_rc.rs
@@ -117,7 +117,7 @@
mod tests {
use crate::RustCrypto;
use core::marker::PhantomData;
- use crypto_provider::hmac::testing::*;
+ use crypto_provider_test::hmac::*;
#[apply(hmac_test_cases)]
fn hmac_tests(testcase: CryptoProviderTestCase<RustCrypto>) {
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs b/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
index e73ea11..7d4a3b4 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/lib.rs
@@ -126,7 +126,7 @@
mod tests {
use core::marker::PhantomData;
- use crypto_provider::sha2::testing::*;
+ use crypto_provider_test::sha2::*;
use crate::RustCrypto;
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/p256.rs b/nearby/crypto/crypto_provider_rustcrypto/src/p256.rs
index a50bec8..3ad08f2 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/p256.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/p256.rs
@@ -120,7 +120,8 @@
#[cfg(test)]
impl<R: CryptoRng + SeedableRng + RngCore + Send>
- crypto_provider::elliptic_curve::EphemeralSecretForTesting<P256> for P256EphemeralSecret<R>
+ crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<P256>
+ for P256EphemeralSecret<R>
{
fn from_private_components(
private_bytes: &[u8; 32],
@@ -139,7 +140,7 @@
mod tests {
use super::P256Ecdh;
use core::marker::PhantomData;
- use crypto_provider::p256::testing::*;
+ use crypto_provider_test::p256::*;
use rand::rngs::StdRng;
#[apply(p256_test_cases)]
diff --git a/nearby/crypto/crypto_provider_rustcrypto/src/x25519.rs b/nearby/crypto/crypto_provider_rustcrypto/src/x25519.rs
index 794d780..60d9bdb 100644
--- a/nearby/crypto/crypto_provider_rustcrypto/src/x25519.rs
+++ b/nearby/crypto/crypto_provider_rustcrypto/src/x25519.rs
@@ -68,7 +68,7 @@
#[cfg(test)]
impl<R: CryptoRng + RngCore + SeedableRng + Send>
- crypto_provider::elliptic_curve::EphemeralSecretForTesting<X25519>
+ crypto_provider_test::elliptic_curve::EphemeralSecretForTesting<X25519>
for X25519EphemeralSecret<R>
{
fn from_private_components(
@@ -114,7 +114,7 @@
mod tests {
use super::X25519Ecdh;
use core::marker::PhantomData;
- use crypto_provider::x25519::testing::*;
+ use crypto_provider_test::x25519::*;
use rand::rngs::StdRng;
#[apply(x25519_test_cases)]
diff --git a/nearby/crypto/crypto_provider_test/Cargo.toml b/nearby/crypto/crypto_provider_test/Cargo.toml
new file mode 100644
index 0000000..1f58c84
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "crypto_provider_test"
+version.workspace = true
+edition.workspace = true
+publish.workspace = true
+
+[dependencies]
+crypto_provider.workspace = true
+rand_ext.workspace = true
+test_helper.workspace = true
+
+hex-literal.workspace = true
+rand.workspace = true
+rstest.workspace = true
+rstest_reuse.workspace = true
+wycheproof.workspace = true
+hex.workspace = true
\ No newline at end of file
diff --git a/nearby/crypto/crypto_provider_test/src/aes/cbc.rs b/nearby/crypto/crypto_provider_test/src/aes/cbc.rs
new file mode 100644
index 0000000..b22c828
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/aes/cbc.rs
@@ -0,0 +1,63 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::aes::Aes256Key;
+pub use crate::prelude::*;
+use core::marker::PhantomData;
+use crypto_provider::aes::cbc::{AesCbcIv, AesCbcPkcs7Padded};
+use hex_literal::hex;
+use rstest_reuse::template;
+
+/// Tests for AES-256-CBC encryption
+pub fn aes_256_cbc_test_encrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
+ // http://google3/third_party/wycheproof/testvectors/aes_cbc_pkcs5_test.json;l=1492;rcl=264817632
+ let key: Aes256Key =
+ hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into();
+ let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb");
+ let msg = hex!("3f56935def3f");
+ let expected_ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48");
+ assert_eq!(A::encrypt(&key, &iv, &msg), expected_ciphertext);
+}
+
+/// Tests for AES-256-CBC decryption
+pub fn aes_256_cbc_test_decrypt<A: AesCbcPkcs7Padded>(_marker: PhantomData<A>) {
+ // http://google3/third_party/wycheproof/testvectors/aes_cbc_pkcs5_test.json;l=1492;rcl=264817632
+ let key: Aes256Key =
+ hex!("665a02bc265a66d01775091da56726b6668bfd903cb7af66fb1b78a8a062e43c").into();
+ let iv: AesCbcIv = hex!("3fb0d5ecd06c71150748b599595833cb");
+ let ciphertext = hex!("3f3f39697bd7e88d85a14132be1cbc48");
+ let expected_msg = hex!("3f56935def3f");
+ assert_eq!(A::decrypt(&key, &iv, &ciphertext).unwrap(), expected_msg);
+}
+
+/// Generates the test cases to validate the AES-256-CBC implementation.
+/// For example, to test `MyAesCbc256Impl`:
+///
+/// ```
+/// use crypto_provider::aes::cbc::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_256_cbc_test_cases)]
+/// fn aes_256_cbc_tests(
+/// testcase: CryptoProviderTestCases<PhantomData<MyAesCbc256Impl>>) {
+/// testcase(PhantomData);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::encrypt(aes_256_cbc_test_encrypt)]
+#[case::decrypt(aes_256_cbc_test_decrypt)]
+fn aes_256_cbc_test_cases<A: AesCbcPkcs7Padded>(#[case] testcase: CryptoProviderTestCases<F>) {}
diff --git a/nearby/crypto/crypto_provider_test/src/aes/ctr.rs b/nearby/crypto/crypto_provider_test/src/aes/ctr.rs
new file mode 100644
index 0000000..401f65b
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/aes/ctr.rs
@@ -0,0 +1,183 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+use crate::aes::{Aes128Key, Aes256Key};
+pub use crate::prelude;
+use core::marker;
+use crypto_provider::aes::ctr::AesCtr;
+use hex_literal::hex;
+use rstest_reuse::template;
+
+/// Test AES-128-CTR encryption
+pub fn aes_128_ctr_test_encrypt<A: AesCtr<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
+ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.1
+ let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
+ let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ let mut block: [u8; 16];
+ let mut cipher = A::new(&key, iv);
+
+ block = hex!("6bc1bee22e409f96e93d7e117393172a");
+ cipher.encrypt(&mut block);
+ let expected_ciphertext_1 = hex!("874d6191b620e3261bef6864990db6ce");
+ assert_eq!(expected_ciphertext_1, block);
+
+ block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
+ cipher.encrypt(&mut block);
+ let expected_ciphertext_2 = hex!("9806f66b7970fdff8617187bb9fffdff");
+ assert_eq!(expected_ciphertext_2, block);
+
+ block = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
+ cipher.encrypt(&mut block);
+ let expected_ciphertext_3 = hex!("5ae4df3edbd5d35e5b4f09020db03eab");
+ assert_eq!(expected_ciphertext_3, block);
+
+ block = hex!("f69f2445df4f9b17ad2b417be66c3710");
+ cipher.encrypt(&mut block);
+ let expected_ciphertext_3 = hex!("1e031dda2fbe03d1792170a0f3009cee");
+ assert_eq!(expected_ciphertext_3, block);
+}
+
+/// Test AES-128-CTR decryption
+pub fn aes_128_ctr_test_decrypt<A: AesCtr<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
+ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.2
+ let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
+ let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ let mut block: [u8; 16];
+ let mut cipher = A::new(&key, iv);
+
+ block = hex!("874d6191b620e3261bef6864990db6ce");
+ cipher.encrypt(&mut block);
+ let expected_plaintext_1 = hex!("6bc1bee22e409f96e93d7e117393172a");
+ assert_eq!(expected_plaintext_1, block);
+
+ block = hex!("9806f66b7970fdff8617187bb9fffdff");
+ cipher.encrypt(&mut block);
+ let expected_plaintext_2 = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
+ assert_eq!(expected_plaintext_2, block);
+
+ block = hex!("5ae4df3edbd5d35e5b4f09020db03eab");
+ cipher.encrypt(&mut block);
+ let expected_plaintext_3 = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
+ assert_eq!(expected_plaintext_3, block);
+
+ block = hex!("1e031dda2fbe03d1792170a0f3009cee");
+ cipher.encrypt(&mut block);
+ let expected_plaintext_3 = hex!("f69f2445df4f9b17ad2b417be66c3710");
+ assert_eq!(expected_plaintext_3, block);
+}
+
+/// Test AES-256-CTR encryption
+pub fn aes_256_ctr_test_encrypt<A: AesCtr<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
+ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.5
+ let key: Aes256Key =
+ hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
+ let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ let mut block: [u8; 16];
+ let mut cipher = A::new(&key, iv);
+
+ block = hex!("6bc1bee22e409f96e93d7e117393172a");
+ cipher.encrypt(&mut block);
+ let expected_ciphertext_1 = hex!("601ec313775789a5b7a7f504bbf3d228");
+ assert_eq!(expected_ciphertext_1, block);
+
+ block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
+ cipher.encrypt(&mut block);
+ let expected_ciphertext_2 = hex!("f443e3ca4d62b59aca84e990cacaf5c5");
+ assert_eq!(expected_ciphertext_2, block);
+
+ block = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
+ cipher.encrypt(&mut block);
+ let expected_ciphertext_3 = hex!("2b0930daa23de94ce87017ba2d84988d");
+ assert_eq!(expected_ciphertext_3, block);
+
+ block = hex!("f69f2445df4f9b17ad2b417be66c3710");
+ cipher.encrypt(&mut block);
+ let expected_ciphertext_3 = hex!("dfc9c58db67aada613c2dd08457941a6");
+ assert_eq!(expected_ciphertext_3, block);
+}
+
+/// Test AES-256-CTR decryption
+pub fn aes_256_ctr_test_decrypt<A: AesCtr<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
+ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.5.6
+ let key: Aes256Key =
+ hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
+ let iv = hex!("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
+ let mut block: [u8; 16];
+ let mut cipher = A::new(&key, iv);
+
+ block = hex!("601ec313775789a5b7a7f504bbf3d228");
+ cipher.encrypt(&mut block);
+ let expected_plaintext_1 = hex!("6bc1bee22e409f96e93d7e117393172a");
+ assert_eq!(expected_plaintext_1, block);
+
+ block = hex!("f443e3ca4d62b59aca84e990cacaf5c5");
+ cipher.encrypt(&mut block);
+ let expected_plaintext_2 = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
+ assert_eq!(expected_plaintext_2, block);
+
+ block = hex!("2b0930daa23de94ce87017ba2d84988d");
+ cipher.encrypt(&mut block);
+ let expected_plaintext_3 = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
+ assert_eq!(expected_plaintext_3, block);
+
+ block = hex!("dfc9c58db67aada613c2dd08457941a6");
+ cipher.encrypt(&mut block);
+ let expected_plaintext_3 = hex!("f69f2445df4f9b17ad2b417be66c3710");
+ assert_eq!(expected_plaintext_3, block);
+}
+
+/// Generates the test cases to validate the AES-128-CTR implementation.
+/// For example, to test `MyAesCtr128Impl`:
+///
+/// ```
+/// use crypto_provider::aes::ctr::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_128_ctr_test_cases)]
+/// fn aes_128_ctr_tests(testcase: CryptoProviderTestCase<MyAesCtr128Impl>) {
+/// testcase(MyAesCtr128Impl);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::encrypt(aes_128_ctr_test_encrypt)]
+#[case::decrypt(aes_128_ctr_test_decrypt)]
+fn aes_128_ctr_test_cases<F: AesCtrFactory<Key = Aes128Key>>(
+ #[case] testcase: CryptoProviderTestCase<F>,
+) {
+}
+
+/// Generates the test cases to validate the AES-256-CTR implementation.
+/// For example, to test `MyAesCtr256Impl`:
+///
+/// ```
+/// use crypto_provider::aes::ctr::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_256_ctr_test_cases_impl)]
+/// fn aes_256_ctr_tests(testcase: CryptoProviderTestCase<MyAesCtr256Impl>) {
+/// testcase(MyAesCtr256Impl);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::encrypt(aes_256_ctr_test_encrypt)]
+#[case::decrypt(aes_256_ctr_test_decrypt)]
+fn aes_256_ctr_test_cases<F: AesCtrFactory<Key = Aes256Key>>(
+ #[case] testcase: CryptoProviderTestCase<F>,
+) {
+}
diff --git a/nearby/crypto/crypto_provider_test/src/aes/gcm_siv.rs b/nearby/crypto/crypto_provider_test/src/aes/gcm_siv.rs
new file mode 100644
index 0000000..b27e61c
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/aes/gcm_siv.rs
@@ -0,0 +1,122 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+use alloc::vec::Vec;
+use core::marker;
+
+use hex_literal::hex;
+use rstest_reuse::template;
+
+use crate::aes::{Aes128Key, Aes256Key};
+pub use crate::prelude;
+
+use crypto_provider::aes::gcm_siv::AesGcmSiv;
+
+/// Test AES-GCM-SIV-128 encryption/decryption
+pub fn aes_128_gcm_siv_test<A: AesGcmSiv<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
+ // https://github.com/google/wycheproof/blob/master/testvectors/aes_gcm_siv_test.json
+ // TC1
+ let test_key = hex!("01000000000000000000000000000000");
+ let nonce = hex!("030000000000000000000000");
+ let aes = A::new(&test_key.into());
+ let msg = hex!("");
+ let mut buf = Vec::from(msg.as_slice());
+ let tag = hex!("dc20e2d83f25705bb49e439eca56de25");
+ assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
+ assert_eq!(&buf[..], &tag);
+ // TC2
+ let msg = hex!("0100000000000000");
+ let ct = hex!("b5d839330ac7b786");
+ let tag = hex!("578782fff6013b815b287c22493a364c");
+ let mut buf = Vec::from(msg.as_slice());
+ assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
+ assert_eq!(&buf[..8], &ct);
+ assert_eq!(&buf[8..], &tag);
+ assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
+ assert_eq!(&buf[..], &msg);
+}
+
+/// Test AES-256-GCM-SIV encryption/decryption
+pub fn aes_256_gcm_siv_test<A: AesGcmSiv<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
+ // https://github.com/google/wycheproof/blob/master/testvectors/aes_gcm_siv_test.json
+ // TC77
+ let test_key = hex!("0100000000000000000000000000000000000000000000000000000000000000");
+ let nonce = hex!("030000000000000000000000");
+ let aes = A::new(&test_key.into());
+ let msg = hex!("0100000000000000");
+ let mut buf = Vec::new();
+ buf.extend_from_slice(&msg);
+ let ct = hex!("c2ef328e5c71c83b");
+ let tag = hex!("843122130f7364b761e0b97427e3df28");
+ assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
+ assert_eq!(&buf[..8], &ct);
+ assert_eq!(&buf[8..], &tag);
+ assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
+ assert_eq!(&buf[..], &msg);
+ // TC78
+ let msg = hex!("010000000000000000000000");
+ let ct = hex!("9aab2aeb3faa0a34aea8e2b1");
+ let tag = hex!("8ca50da9ae6559e48fd10f6e5c9ca17e");
+ let mut buf = Vec::from(msg.as_slice());
+ assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
+ assert_eq!(&buf[..12], &ct);
+ assert_eq!(&buf[12..], &tag);
+ assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
+ assert_eq!(&buf[..], &msg);
+}
+
+/// Generates the test cases to validate the AES-128-GCM-SIV implementation.
+/// For example, to test `MyAesGcmSiv128Impl`:
+///
+/// ```
+/// use crypto_provider::aes::gcm_siv::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_128_gcm_siv_test_cases)]
+/// fn aes_128_gcm_siv_tests(testcase: CryptoProviderTestCase<MyAesGcmSivImpl>) {
+/// testcase(MyAesGcmSiv128Impl);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::encrypt(aes_128_gcm_siv_test)]
+#[case::decrypt(aes_128_gcm_siv_test)]
+fn aes_128_gcm_siv_test_cases<F: AesGcmSivFactory<Key = Aes128Key>>(
+ #[case] testcase: CryptoProviderTestCase<F>,
+) {
+}
+
+/// Generates the test cases to validate the AES-256-GCM-SIV implementation.
+/// For example, to test `MyAesGcmSiv256Impl`:
+///
+/// ```
+/// use crypto_provider::aes::gcm_siv::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_256_gcm_siv_test_cases)]
+/// fn aes_256_gcm_siv_tests(testcase: CryptoProviderTestCase<MyAesGcmSiv256Impl>) {
+/// testcase(MyAesGcmSiv256Impl);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::encrypt(aes_256_gcm_siv_test)]
+#[case::decrypt(aes_256_gcm_siv_test)]
+fn aes_256_gcm_siv_test_cases<F: AesGcmSivFactory<Key = Aes256Key>>(
+ #[case] testcase: CryptoProviderTestCase<F>,
+) {
+}
diff --git a/nearby/crypto/crypto_provider_test/src/aes/mod.rs b/nearby/crypto/crypto_provider_test/src/aes/mod.rs
new file mode 100644
index 0000000..e1489da
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/aes/mod.rs
@@ -0,0 +1,210 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+pub mod cbc;
+pub mod ctr;
+pub mod gcm_siv;
+
+pub use crate::prelude::*;
+
+use core::marker;
+use crypto_provider::aes::*;
+use hex_literal::hex;
+use rstest_reuse::template;
+
+/// Test encryption with AES-128
+pub fn aes_128_test_encrypt<A: AesEncryptCipher<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
+ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.1
+ let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
+ let mut block = [0_u8; 16];
+ let enc_cipher = A::new(&key);
+
+ block.copy_from_slice(&hex!("6bc1bee22e409f96e93d7e117393172a"));
+ enc_cipher.encrypt(&mut block);
+ assert_eq!(hex!("3ad77bb40d7a3660a89ecaf32466ef97"), block);
+
+ block.copy_from_slice(&hex!("ae2d8a571e03ac9c9eb76fac45af8e51"));
+ enc_cipher.encrypt(&mut block);
+ assert_eq!(hex!("f5d3d58503b9699de785895a96fdbaaf"), block);
+
+ block.copy_from_slice(&hex!("30c81c46a35ce411e5fbc1191a0a52ef"));
+ enc_cipher.encrypt(&mut block);
+ assert_eq!(hex!("43b1cd7f598ece23881b00e3ed030688"), block);
+
+ block.copy_from_slice(&hex!("f69f2445df4f9b17ad2b417be66c3710"));
+ enc_cipher.encrypt(&mut block);
+ assert_eq!(hex!("7b0c785e27e8ad3f8223207104725dd4"), block);
+}
+
+/// Test decryption with AES-128
+pub fn aes_128_test_decrypt<A: AesDecryptCipher<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
+ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.2
+ let key: Aes128Key = hex!("2b7e151628aed2a6abf7158809cf4f3c").into();
+ let mut block = [0_u8; 16];
+ let dec_cipher = A::new(&key);
+
+ block.copy_from_slice(&hex!("3ad77bb40d7a3660a89ecaf32466ef97"));
+ dec_cipher.decrypt(&mut block);
+ assert_eq!(hex!("6bc1bee22e409f96e93d7e117393172a"), block);
+
+ block.copy_from_slice(&hex!("f5d3d58503b9699de785895a96fdbaaf"));
+ dec_cipher.decrypt(&mut block);
+ assert_eq!(hex!("ae2d8a571e03ac9c9eb76fac45af8e51"), block);
+
+ block.copy_from_slice(&hex!("43b1cd7f598ece23881b00e3ed030688"));
+ dec_cipher.decrypt(&mut block);
+ assert_eq!(hex!("30c81c46a35ce411e5fbc1191a0a52ef"), block);
+
+ block.copy_from_slice(&hex!("7b0c785e27e8ad3f8223207104725dd4"));
+ dec_cipher.decrypt(&mut block);
+ assert_eq!(hex!("f69f2445df4f9b17ad2b417be66c3710"), block);
+}
+
+/// Test encryption with AES-256
+pub fn aes_256_test_encrypt<A: AesEncryptCipher<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
+ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.5
+ let key: Aes256Key =
+ hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
+ let mut block: [u8; 16];
+ let enc_cipher = A::new(&key);
+
+ block = hex!("6bc1bee22e409f96e93d7e117393172a");
+ enc_cipher.encrypt(&mut block);
+ assert_eq!(hex!("f3eed1bdb5d2a03c064b5a7e3db181f8"), block);
+
+ block = hex!("ae2d8a571e03ac9c9eb76fac45af8e51");
+ enc_cipher.encrypt(&mut block);
+ assert_eq!(hex!("591ccb10d410ed26dc5ba74a31362870"), block);
+
+ block = hex!("30c81c46a35ce411e5fbc1191a0a52ef");
+ enc_cipher.encrypt(&mut block);
+ assert_eq!(hex!("b6ed21b99ca6f4f9f153e7b1beafed1d"), block);
+
+ block = hex!("f69f2445df4f9b17ad2b417be66c3710");
+ enc_cipher.encrypt(&mut block);
+ assert_eq!(hex!("23304b7a39f9f3ff067d8d8f9e24ecc7"), block);
+}
+
+/// Test decryption with AES-256
+pub fn aes_256_test_decrypt<A: AesDecryptCipher<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
+ // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.6
+ let key: Aes256Key =
+ hex!("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4").into();
+ let mut block: [u8; 16];
+ let dec_cipher = A::new(&key);
+
+ block = hex!("f3eed1bdb5d2a03c064b5a7e3db181f8");
+ dec_cipher.decrypt(&mut block);
+ assert_eq!(hex!("6bc1bee22e409f96e93d7e117393172a"), block);
+
+ block = hex!("591ccb10d410ed26dc5ba74a31362870");
+ dec_cipher.decrypt(&mut block);
+ assert_eq!(hex!("ae2d8a571e03ac9c9eb76fac45af8e51"), block);
+
+ block = hex!("b6ed21b99ca6f4f9f153e7b1beafed1d");
+ dec_cipher.decrypt(&mut block);
+ assert_eq!(hex!("30c81c46a35ce411e5fbc1191a0a52ef"), block);
+
+ block = hex!("23304b7a39f9f3ff067d8d8f9e24ecc7");
+ dec_cipher.decrypt(&mut block);
+ assert_eq!(hex!("f69f2445df4f9b17ad2b417be66c3710"), block);
+}
+
+/// Generates the test cases to validate the AES-128 implementation.
+/// For example, to test `MyAes128Impl`:
+///
+/// ```
+/// use crypto_provider::aes::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_128_encrypt_test_cases)]
+/// fn aes_128_tests(f: CryptoProviderTestCase<MyAes128Impl>) {
+/// f(MyAes128Impl);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::encrypt(aes_128_test_encrypt)]
+fn aes_128_encrypt_test_cases<A: AesFactory<Key = Aes128Key>>(
+ #[case] testcase: CryptoProviderTestCase<F>,
+) {
+}
+
+/// Generates the test cases to validate the AES-128 implementation.
+/// For example, to test `MyAes128Impl`:
+///
+/// ```
+/// use crypto_provider::aes::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_128_decrypt_test_cases)]
+/// fn aes_128_tests(f: CryptoProviderTestCase<MyAes128Impl>) {
+/// f(MyAes128Impl);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::decrypt(aes_128_test_decrypt)]
+fn aes_128_decrypt_test_cases<F: AesFactory<Key = Aes128Key>>(
+ #[case] testcase: CryptoProviderTestCase<F>,
+) {
+}
+
+/// Generates the test cases to validate the AES-256 implementation.
+/// For example, to test `MyAes256Impl`:
+///
+/// ```
+/// use crypto_provider::aes::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_256_encrypt_test_cases)]
+/// fn aes_256_tests(f: CryptoProviderTestCase<MyAes256Impl>) {
+/// f(MyAes256Impl);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::encrypt(aes_256_test_encrypt)]
+fn aes_256_encrypt_test_cases<F: AesFactory<Key = Aes256Key>>(
+ #[case] testcase: CryptoProviderTestCase<F>,
+) {
+}
+
+/// Generates the test cases to validate the AES-256 implementation.
+/// For example, to test `MyAes256Impl`:
+///
+/// ```
+/// use crypto_provider::aes::testing::*;
+///
+/// mod tests {
+/// #[apply(aes_256_decrypt_test_cases)]
+/// fn aes_256_tests(f: CryptoProviderTestCase<MyAes256Impl>) {
+/// f(MyAes256Impl);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::decrypt(aes_256_test_decrypt)]
+fn aes_256_decrypt_test_cases<F: AesFactory<Key = Aes256Key>>(
+ #[case] testcase: CryptoProviderTestCase<F>,
+) {
+}
diff --git a/nearby/crypto/crypto_provider_test/src/ed25519.rs b/nearby/crypto/crypto_provider_test/src/ed25519.rs
new file mode 100644
index 0000000..c2da3b3
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/ed25519.rs
@@ -0,0 +1,151 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+extern crate alloc;
+extern crate std;
+
+use alloc::borrow::ToOwned;
+use alloc::string::String;
+use alloc::vec::Vec;
+use crypto_provider::ed25519::{Ed25519Provider, KeyPair, PublicKey, Signature};
+use wycheproof::TestResult;
+
+// These are test vectors from the creators of Ed25519: https://ed25519.cr.yp.to/ which are referenced
+// as the SOT for the test vectors in the RFC: https://www.rfc-editor.org/rfc/rfc8032#section-7.1
+// The vectors have been formatted into a easily parsable/readable format by libgcrypt which is
+// also used for test cases in the above RFC:
+// https://dev.gnupg.org/source/libgcrypt/browse/master/tests/t-ed25519.inp
+const PATH_TO_RFC_VECTORS_FILE: &str =
+ "crypto/crypto_provider_test/src/testdata/ecdsa/rfc_test_vectors.txt";
+
+/// Runs set of Ed25519 wycheproof test vectors against a provided ed25519 implementation
+/// Tests vectors from Project Wycheproof: <https://github.com/google/wycheproof>
+pub fn run_wycheproof_test_vectors<E>()
+where
+ E: Ed25519Provider,
+{
+ let test_set = wycheproof::eddsa::TestSet::load(wycheproof::eddsa::TestName::Ed25519)
+ .expect("should be able to load test set");
+
+ for test_group in test_set.test_groups {
+ let key_pair = test_group.key;
+ let public_key = key_pair.pk;
+ let secret_key = key_pair.sk;
+
+ for test in test_group.tests {
+ let tc_id = test.tc_id;
+ let comment = test.comment;
+ let sig = test.sig;
+ let msg = test.msg;
+
+ let valid = match test.result {
+ TestResult::Invalid => false,
+ TestResult::Valid | TestResult::Acceptable => true,
+ };
+ let result = run_test::<E>(
+ public_key.clone(),
+ secret_key.clone(),
+ sig.clone(),
+ msg.clone(),
+ );
+ if valid {
+ if let Err(desc) = result {
+ panic!(
+ "\n\
+ Failed test {}: {}\n\
+ msg:\t{:?}\n\
+ sig:\t{:?}\n\
+ comment:\t{:?}\n",
+ tc_id, desc, msg, sig, comment,
+ );
+ }
+ } else {
+ assert!(result.is_err())
+ }
+ }
+ }
+}
+
+/// Runs the RFC specified test vectors against an Ed25519 implementation
+pub fn run_rfc_test_vectors<E>()
+where
+ E: Ed25519Provider,
+{
+ let file_contents =
+ std::fs::read_to_string(test_helper::get_data_file(PATH_TO_RFC_VECTORS_FILE))
+ .expect("should be able to read file");
+
+ let mut split_cases: Vec<&str> = file_contents.as_str().split("\n\n").collect();
+ // remove the comments
+ split_cases.remove(0);
+ for case in split_cases {
+ let test_case: Vec<&str> = case.split('\n').collect();
+
+ let tc_id = extract_string(test_case[0]);
+ let sk = extract_hex(test_case[1]);
+ let pk = extract_hex(test_case[2]);
+ let msg = extract_hex(test_case[3]);
+ let sig = extract_hex(test_case[4]);
+
+ let result = run_test::<E>(pk.clone(), sk.clone(), sig.clone(), msg.clone());
+ if let Err(desc) = result {
+ panic!(
+ "\n\
+ Failed test {}: {}\n\
+ msg:\t{:?}\n\
+ sig:\t{:?}\n\"",
+ tc_id, desc, msg, sig,
+ );
+ }
+ }
+}
+
+fn extract_hex(line: &str) -> Vec<u8> {
+ test_helper::string_to_hex(extract_string(line).as_str())
+}
+
+fn extract_string(line: &str) -> String {
+ line.split(':').collect::<Vec<&str>>()[1].trim().to_owned()
+}
+
+fn run_test<E>(
+ pub_key: Vec<u8>,
+ secret_key: Vec<u8>,
+ sig: Vec<u8>,
+ msg: Vec<u8>,
+) -> Result<(), &'static str>
+where
+ E: Ed25519Provider,
+{
+ let kp_bytes: [u8; 64] = [secret_key.as_slice(), pub_key.as_slice()]
+ .concat()
+ .try_into()
+ .map_err(|_| "invalid length keypair")?;
+ let kp = E::KeyPair::from_bytes(kp_bytes)
+ .map_err(|_| "Should be able to create Keypair from bytes")?;
+
+ let sig_result = kp.sign(msg.as_slice());
+ (sig.as_slice() == sig_result.to_bytes())
+ .then_some(())
+ .ok_or("sig not matching expected")?;
+ let signature = E::Signature::from_bytes(sig.as_slice())
+ .map_err(|_| "unable to parse sign from test case")?;
+
+ let pub_key = kp.public();
+ pub_key
+ .verify_strict(msg.as_slice(), &signature)
+ .map_err(|_| "verify failed")?;
+
+ Ok(())
+}
diff --git a/nearby/crypto/crypto_provider_test/src/elliptic_curve.rs b/nearby/crypto/crypto_provider_test/src/elliptic_curve.rs
new file mode 100644
index 0000000..4807d25
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/elliptic_curve.rs
@@ -0,0 +1,26 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crypto_provider::elliptic_curve::*;
+
+/// Trait for an ephemeral secret for functions used in testing.
+pub trait EphemeralSecretForTesting<C: Curve>: EphemeralSecret<C> {
+ /// Creates an ephemeral secret from the given private and public components.
+ fn from_private_components(
+ _private_bytes: &[u8; 32],
+ _public_key: &<Self::Impl as EcdhProvider<C>>::PublicKey,
+ ) -> Result<Self, Self::Error>
+ where
+ Self: Sized;
+}
diff --git a/nearby/crypto/crypto_provider_test/src/hkdf.rs b/nearby/crypto/crypto_provider_test/src/hkdf.rs
new file mode 100644
index 0000000..5780263
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/hkdf.rs
@@ -0,0 +1,297 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+extern crate alloc;
+pub use crate::prelude::*;
+use crate::CryptoProvider;
+use alloc::vec;
+use alloc::vec::Vec;
+use core::iter;
+use core::marker::PhantomData;
+use crypto_provider::hkdf::Hkdf;
+use hex_literal::hex;
+use rstest_reuse::template;
+
+/// Generates the test cases to validate the hkdf implementation.
+/// For example, to test `MyCryptoProvider`:
+///
+/// ```
+/// mod tests {
+/// use std::marker::PhantomData;
+/// use crypto_provider::testing::CryptoProviderTestCase;
+/// #[apply(hkdf_test_cases)]
+/// fn hkdf_tests(testcase: CryptoProviderTestCase<MyCryptoProvider>){
+/// testcase(PhantomData::<MyCryptoProvider>);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::basic_test_hkdf(basic_test_hkdf)]
+#[case::test_rfc5869_sha256(test_rfc5869_sha256)]
+#[case::test_lengths(test_lengths)]
+#[case::test_max_length(test_max_length)]
+#[case::test_max_length_exceeded(test_max_length_exceeded)]
+#[case::test_unsupported_length(test_unsupported_length)]
+#[case::test_expand_multi_info(test_expand_multi_info)]
+#[case::run_hkdf_sha256_vectors(run_hkdf_sha256_vectors)]
+#[case::run_hkdf_sha512_vectors(run_hkdf_sha512_vectors)]
+fn hkdf_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
+
+const MAX_SHA256_LENGTH: usize = 255 * (256 / 8); // =8160
+
+///
+pub struct Test<'a> {
+ ikm: &'a [u8],
+ salt: &'a [u8],
+ info: &'a [u8],
+ okm: &'a [u8],
+}
+
+/// data taken from sample code in Readme of crates.io page
+pub fn basic_test_hkdf<C: CryptoProvider>(_: PhantomData<C>) {
+ let ikm = hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+ let salt = hex!("000102030405060708090a0b0c");
+ let info = hex!("f0f1f2f3f4f5f6f7f8f9");
+
+ let hk = C::HkdfSha256::new(Some(&salt[..]), &ikm);
+ let mut okm = [0u8; 42];
+ hk.expand(&info, &mut okm)
+ .expect("42 is a valid length for Sha256 to output");
+
+ let expected = hex!(
+ "
+ 3cb25f25faacd57a90434f64d0362f2a
+ 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+ 34007208d5b887185865
+ "
+ );
+ assert_eq!(okm, expected);
+}
+
+// Test Vectors from https://tools.ietf.org/html/rfc5869.
+#[rustfmt::skip]
+ ///
+ pub fn test_rfc5869_sha256<C: CryptoProvider>(_: PhantomData<C>) {
+ let tests = [
+ Test {
+ // Test Case 1
+ ikm: &hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ salt: &hex!("000102030405060708090a0b0c"),
+ info: &hex!("f0f1f2f3f4f5f6f7f8f9"),
+ okm: &hex!("
+ 3cb25f25faacd57a90434f64d0362f2a
+ 2d2d0a90cf1a5a4c5db02d56ecc4c5bf
+ 34007208d5b887185865
+ "),
+ },
+ Test {
+ // Test Case 2
+ ikm: &hex!("
+ 000102030405060708090a0b0c0d0e0f
+ 101112131415161718191a1b1c1d1e1f
+ 202122232425262728292a2b2c2d2e2f
+ 303132333435363738393a3b3c3d3e3f
+ 404142434445464748494a4b4c4d4e4f
+ "),
+ salt: &hex!("
+ 606162636465666768696a6b6c6d6e6f
+ 707172737475767778797a7b7c7d7e7f
+ 808182838485868788898a8b8c8d8e8f
+ 909192939495969798999a9b9c9d9e9f
+ a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
+ "),
+ info: &hex!("
+ b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+ e0e1e2e3e4e5e6e7e8e9eaebecedeeef
+ f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+ "),
+ okm: &hex!("
+ b11e398dc80327a1c8e7f78c596a4934
+ 4f012eda2d4efad8a050cc4c19afa97c
+ 59045a99cac7827271cb41c65e590e09
+ da3275600c2f09b8367793a9aca3db71
+ cc30c58179ec3e87c14c01d5c1f3434f
+ 1d87
+ "),
+ },
+ Test {
+ // Test Case 3
+ ikm: &hex!("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+ salt: &hex!(""),
+ info: &hex!(""),
+ okm: &hex!("
+ 8da4e775a563c18f715f802a063c5a31
+ b8a11f5c5ee1879ec3454e5f3c738d2d
+ 9d201395faa4b61a96c8
+ "),
+ },
+ ];
+ for Test { ikm, salt, info, okm } in tests.iter() {
+ let salt = if salt.is_empty() {
+ None
+ } else {
+ Some(&salt[..])
+ };
+ let hkdf = C::HkdfSha256::new(salt, ikm);
+ let mut okm2 = vec![0u8; okm.len()];
+ assert!(hkdf.expand(&info[..], &mut okm2).is_ok());
+ assert_eq!(okm2[..], okm[..]);
+ }
+ }
+
+///
+pub fn test_lengths<C: CryptoProvider>(_: PhantomData<C>) {
+ let hkdf = C::HkdfSha256::new(None, &[]);
+ let mut longest = vec![0u8; MAX_SHA256_LENGTH];
+ assert!(hkdf.expand(&[], &mut longest).is_ok());
+ // Runtime is O(length), so exhaustively testing all legal lengths
+ // would take too long (at least without --release). Only test a
+ // subset: the first 500, the last 10, and every 100th in between.
+ // 0 is an invalid key length for openssl, so start at 1
+ let lengths = (1..MAX_SHA256_LENGTH + 1)
+ .filter(|&len| !(500..=MAX_SHA256_LENGTH - 10).contains(&len) || len % 100 == 0);
+
+ for length in lengths {
+ let mut okm = vec![0u8; length];
+
+ assert!(hkdf.expand(&[], &mut okm).is_ok());
+ assert_eq!(okm.len(), length);
+ assert_eq!(okm[..], longest[..length]);
+ }
+}
+
+///
+pub fn test_max_length<C: CryptoProvider>(_: PhantomData<C>) {
+ let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
+ let mut okm = vec![0u8; MAX_SHA256_LENGTH];
+ assert!(hkdf.expand(&[], &mut okm).is_ok());
+}
+
+///
+pub fn test_max_length_exceeded<C: CryptoProvider>(_: PhantomData<C>) {
+ let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
+ let mut okm = vec![0u8; MAX_SHA256_LENGTH + 1];
+ assert!(hkdf.expand(&[], &mut okm).is_err());
+}
+
+///
+pub fn test_unsupported_length<C: CryptoProvider>(_: PhantomData<C>) {
+ let hkdf = C::HkdfSha256::new(Some(&[]), &[]);
+ let mut okm = vec![0u8; 90000];
+ assert!(hkdf.expand(&[], &mut okm).is_err());
+}
+
+///
+pub fn test_expand_multi_info<C: CryptoProvider>(_: PhantomData<C>) {
+ let info_components = &[
+ &b"09090909090909090909090909090909090909090909"[..],
+ &b"8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a"[..],
+ &b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0"[..],
+ &b"4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c4"[..],
+ &b"1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d"[..],
+ ];
+
+ let hkdf = C::HkdfSha256::new(None, b"some ikm here");
+
+ // Compute HKDF-Expand on the concatenation of all the info components
+ let mut oneshot_res = [0u8; 16];
+ hkdf.expand(&info_components.concat(), &mut oneshot_res)
+ .unwrap();
+
+ // Now iteratively join the components of info_components until it's all 1 component. The value
+ // of HKDF-Expand should be the same throughout
+ let mut num_concatted = 0;
+ let mut info_head = Vec::new();
+
+ while num_concatted < info_components.len() {
+ info_head.extend(info_components[num_concatted]);
+
+ // Build the new input to be the info head followed by the remaining components
+ let input: Vec<&[u8]> = iter::once(info_head.as_slice())
+ .chain(info_components.iter().cloned().skip(num_concatted + 1))
+ .collect();
+
+ // Compute and compare to the one-shot answer
+ let mut multipart_res = [0u8; 16];
+ hkdf.expand_multi_info(&input, &mut multipart_res).unwrap();
+ assert_eq!(multipart_res, oneshot_res);
+ num_concatted += 1;
+ }
+}
+
+///
+pub fn run_hkdf_sha256_vectors<C: CryptoProvider>(_: PhantomData<C>) {
+ run_hkdf_test_vectors::<C::HkdfSha256>(HashAlg::Sha256)
+}
+
+///
+pub fn run_hkdf_sha512_vectors<C: CryptoProvider>(_: PhantomData<C>) {
+ run_hkdf_test_vectors::<C::HkdfSha512>(HashAlg::Sha512)
+}
+
+enum HashAlg {
+ Sha256,
+ Sha512,
+}
+
+///
+fn run_hkdf_test_vectors<K: Hkdf>(hash: HashAlg) {
+ let test_name = match hash {
+ HashAlg::Sha256 => wycheproof::hkdf::TestName::HkdfSha256,
+ HashAlg::Sha512 => wycheproof::hkdf::TestName::HkdfSha512,
+ };
+
+ let test_set =
+ wycheproof::hkdf::TestSet::load(test_name).expect("should be able to load test set");
+ for test_group in test_set.test_groups {
+ for test in test_group.tests {
+ let ikm = test.ikm;
+ let salt = test.salt;
+ let info = test.info;
+ let okm = test.okm;
+ let tc_id = test.tc_id;
+ if let Some(desc) = run_test::<K>(
+ ikm.as_slice(),
+ salt.as_slice(),
+ info.as_slice(),
+ okm.as_slice(),
+ ) {
+ panic!(
+ "\n\
+ Failed test {tc_id}: {desc}\n\
+ ikm:\t{ikm:?}\n\
+ salt:\t{salt:?}\n\
+ info:\t{info:?}\n\
+ okm:\t{okm:?}\n"
+ );
+ }
+ }
+ }
+}
+
+fn run_test<K: Hkdf>(ikm: &[u8], salt: &[u8], info: &[u8], okm: &[u8]) -> Option<&'static str> {
+ let prk = K::new(Some(salt), ikm);
+ let mut got_okm = vec![0; okm.len()];
+
+ if prk.expand(info, &mut got_okm).is_err() {
+ return Some("prk expand");
+ }
+ if got_okm != okm {
+ return Some("mismatch in okm");
+ }
+ None
+}
diff --git a/nearby/crypto/crypto_provider_test/src/hmac.rs b/nearby/crypto/crypto_provider_test/src/hmac.rs
new file mode 100644
index 0000000..e3d1c0e
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/hmac.rs
@@ -0,0 +1,130 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+pub use crate::prelude::*;
+use crate::rstest_reuse::template;
+use crate::CryptoProvider;
+use core::cmp::min;
+use core::marker::PhantomData;
+use crypto_provider::hmac::Hmac;
+use wycheproof::TestResult;
+
+/// Generates the test cases to validate the hmac implementation.
+/// For example, to test `MyCryptoProvider`:
+///
+/// ```
+/// mod tests {
+/// use std::marker::PhantomData;
+/// use crypto_provider::testing::CryptoProviderTestCase;
+/// #[apply(hmac_test_cases)]
+/// fn hmac_tests(testcase: CryptoProviderTestCase<MyCryptoProvider>){
+/// testcase(PhantomData::<MyCryptoProvider>);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::hmac_sha256_test_vectors(hmac_sha256_test_vectors)]
+#[case::hmac_sha512_test_vectors(hmac_sha512_test_vectors)]
+fn hmac_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
+
+/// Run wycheproof hmac sha256 test vectors on provided CryptoProvider
+pub fn hmac_sha256_test_vectors<C: CryptoProvider>(_: PhantomData<C>) {
+ run_hmac_test_vectors::<32, C::HmacSha256>(HashAlg::Sha256)
+}
+
+/// Run wycheproof hmac sha512 test vectors on provided CryptoProvider
+pub fn hmac_sha512_test_vectors<C: CryptoProvider>(_: PhantomData<C>) {
+ run_hmac_test_vectors::<64, C::HmacSha512>(HashAlg::Sha512)
+}
+
+enum HashAlg {
+ Sha256,
+ Sha512,
+}
+
+// Tests vectors from Project Wycheproof:
+// https://github.com/google/wycheproof
+fn run_hmac_test_vectors<const N: usize, H: Hmac<N>>(hash: HashAlg) {
+ let test_name = match hash {
+ HashAlg::Sha256 => wycheproof::mac::TestName::HmacSha256,
+ HashAlg::Sha512 => wycheproof::mac::TestName::HmacSha512,
+ };
+ let test_set =
+ wycheproof::mac::TestSet::load(test_name).expect("should be able to load test set");
+
+ for test_group in test_set.test_groups {
+ for test in test_group.tests {
+ let key = test.key;
+ let msg = test.msg;
+ let tag = test.tag;
+ let tc_id = test.tc_id;
+ let valid = match test.result {
+ TestResult::Valid | TestResult::Acceptable => true,
+ TestResult::Invalid => false,
+ };
+
+ if let Some(desc) =
+ run_test::<N, H>(key.as_slice(), msg.as_slice(), tag.as_slice(), valid)
+ {
+ panic!(
+ "\n\
+ Failed test {tc_id}: {desc}\n\
+ key:\t{key:?}\n\
+ msg:\t{msg:?}\n\
+ tag:\t{tag:?}\n",
+ );
+ }
+ }
+ }
+}
+
+fn run_test<const N: usize, H: Hmac<N>>(
+ key: &[u8],
+ input: &[u8],
+ tag: &[u8],
+ valid_data: bool,
+) -> Option<&'static str> {
+ let mut mac = H::new_from_slice(key).unwrap();
+ mac.update(input);
+ let result = mac.finalize();
+ let n = tag.len();
+ let result_bytes = &result[..n];
+
+ if valid_data {
+ if result_bytes != tag {
+ return Some("whole message");
+ }
+ } else {
+ return if result_bytes == tag {
+ Some("invalid should not match")
+ } else {
+ None
+ };
+ }
+
+ // test reading different chunk sizes
+ for chunk_size in 1..min(64, input.len()) {
+ let mut mac = H::new_from_slice(key).unwrap();
+ for chunk in input.chunks(chunk_size) {
+ mac.update(chunk);
+ }
+ let res = mac.verify_truncated_left(tag);
+ if res.is_err() {
+ return Some("chunked message");
+ }
+ }
+
+ None
+}
diff --git a/nearby/crypto/crypto_provider_test/src/lib.rs b/nearby/crypto/crypto_provider_test/src/lib.rs
new file mode 100644
index 0000000..f7d6253
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/lib.rs
@@ -0,0 +1,121 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+extern crate alloc;
+
+use alloc::{format, string::String};
+use core::marker::PhantomData;
+
+use crypto_provider::CryptoProvider;
+use hex_literal::hex;
+use rand::{Rng, RngCore};
+use rstest_reuse::template;
+
+pub use rstest_reuse;
+
+pub mod aes;
+pub mod ed25519;
+pub mod elliptic_curve;
+pub mod hkdf;
+pub mod hmac;
+pub mod p256;
+pub mod sha2;
+pub mod x25519;
+
+/// Common items that needs to be imported to use these test cases
+pub mod prelude {
+ pub use super::CryptoProviderTestCase;
+ pub use rstest::rstest;
+ pub use rstest_reuse;
+ pub use rstest_reuse::apply;
+}
+
+/// A test case for Crypto Provider. A test case is a function that panics if the test fails.
+pub type CryptoProviderTestCase<T> = fn(PhantomData<T>);
+
+#[derive(Debug)]
+pub(crate) struct TestError(String);
+
+impl TestError {
+ pub(crate) fn new<D: core::fmt::Debug>(value: D) -> Self {
+ Self(format!("{value:?}"))
+ }
+}
+
+/// Test for `constant_time_eq` when the two inputs are equal.
+pub fn constant_time_eq_test_equal<C: CryptoProvider>(_marker: PhantomData<C>) {
+ assert!(C::constant_time_eq(
+ &hex!("00010203040506070809"),
+ &hex!("00010203040506070809")
+ ));
+}
+
+/// Test for `constant_time_eq` when the two inputs are not equal.
+pub fn constant_time_eq_test_not_equal<C: CryptoProvider>(_marker: PhantomData<C>) {
+ assert!(!C::constant_time_eq(
+ &hex!("00010203040506070809"),
+ &hex!("00000000000000000000")
+ ));
+}
+
+/// Random tests for `constant_time_eq`.
+pub fn constant_time_eq_random_test<C: CryptoProvider>(_marker: PhantomData<C>) {
+ let mut rng = rand::thread_rng();
+ for _ in 1..100 {
+ // Test using "oracle" of ==, with possibly different lengths for a and b
+ let mut a = alloc::vec![0; rng.gen_range(1..1000)];
+ rng.fill_bytes(&mut a);
+ let mut b = alloc::vec![0; rng.gen_range(1..1000)];
+ rng.fill_bytes(&mut b);
+ assert_eq!(C::constant_time_eq(&a, &b), a == b);
+ }
+
+ for _ in 1..10000 {
+ // Test using "oracle" of ==, with same lengths for a and b
+ let len = rng.gen_range(1..1000);
+ let mut a = alloc::vec![0; len];
+ rng.fill_bytes(&mut a);
+ let mut b = alloc::vec![0; len];
+ rng.fill_bytes(&mut b);
+ assert_eq!(C::constant_time_eq(&a, &b), a == b);
+ }
+
+ for _ in 1..10000 {
+ // Clones and the original should always be equal
+ let mut a = alloc::vec![0; rng.gen_range(1..1000)];
+ rng.fill_bytes(&mut a);
+ assert!(C::constant_time_eq(&a, &a.clone()));
+ }
+}
+
+/// Generates the test cases to validate the P256 implementation.
+/// For example, to test `MyCryptoProvider`:
+///
+/// ```
+/// use crypto_provider::p256::testing::*;
+///
+/// mod tests {
+/// #[apply(constant_time_eq_test_cases)]
+/// fn constant_time_eq_tests(
+/// testcase: CryptoProviderTestCase<MyCryptoProvider>) {
+/// testcase(PhantomData);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::constant_time_eq_test_not_equal(constant_time_eq_test_not_equal)]
+#[case::constant_time_eq_test_equal(constant_time_eq_test_equal)]
+#[case::constant_time_eq_random_test(constant_time_eq_random_test)]
+fn constant_time_eq_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
diff --git a/nearby/crypto/crypto_provider_test/src/p256.rs b/nearby/crypto/crypto_provider_test/src/p256.rs
new file mode 100644
index 0000000..6c5f395
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/p256.rs
@@ -0,0 +1,239 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+extern crate std;
+use crate::elliptic_curve::EphemeralSecretForTesting;
+pub use crate::prelude::*;
+use crate::TestError;
+use core::marker::PhantomData;
+use crypto_provider::p256::{P256PublicKey, P256};
+use crypto_provider::{
+ elliptic_curve::{EcdhProvider, EphemeralSecret, PublicKey},
+ CryptoRng,
+};
+use hex_literal::hex;
+use rstest_reuse::template;
+
+/// An ECDH provider that provides associated types for testing purposes. This can be mostly
+/// considered "aliases" for the otherwise long fully-qualified associated types.
+pub trait EcdhProviderForP256Test {
+ /// The ECDH Provider that is "wrapped" by this type.
+ type EcdhProvider: EcdhProvider<
+ P256,
+ PublicKey = <Self as EcdhProviderForP256Test>::PublicKey,
+ EphemeralSecret = <Self as EcdhProviderForP256Test>::EphemeralSecret,
+ SharedSecret = <Self as EcdhProviderForP256Test>::SharedSecret,
+ >;
+ /// The public key type.
+ type PublicKey: P256PublicKey;
+ /// The ephemeral secret type.
+ type EphemeralSecret: EphemeralSecretForTesting<P256, Impl = Self::EcdhProvider>;
+ /// The shared secret type.
+ type SharedSecret: Into<[u8; 32]>;
+}
+
+impl<E> EcdhProviderForP256Test for E
+where
+ E: EcdhProvider<P256>,
+ E::PublicKey: P256PublicKey,
+ E::EphemeralSecret: EphemeralSecretForTesting<P256>,
+{
+ type EcdhProvider = E;
+ type PublicKey = E::PublicKey;
+ type EphemeralSecret = E::EphemeralSecret;
+ type SharedSecret = E::SharedSecret;
+}
+
+/// Test for P256PublicKey::to_bytes
+pub fn to_bytes_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
+ let sec1_bytes = hex!(
+ "04756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09f0b6da270d2a58a06022
+ 8bbe76c6dc1643088107636deff8aa79e8002a157b92"
+ );
+ let key = E::PublicKey::from_sec1_bytes(&sec1_bytes).unwrap();
+ let sec1_bytes_compressed =
+ hex!("02756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09");
+ assert_eq!(sec1_bytes_compressed.to_vec(), key.to_bytes());
+}
+
+/// Random test for P256PublicKey::to_bytes
+pub fn to_bytes_random_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
+ for _ in 1..100 {
+ let public_key_bytes =
+ E::EphemeralSecret::generate_random(&mut <E::EphemeralSecret as EphemeralSecret<
+ P256,
+ >>::Rng::new())
+ .public_key_bytes();
+ let public_key = E::PublicKey::from_bytes(&public_key_bytes).unwrap();
+ assert_eq!(
+ E::PublicKey::from_bytes(&public_key.to_bytes()).unwrap(),
+ public_key,
+ "from_bytes should return the same key for `{public_key_bytes:?}`",
+ );
+ }
+}
+
+/// Test for P256PublicKey::from_affine_coordinates
+pub fn from_affine_coordinates_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
+ // https://www.secg.org/sec1-v2.pdf, section 2.3.3
+ let x = hex!("756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09");
+ let y = hex!("f0b6da270d2a58a060228bbe76c6dc1643088107636deff8aa79e8002a157b92");
+ let sec1 = hex!(
+ "04756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09f0b6da270d2a58a06022
+ 8bbe76c6dc1643088107636deff8aa79e8002a157b92"
+ );
+ let expected_key = E::PublicKey::from_sec1_bytes(&sec1).unwrap();
+ assert!(
+ E::PublicKey::from_affine_coordinates(&x, &y).unwrap() == expected_key,
+ "Public key does not match"
+ );
+}
+
+/// Test for P256PublicKey::from_affine_coordinates
+pub fn from_affine_coordinates_not_on_curve_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
+ // (Invalid) coordinate from wycheproof ecdh_secp256r1_ecpoint_test.json, tcId 193
+ let x = hex!("0000000000000000000000000000000000000000000000000000000000000000");
+ let y = hex!("0000000000000000000000000000000000000000000000000000000000000000");
+ let result = E::PublicKey::from_affine_coordinates(&x, &y);
+ assert!(
+ result.is_err(),
+ "Creating public key from invalid affine coordinate should fail"
+ );
+}
+
+/// Test for P256PublicKey::from_sec1_bytes
+pub fn from_sec1_bytes_not_on_curve_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
+ // (Invalid) sec1 encoding from wycheproof ecdh_secp256r1_ecpoint_test.json, tcId 193
+ let sec1 = hex!(
+ "04000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000000000000000000000000000000000"
+ );
+ let result = E::PublicKey::from_sec1_bytes(&sec1);
+ assert!(
+ result.is_err(),
+ "Creating public key from point not on curve should fail"
+ );
+}
+
+/// Test for P256PublicKey::to_affine_coordinates
+pub fn public_key_to_affine_coordinates_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
+ // https://www.secg.org/sec1-v2.pdf, section 2.3.3
+ let expected_x = hex!("756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09");
+ let expected_y = hex!("f0b6da270d2a58a060228bbe76c6dc1643088107636deff8aa79e8002a157b92");
+ let sec1 = hex!(
+ "04756c07ba5b596fa96c9099e6619dc62deac4297a8fc1d803d74dc5caa9197c09f0b6da270d2a58a06022
+ 8bbe76c6dc1643088107636deff8aa79e8002a157b92"
+ );
+ let public_key = E::PublicKey::from_sec1_bytes(&sec1).unwrap();
+ let (actual_x, actual_y) = public_key.to_affine_coordinates().unwrap();
+ assert_eq!(actual_x, expected_x);
+ assert_eq!(actual_y, expected_y);
+}
+
+/// Test for P256 Diffie-Hellman key exchange.
+pub fn p256_ecdh_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
+ // From wycheproof ecdh_secp256r1_ecpoint_test.json, tcId 1
+ // http://google3/third_party/wycheproof/testvectors/ecdh_secp256r1_ecpoint_test.json;l=22;rcl=375894991
+ // sec1 public key manually extracted from the ASN encoded test data
+ let public_key_sec1 = hex!(
+ "0462d5bd3372af75fe85a040715d0f502428e07046868b0bfdfa61d731afe44f
+ 26ac333a93a9e70a81cd5a95b5bf8d13990eb741c8c38872b4a07d275a014e30cf"
+ );
+ let private = hex!("0612465c89a023ab17855b0a6bcebfd3febb53aef84138647b5352e02c10c346");
+ let expected_shared_secret =
+ hex!("53020d908b0219328b658b525f26780e3ae12bcd952bb25a93bc0895e1714285");
+ let actual_shared_secret = p256_ecdh_test_impl::<E>(&public_key_sec1, &private).unwrap();
+ assert_eq!(actual_shared_secret.into(), expected_shared_secret);
+}
+
+fn p256_ecdh_test_impl<E: EcdhProviderForP256Test>(
+ public_key_sec1: &[u8],
+ private: &[u8; 32],
+) -> Result<E::SharedSecret, TestError> {
+ let public_key = E::PublicKey::from_sec1_bytes(public_key_sec1).map_err(TestError::new)?;
+ let ephemeral_secret = E::EphemeralSecret::from_private_components(private, &public_key)
+ .map_err(TestError::new)?;
+ ephemeral_secret
+ .diffie_hellman(&public_key)
+ .map_err(TestError::new)
+}
+
+/// Wycheproof test for P256 Diffie-Hellman.
+pub fn wycheproof_p256_test<E: EcdhProviderForP256Test>(_: PhantomData<E>) {
+ // Test cases from https://github.com/randombit/wycheproof-rs/blob/master/src/data/ecdh_secp256r1_ecpoint_test.json
+ let test_set =
+ wycheproof::ecdh::TestSet::load(wycheproof::ecdh::TestName::EcdhSecp256r1Ecpoint).unwrap();
+ for test_group in test_set.test_groups {
+ for test in test_group.tests {
+ if test.private_key.len() != 32 {
+ // Some Wycheproof test cases have private key length that are not 32 bytes, but
+ // the RustCrypto implementation doesn't support that (it always take 32 bytes
+ // from the given RNG when generating a new key).
+ continue;
+ };
+ std::println!("Testing {}", test.tc_id);
+ let result = p256_ecdh_test_impl::<E>(
+ &test.public_key,
+ &test
+ .private_key
+ .try_into()
+ .expect("Private key should be 32 bytes long"),
+ );
+ match test.result {
+ wycheproof::TestResult::Valid => {
+ let shared_secret =
+ result.unwrap_or_else(|_| panic!("Test {} should succeed", test.tc_id));
+ assert_eq!(test.shared_secret, shared_secret.into());
+ }
+ wycheproof::TestResult::Invalid => {
+ result
+ .err()
+ .unwrap_or_else(|| panic!("Test {} should fail", test.tc_id));
+ }
+ wycheproof::TestResult::Acceptable => {
+ if let Ok(shared_secret) = result {
+ assert_eq!(test.shared_secret, shared_secret.into());
+ }
+ // Test passes if `result` is an error because this test is "acceptable"
+ }
+ }
+ }
+ }
+}
+
+/// Generates the test cases to validate the P256 implementation.
+/// For example, to test `MyCryptoProvider`:
+///
+/// ```
+/// use crypto_provider::p256::testing::*;
+///
+/// mod tests {
+/// #[apply(p256_test_cases)]
+/// fn p256_tests(testcase: CryptoProviderTestCase<MyCryptoProvider> {
+/// testcase(PhantomData::<MyCryptoProvider>);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::to_bytes(to_bytes_test)]
+#[case::to_bytes_random(to_bytes_random_test)]
+#[case::from_sec1_bytes_not_on_curve(from_sec1_bytes_not_on_curve_test)]
+#[case::from_affine_coordinates(from_affine_coordinates_test)]
+#[case::from_affine_coordinates_not_on_curve(from_affine_coordinates_not_on_curve_test)]
+#[case::public_key_to_affine_coordinates(public_key_to_affine_coordinates_test)]
+#[case::p256_ecdh(p256_ecdh_test)]
+#[case::wycheproof_p256(wycheproof_p256_test)]
+fn p256_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
diff --git a/nearby/crypto/crypto_provider_test/src/sha2.rs b/nearby/crypto/crypto_provider_test/src/sha2.rs
new file mode 100644
index 0000000..330f284
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/sha2.rs
@@ -0,0 +1,119 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+extern crate alloc;
+extern crate std;
+pub use crate::prelude::*;
+use crate::CryptoProvider;
+use alloc::vec::Vec;
+use core::{marker::PhantomData, str::FromStr};
+use crypto_provider::sha2::{Sha256, Sha512};
+use hex::FromHex;
+pub use hex_literal::hex;
+use rstest_reuse::template;
+
+/// Test vectors from SHA256ShortMsg.rsp in
+/// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
+pub fn sha256_cavp_short_vector_test<C: CryptoProvider>(_marker: PhantomData<C>) {
+ sha256_cavp_vector_test::<C>(include_str!("testdata/SHA256ShortMsg.rsp"));
+}
+
+/// Test vectors from SHA256LongMsg.rsp in
+/// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
+pub fn sha256_cavp_long_vector_test<C: CryptoProvider>(_marker: PhantomData<C>) {
+ sha256_cavp_vector_test::<C>(include_str!("testdata/SHA256LongMsg.rsp"));
+}
+
+/// Test vectors from SHA512ShortMsg.rsp in
+/// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
+pub fn sha512_cavp_short_vector_test<C: CryptoProvider>(_marker: PhantomData<C>) {
+ sha512_cavp_vector_test::<C>(include_str!("testdata/SHA512ShortMsg.rsp"));
+}
+
+/// Test vectors from SHA512LongMsg.rsp in
+/// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
+pub fn sha512_cavp_long_vector_test<C: CryptoProvider>(_marker: PhantomData<C>) {
+ sha512_cavp_vector_test::<C>(include_str!("testdata/SHA512LongMsg.rsp"));
+}
+
+/// Test vectors an rsp file in
+/// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
+fn sha256_cavp_vector_test<C: CryptoProvider>(cavp_file_contents: &str) {
+ sha_cavp_vector_test(<C::Sha256 as Sha256>::sha256, cavp_file_contents)
+}
+
+/// Test vectors an rsp file in
+/// <https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs>
+fn sha512_cavp_vector_test<C: CryptoProvider>(cavp_file_contents: &str) {
+ sha_cavp_vector_test(<C::Sha512 as Sha512>::sha512, cavp_file_contents)
+}
+
+fn sha_cavp_vector_test<const N: usize>(
+ hash_func: impl Fn(&[u8]) -> [u8; N],
+ cavp_file_contents: &str,
+) {
+ let test_cases = cavp_file_contents.split("\n\n").filter_map(|chunk| {
+ let mut len: Option<usize> = None;
+ let mut msg: Option<Vec<u8>> = None;
+ let mut md: Option<Vec<u8>> = None;
+ for line in chunk.split('\n') {
+ if line.starts_with('#') || line.is_empty() || line == std::format!("[L = {N}]") {
+ continue;
+ } else if let Some(len_str) = line.strip_prefix("Len = ") {
+ len = Some(FromStr::from_str(len_str).unwrap());
+ } else if let Some(hex_str) = line.strip_prefix("Msg = ") {
+ msg = Some(Vec::<u8>::from_hex(hex_str).unwrap());
+ } else if let Some(hex_str) = line.strip_prefix("MD = ") {
+ md = Some(Vec::<u8>::from_hex(hex_str).unwrap());
+ } else {
+ panic!("Unexpected line in test file: `{}`", line);
+ }
+ }
+ if let (Some(len), Some(msg), Some(md)) = (len, msg, md) {
+ Some((len, msg, md))
+ } else {
+ None
+ }
+ });
+ for (len, mut msg, md) in test_cases {
+ if len == 0 {
+ // Truncate len = 0, since the test file has "Msg = 00" in there that should be
+ // ignored.
+ msg.truncate(0);
+ }
+ assert_eq!(msg.len(), len / 8);
+ let md_arr: [u8; N] = md.try_into().unwrap();
+ assert_eq!(hash_func(&msg), md_arr);
+ }
+}
+
+/// Generates the test cases to validate the SHA2 implementation.
+/// For example, to test `MyCryptoProvider`:
+///
+/// ```
+/// use crypto_provider::sha2::testing::*;
+///
+/// mod tests {
+/// #[apply(sha2_test_cases)]
+/// fn sha2_tests(testcase: CryptoProviderTestCase<MyCryptoProvider>) {
+/// testcase(PhantomData::<MyCryptoProvider>);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::sha256_cavp_short_vector(sha256_cavp_short_vector_test)]
+#[case::sha256_cavp_long_vector(sha256_cavp_long_vector_test)]
+fn sha2_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
diff --git a/nearby/crypto/crypto_provider/src/testdata/README.md b/nearby/crypto/crypto_provider_test/src/testdata/README.md
similarity index 100%
rename from nearby/crypto/crypto_provider/src/testdata/README.md
rename to nearby/crypto/crypto_provider_test/src/testdata/README.md
diff --git a/nearby/crypto/crypto_provider/src/testdata/SHA256LongMsg.rsp b/nearby/crypto/crypto_provider_test/src/testdata/SHA256LongMsg.rsp
similarity index 100%
rename from nearby/crypto/crypto_provider/src/testdata/SHA256LongMsg.rsp
rename to nearby/crypto/crypto_provider_test/src/testdata/SHA256LongMsg.rsp
diff --git a/nearby/crypto/crypto_provider/src/testdata/SHA256ShortMsg.rsp b/nearby/crypto/crypto_provider_test/src/testdata/SHA256ShortMsg.rsp
similarity index 100%
rename from nearby/crypto/crypto_provider/src/testdata/SHA256ShortMsg.rsp
rename to nearby/crypto/crypto_provider_test/src/testdata/SHA256ShortMsg.rsp
diff --git a/nearby/crypto/crypto_provider/src/testdata/SHA512LongMsg.rsp b/nearby/crypto/crypto_provider_test/src/testdata/SHA512LongMsg.rsp
similarity index 100%
rename from nearby/crypto/crypto_provider/src/testdata/SHA512LongMsg.rsp
rename to nearby/crypto/crypto_provider_test/src/testdata/SHA512LongMsg.rsp
diff --git a/nearby/crypto/crypto_provider/src/testdata/SHA512ShortMsg.rsp b/nearby/crypto/crypto_provider_test/src/testdata/SHA512ShortMsg.rsp
similarity index 100%
rename from nearby/crypto/crypto_provider/src/testdata/SHA512ShortMsg.rsp
rename to nearby/crypto/crypto_provider_test/src/testdata/SHA512ShortMsg.rsp
diff --git a/nearby/crypto/crypto_provider/src/testdata/ecdsa/rfc_test_vectors.txt b/nearby/crypto/crypto_provider_test/src/testdata/ecdsa/rfc_test_vectors.txt
similarity index 100%
rename from nearby/crypto/crypto_provider/src/testdata/ecdsa/rfc_test_vectors.txt
rename to nearby/crypto/crypto_provider_test/src/testdata/ecdsa/rfc_test_vectors.txt
diff --git a/nearby/crypto/crypto_provider_test/src/x25519.rs b/nearby/crypto/crypto_provider_test/src/x25519.rs
new file mode 100644
index 0000000..23f8f9b
--- /dev/null
+++ b/nearby/crypto/crypto_provider_test/src/x25519.rs
@@ -0,0 +1,161 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use crate::elliptic_curve::EphemeralSecretForTesting;
+pub use crate::prelude::*;
+use crate::TestError;
+use core::marker::PhantomData;
+use crypto_provider::x25519::X25519;
+use crypto_provider::{
+ elliptic_curve::{EcdhProvider, EphemeralSecret, PublicKey},
+ CryptoRng,
+};
+use hex_literal::hex;
+use rstest_reuse::template;
+
+/// An ECDH provider that provides associated types for testing purposes. This can be mostly
+/// considered "aliases" for the otherwise long fully-qualified associated types.
+pub trait EcdhProviderForX25519Test {
+ /// The ECDH Provider that is "wrapped" by this type.
+ type EcdhProvider: EcdhProvider<
+ X25519,
+ PublicKey = <Self as EcdhProviderForX25519Test>::PublicKey,
+ EphemeralSecret = <Self as EcdhProviderForX25519Test>::EphemeralSecret,
+ SharedSecret = <Self as EcdhProviderForX25519Test>::SharedSecret,
+ >;
+ /// The public key type.
+ type PublicKey: PublicKey<X25519>;
+ /// The ephemeral secret type.
+ type EphemeralSecret: EphemeralSecretForTesting<X25519, Impl = Self::EcdhProvider>;
+ /// The shared secret type.
+ type SharedSecret: Into<[u8; 32]>;
+}
+
+impl<E> EcdhProviderForX25519Test for E
+where
+ E: EcdhProvider<X25519>,
+ E::PublicKey: PublicKey<X25519>,
+ E::EphemeralSecret: EphemeralSecretForTesting<X25519>,
+{
+ type EcdhProvider = E;
+ type PublicKey = E::PublicKey;
+ type EphemeralSecret = E::EphemeralSecret;
+ type SharedSecret = E::SharedSecret;
+}
+
+/// Test for `PublicKey<X25519>::to_bytes`
+pub fn x25519_to_bytes_test<E: EcdhProviderForX25519Test>(_: PhantomData<E>) {
+ let public_key_bytes = hex!("504a36999f489cd2fdbc08baff3d88fa00569ba986cba22548ffde80f9806829");
+ let public_key = E::PublicKey::from_bytes(&public_key_bytes).unwrap();
+ assert_eq!(public_key_bytes.to_vec(), public_key.to_bytes());
+}
+
+/// Random test for `PublicKey<X25519>::to_bytes`
+pub fn x25519_to_bytes_random_test<E: EcdhProviderForX25519Test>(_: PhantomData<E>) {
+ for _ in 1..100 {
+ let public_key_bytes =
+ E::EphemeralSecret::generate_random(&mut <E::EphemeralSecret as EphemeralSecret<
+ X25519,
+ >>::Rng::new())
+ .public_key_bytes();
+ let public_key = E::PublicKey::from_bytes(&public_key_bytes).unwrap();
+ assert_eq!(
+ E::PublicKey::from_bytes(&public_key.to_bytes()).unwrap(),
+ public_key,
+ "from_bytes should return the same key for `{public_key_bytes:?}`",
+ );
+ }
+}
+
+/// Test for X25519 Diffie-Hellman key exchange.
+pub fn x25519_ecdh_test<E: EcdhProviderForX25519Test>(_: PhantomData<E>) {
+ // From wycheproof ecdh_secx25519r1_ecpoint_test.json, tcId 1
+ // http://google3/third_party/wycheproof/testvectors/ecdh_secx25519r1_ecpoint_test.json;l=22;rcl=375894991
+ // sec1 public key manually extracted from the ASN encoded test data
+ let public_key = hex!("504a36999f489cd2fdbc08baff3d88fa00569ba986cba22548ffde80f9806829");
+ let private = hex!("c8a9d5a91091ad851c668b0736c1c9a02936c0d3ad62670858088047ba057475");
+ let expected_shared_secret =
+ hex!("436a2c040cf45fea9b29a0cb81b1f41458f863d0d61b453d0a982720d6d61320");
+ let result = x25519_ecdh_test_impl::<E>(&public_key, &private).unwrap();
+ assert_eq!(expected_shared_secret, result.into());
+}
+
+fn x25519_ecdh_test_impl<E: EcdhProviderForX25519Test>(
+ public_key: &[u8],
+ private: &[u8; 32],
+) -> Result<E::SharedSecret, TestError> {
+ let public_key = E::PublicKey::from_bytes(public_key).map_err(TestError::new)?;
+ let ephemeral_secret = E::EphemeralSecret::from_private_components(private, &public_key)
+ .map_err(TestError::new)?;
+ ephemeral_secret
+ .diffie_hellman(&public_key)
+ .map_err(TestError::new)
+}
+
+/// Wycheproof test for X25519 Diffie-Hellman.
+pub fn wycheproof_x25519_test<E: EcdhProviderForX25519Test>(_: PhantomData<E>) {
+ // Test cases from https://github.com/randombit/wycheproof-rs/blob/master/src/data/x25519_test.json
+ let test_set = wycheproof::xdh::TestSet::load(wycheproof::xdh::TestName::X25519).unwrap();
+ for test_group in test_set.test_groups {
+ for test in test_group.tests {
+ let result = x25519_ecdh_test_impl::<E>(
+ &test.public_key,
+ &test
+ .private_key
+ .try_into()
+ .expect("Private keys should be 32 bytes long"),
+ );
+ match test.result {
+ wycheproof::TestResult::Valid => {
+ let shared_secret =
+ result.unwrap_or_else(|_| panic!("Test {} should succeed", test.tc_id));
+ assert_eq!(&test.shared_secret, &shared_secret.into());
+ }
+ wycheproof::TestResult::Invalid => {
+ result
+ .err()
+ .unwrap_or_else(|| panic!("Test {} should fail", test.tc_id));
+ }
+ wycheproof::TestResult::Acceptable => {
+ if let Ok(shared_secret) = result {
+ assert_eq!(test.shared_secret, shared_secret.into());
+ }
+ // Test passes if `result` is an error because this test is "acceptable"
+ }
+ }
+ }
+ }
+}
+
+/// Generates the test cases to validate the x25519 implementation.
+/// For example, to test `MyCryptoProvider`:
+///
+/// ```
+/// use crypto_provider::x25519::testing::*;
+///
+/// mod tests {
+/// #[apply(x25519_test_cases)]
+/// fn x25519_tests(testcase: CryptoProviderTestCase<MyCryptoProvider>) {
+/// testcase(PhantomData::<MyCryptoProvider>);
+/// }
+/// }
+/// ```
+#[template]
+#[export]
+#[rstest]
+#[case::x25519_to_bytes(x25519_to_bytes_test)]
+#[case::x25519_to_bytes_random(x25519_to_bytes_random_test)]
+#[case::x25519_ecdh(x25519_ecdh_test)]
+#[case::wycheproof_x25519(wycheproof_x25519_test)]
+fn x25519_test_cases<C: CryptoProvider>(#[case] testcase: CryptoProviderTestCase<C>) {}
diff --git a/nearby/presence/array_view/src/lib.rs b/nearby/presence/array_view/src/lib.rs
index 7a579a6..24a5001 100644
--- a/nearby/presence/array_view/src/lib.rs
+++ b/nearby/presence/array_view/src/lib.rs
@@ -42,6 +42,16 @@
}
impl<T, const N: usize> ArrayView<T, N> {
+ /// A version of [`ArrayView#try_from_array`] which panics if `len > buffer.len()`,
+ /// suitable for usage in `const` contexts.
+ pub const fn const_from_array(array: [T; N], len: usize) -> ArrayView<T, N> {
+ if N < len {
+ panic!("Invalid const ArrayView");
+ } else {
+ ArrayView { array, len }
+ }
+ }
+
/// Create an [ArrayView] of the first `len` elements of `buffer`.
///
/// Returns `None` if `len > buffer.len()`.
diff --git a/nearby/presence/ldt/fuzz/Cargo.lock b/nearby/presence/ldt/fuzz/Cargo.lock
index e0b529d..285bbca 100644
--- a/nearby/presence/ldt/fuzz/Cargo.lock
+++ b/nearby/presence/ldt/fuzz/Cargo.lock
@@ -207,9 +207,9 @@
[[package]]
name = "der"
-version = "0.7.4"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b14af2045fa69ed2b7a48934bebb842d0f33e73e96e78766ecb14bb5347a11"
+checksum = "bc906908ea6458456e5eaa160a9c08543ec3d1e6f71e2235cedd660cb65f9df0"
dependencies = [
"const-oid",
"zeroize",
@@ -260,9 +260,9 @@
[[package]]
name = "elliptic-curve"
-version = "0.13.4"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7"
+checksum = "6ea5a92946e8614bb585254898bb7dd1ddad241ace60c52149e3765e34cc039d"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -295,9 +295,9 @@
[[package]]
name = "generic-array"
-version = "0.14.7"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
@@ -426,9 +426,9 @@
[[package]]
name = "p256"
-version = "0.13.2"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+checksum = "7270da3e5caa82afd3deb054cc237905853813aea3859544bc082c3fe55b8d47"
dependencies = [
"elliptic-curve",
"primeorder",
@@ -470,9 +470,9 @@
[[package]]
name = "primeorder"
-version = "0.13.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf8d3875361e28f7753baefef104386e7aa47642c93023356d97fdef4003bfb5"
+checksum = "7613fdcc0831c10060fa69833ea8fa2caa94b6456f51e25356a885b530a2e3d0"
dependencies = [
"elliptic-curve",
]
@@ -525,9 +525,9 @@
[[package]]
name = "sec1"
-version = "0.7.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
+checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e"
dependencies = [
"base16ct",
"der",
diff --git a/nearby/presence/ldt_np_adv/fuzz/Cargo.lock b/nearby/presence/ldt_np_adv/fuzz/Cargo.lock
index 31409c8..92f2deb 100644
--- a/nearby/presence/ldt_np_adv/fuzz/Cargo.lock
+++ b/nearby/presence/ldt_np_adv/fuzz/Cargo.lock
@@ -211,9 +211,9 @@
[[package]]
name = "der"
-version = "0.7.4"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b14af2045fa69ed2b7a48934bebb842d0f33e73e96e78766ecb14bb5347a11"
+checksum = "bc906908ea6458456e5eaa160a9c08543ec3d1e6f71e2235cedd660cb65f9df0"
dependencies = [
"const-oid",
"zeroize",
@@ -264,9 +264,9 @@
[[package]]
name = "elliptic-curve"
-version = "0.13.4"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7"
+checksum = "6ea5a92946e8614bb585254898bb7dd1ddad241ace60c52149e3765e34cc039d"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -299,9 +299,9 @@
[[package]]
name = "generic-array"
-version = "0.14.7"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
@@ -453,9 +453,9 @@
[[package]]
name = "p256"
-version = "0.13.2"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+checksum = "7270da3e5caa82afd3deb054cc237905853813aea3859544bc082c3fe55b8d47"
dependencies = [
"elliptic-curve",
"primeorder",
@@ -497,9 +497,9 @@
[[package]]
name = "primeorder"
-version = "0.13.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf8d3875361e28f7753baefef104386e7aa47642c93023356d97fdef4003bfb5"
+checksum = "7613fdcc0831c10060fa69833ea8fa2caa94b6456f51e25356a885b530a2e3d0"
dependencies = [
"elliptic-curve",
]
@@ -552,9 +552,9 @@
[[package]]
name = "sec1"
-version = "0.7.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
+checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e"
dependencies = [
"base16ct",
"der",
diff --git a/nearby/presence/ldt_np_adv_ffi/Cargo.lock b/nearby/presence/ldt_np_adv_ffi/Cargo.lock
index 12f0615..0ad9a64 100644
--- a/nearby/presence/ldt_np_adv_ffi/Cargo.lock
+++ b/nearby/presence/ldt_np_adv_ffi/Cargo.lock
@@ -305,9 +305,9 @@
[[package]]
name = "elliptic-curve"
-version = "0.13.4"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7"
+checksum = "6ea5a92946e8614bb585254898bb7dd1ddad241ace60c52149e3765e34cc039d"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -581,9 +581,9 @@
[[package]]
name = "p256"
-version = "0.13.2"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+checksum = "7270da3e5caa82afd3deb054cc237905853813aea3859544bc082c3fe55b8d47"
dependencies = [
"elliptic-curve",
"primeorder",
@@ -647,9 +647,9 @@
[[package]]
name = "primeorder"
-version = "0.13.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf8d3875361e28f7753baefef104386e7aa47642c93023356d97fdef4003bfb5"
+checksum = "7613fdcc0831c10060fa69833ea8fa2caa94b6456f51e25356a885b530a2e3d0"
dependencies = [
"elliptic-curve",
]
@@ -734,9 +734,9 @@
[[package]]
name = "sec1"
-version = "0.7.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
+checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e"
dependencies = [
"base16ct",
"der",
diff --git a/nearby/presence/ldt_np_adv_ffi/src/lib.rs b/nearby/presence/ldt_np_adv_ffi/src/lib.rs
index 7b440e4..b4dd932 100644
--- a/nearby/presence/ldt_np_adv_ffi/src/lib.rs
+++ b/nearby/presence/ldt_np_adv_ffi/src/lib.rs
@@ -22,15 +22,11 @@
)]
// These features are needed to support no_std + alloc
#![feature(lang_items)]
-#![feature(alloc_error_handler)]
//! Rust ffi wrapper of ldt_np_adv, can be called from C/C++ Clients
-mod handle_map;
-
extern crate alloc;
-use crate::handle_map::get_dec_handle_map;
use alloc::boxed::Box;
use core::slice;
use handle_map::get_enc_handle_map;
@@ -40,6 +36,10 @@
};
use np_hkdf::NpKeySeedHkdf;
+use crate::handle_map::get_dec_handle_map;
+
+mod handle_map;
+
// Pull in the needed deps for std vs no_std
cfg_if::cfg_if! {
// Test pulls in std which causes duplicate errors
diff --git a/nearby/presence/ldt_np_adv_ffi/src/no_std.rs b/nearby/presence/ldt_np_adv_ffi/src/no_std.rs
index 34a16ef..524bc3d 100644
--- a/nearby/presence/ldt_np_adv_ffi/src/no_std.rs
+++ b/nearby/presence/ldt_np_adv_ffi/src/no_std.rs
@@ -14,18 +14,12 @@
//
// mod to handle all of the impls needed for no_std
-use libc_alloc::LibcAlloc;
-
extern crate panic_abort;
+use libc_alloc::LibcAlloc;
+
#[global_allocator]
static ALLOCATOR: LibcAlloc = LibcAlloc;
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}
-
-#[alloc_error_handler]
-#[allow(clippy::panic)]
-fn default_handler(layout: core::alloc::Layout) -> ! {
- panic!("memory allocation of {} bytes failed", layout.size())
-}
diff --git a/nearby/presence/ldt_np_c_sample/tests/np_ffi_tests.cc b/nearby/presence/ldt_np_c_sample/tests/np_ffi_tests.cc
index 1cc2ae2..6359e7e 100644
--- a/nearby/presence/ldt_np_c_sample/tests/np_ffi_tests.cc
+++ b/nearby/presence/ldt_np_c_sample/tests/np_ffi_tests.cc
@@ -14,13 +14,13 @@
#include <gtest/gtest.h>
#include <json/json.h>
-#include <fstream>
extern "C" {
#include "np_ldt.h"
}
#include <algorithm>
+#include <fstream>
// TODO: get multi threaded tests working on windows
#ifndef _WIN32
diff --git a/nearby/presence/xts_aes/fuzz/Cargo.lock b/nearby/presence/xts_aes/fuzz/Cargo.lock
index 06b5f86..2bdaef3 100644
--- a/nearby/presence/xts_aes/fuzz/Cargo.lock
+++ b/nearby/presence/xts_aes/fuzz/Cargo.lock
@@ -207,9 +207,9 @@
[[package]]
name = "der"
-version = "0.7.4"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b14af2045fa69ed2b7a48934bebb842d0f33e73e96e78766ecb14bb5347a11"
+checksum = "bc906908ea6458456e5eaa160a9c08543ec3d1e6f71e2235cedd660cb65f9df0"
dependencies = [
"const-oid",
"zeroize",
@@ -260,9 +260,9 @@
[[package]]
name = "elliptic-curve"
-version = "0.13.4"
+version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7"
+checksum = "6ea5a92946e8614bb585254898bb7dd1ddad241ace60c52149e3765e34cc039d"
dependencies = [
"base16ct",
"crypto-bigint",
@@ -295,9 +295,9 @@
[[package]]
name = "generic-array"
-version = "0.14.7"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
@@ -407,9 +407,9 @@
[[package]]
name = "p256"
-version = "0.13.2"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+checksum = "7270da3e5caa82afd3deb054cc237905853813aea3859544bc082c3fe55b8d47"
dependencies = [
"elliptic-curve",
"primeorder",
@@ -451,9 +451,9 @@
[[package]]
name = "primeorder"
-version = "0.13.1"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf8d3875361e28f7753baefef104386e7aa47642c93023356d97fdef4003bfb5"
+checksum = "7613fdcc0831c10060fa69833ea8fa2caa94b6456f51e25356a885b530a2e3d0"
dependencies = [
"elliptic-curve",
]
@@ -506,9 +506,9 @@
[[package]]
name = "sec1"
-version = "0.7.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
+checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e"
dependencies = [
"base16ct",
"der",
diff --git a/nearby/scripts/build-script.sh b/nearby/scripts/build-script.sh
index 3643482..5fc999e 100755
--- a/nearby/scripts/build-script.sh
+++ b/nearby/scripts/build-script.sh
@@ -22,7 +22,9 @@
# Use to generate headers for new source code files
gen_headers() {
set -e
- $HOME/go/bin/addlicense -c "Google LLC" -l apache -ignore=**/android/build/** -ignore=target/** -ignore=**/target/** -ignore=".idea/*" -ignore=**/cmake-build/** -ignore="**/java/build/**" .
+ $HOME/go/bin/addlicense -c "Google LLC" -l apache -ignore=**/android/build/** -ignore=target/** \
+ -ignore=**/target/** -ignore=".idea/*" -ignore=**/cmake-build/** -ignore="**/java/build/**" \
+ -ignore="**/ukey2_c_ffi/cpp/build/**" .
}
# Checks the workspace 3rd party crates and makes sure they have a valid license
@@ -40,6 +42,7 @@
check_workspace
check_boringssl
check_ldt_ffi
+ check_ukey2_ffi
build_fuzzers
}
@@ -88,6 +91,7 @@
-ignore="**/cmake-build/**" \
-ignore="**/java/build/**" \
-ignore="**/java/*/build/**" \
+ -ignore="**/ukey2_c_ffi/cpp/build/**" \
.; then
echo "License header check succeeded!"
else
@@ -169,6 +173,30 @@
cd ../
}
+# Builds and runs tests for the UKEY2 FFI
+check_ukey2_ffi() {
+ set -e
+ cd $SCRIPT_DIR/..
+ cd connections/ukey2/ukey2_c_ffi
+ # Default build, RustCrypto
+ cargo build --release --lib
+ # Try to build with OpenSSL
+ cargo build --no-default-features --features=openssl
+ cargo doc --no-deps
+ cargo clippy --release
+ cargo clippy --no-default-features --features=openssl
+ cargo deny check
+
+ # build C/C++ samples, tests, and benches
+ cd cpp
+ mkdir -p build && cd build
+ cmake ..
+ make all
+ ctest
+
+ cd $SCRIPT_DIR/..
+}
+
# Clones boringssl and uses bindgen to generate the rust crate, applies AOSP
# specific patches to the 3p `openssl` crate so that it can use a bssl backend
prepare_boringssl() {
@@ -181,11 +209,12 @@
git clone https://boringssl.googlesource.com/boringssl
fi
# Snap to the AOSP commit of boringssl
- boringssl_rev=$(curl https://android.googlesource.com/platform/external/boringssl/+/master/BORINGSSL_REVISION?format=text | base64 -d)
+ boringssl_rev=$(curl https://android.googlesource.com/platform/external/boringssl/+/master/BORINGSSL_REVISION?format=text | base64 -d)
cd boringssl && git checkout $boringssl_rev && mkdir -p build && cd build
target=$(rustc -vV | awk '/host/ { print $2 }')
cmake -G Ninja .. -DRUST_BINDINGS="$target" && ninja
- # A valid Rust crate is built under `boringssl-build/boringssl/build/rust/bssl-sys`
+ # The Rust crate is in `boringssl-build/boringssl/build/rust/bssl-sys`, which depends on a
+ # cmake-generated file as part of its source.
cd $projectroot/boringssl-build
rm -Rf rust-openssl
diff --git a/nearby/scripts/openssl-patches/0001-Apply-Android-changes.patch b/nearby/scripts/openssl-patches/0001-Apply-Android-changes.patch
index aca9408..be6ca09 100644
--- a/nearby/scripts/openssl-patches/0001-Apply-Android-changes.patch
+++ b/nearby/scripts/openssl-patches/0001-Apply-Android-changes.patch
@@ -1,35 +1,72 @@
-From b89f5e640f0d4d9cb87412d897797ce89e12d15b Mon Sep 17 00:00:00 2001
+From 66e1daa9b4a345617bf9a090d56fa09ccd9b1d35 Mon Sep 17 00:00:00 2001
From: Maurice Lam <yukl@google.com>
-Date: Thu, 2 Feb 2023 19:16:31 +0000
-Subject: [PATCH 1/3] Apply Android changes
+Date: Wed, 26 Apr 2023 02:21:36 +0000
+Subject: [PATCH] Apply Android patches
---
- .cargo/config.toml | 2 +
+ openssl/src/bio.rs | 6 +-
+ openssl/src/bn.rs | 2 +-
openssl/src/cipher.rs | 4 +
+ openssl/src/dh.rs | 2 +-
openssl/src/ec.rs | 20 +
openssl/src/encrypt.rs | 4 +-
openssl/src/hkdf.rs | 89 ++
- openssl/src/hmac.rs | 68 ++
- openssl/src/lib.rs | 7 +
+ openssl/src/hmac.rs | 217 ++++
+ openssl/src/lib.rs | 12 +
openssl/src/pkey.rs | 20 +-
openssl/src/sign.rs | 10 +-
openssl/src/symm.rs | 7 +-
- openssl/src/x509/mod.rs | 36 +
- openssl/src/x509/mod.rs.orig | 1843 ++++++++++++++++++++++++++++++++++
- 12 files changed, 2091 insertions(+), 19 deletions(-)
- create mode 100644 .cargo/config.toml
+ openssl/src/x509/mod.rs | 52 +-
+ openssl/src/x509/mod.rs.orig | 1879 ++++++++++++++++++++++++++++++++++
+ 14 files changed, 2292 insertions(+), 32 deletions(-)
create mode 100644 openssl/src/hkdf.rs
create mode 100644 openssl/src/hmac.rs
create mode 100644 openssl/src/x509/mod.rs.orig
-diff --git a/.cargo/config.toml b/.cargo/config.toml
-new file mode 100644
-index 00000000..f92f06a0
---- /dev/null
-+++ b/.cargo/config.toml
-@@ -0,0 +1,2 @@
-+[patch.crates-io]
-+bssl-sys = { path = "../boringssl/build/rust" }
+diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs
+index 6a72552a..03242188 100644
+--- a/openssl/src/bio.rs
++++ b/openssl/src/bio.rs
+@@ -4,7 +4,7 @@ use std::marker::PhantomData;
+ use std::ptr;
+ use std::slice;
+
+-use crate::cvt_p;
++use crate::{cvt_p, SignedLenType};
+ use crate::error::ErrorStack;
+
+ pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>);
+@@ -25,7 +25,7 @@ impl<'a> MemBioSlice<'a> {
+ let bio = unsafe {
+ cvt_p(BIO_new_mem_buf(
+ buf.as_ptr() as *const _,
+- buf.len() as c_int,
++ buf.len() as SignedLenType,
+ ))?
+ };
+
+@@ -78,7 +78,7 @@ cfg_if! {
+ use ffi::BIO_new_mem_buf;
+ } else {
+ #[allow(bad_style)]
+- unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: ::libc::c_int) -> *mut ffi::BIO {
++ unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: SignedLenType) -> *mut ffi::BIO {
+ ffi::BIO_new_mem_buf(buf as *mut _, len)
+ }
+ }
+diff --git a/openssl/src/bn.rs b/openssl/src/bn.rs
+index 0328730a..fe820a2c 100644
+--- a/openssl/src/bn.rs
++++ b/openssl/src/bn.rs
+@@ -814,7 +814,7 @@ impl BigNumRef {
+ /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]);
+ /// ```
+ #[corresponds(BN_bn2binpad)]
+- #[cfg(ossl110)]
++ #[cfg(any(boringssl, ossl110))]
+ pub fn to_vec_padded(&self, pad_to: i32) -> Result<Vec<u8>, ErrorStack> {
+ let mut v = Vec::with_capacity(pad_to as usize);
+ unsafe {
diff --git a/openssl/src/cipher.rs b/openssl/src/cipher.rs
index aeedf459..570794ca 100644
--- a/openssl/src/cipher.rs
@@ -64,6 +101,19 @@
pub fn bf_ecb() -> &'static CipherRef {
unsafe { CipherRef::from_ptr(ffi::EVP_bf_ecb() as *mut _) }
}
+diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs
+index 12170b99..e781543e 100644
+--- a/openssl/src/dh.rs
++++ b/openssl/src/dh.rs
+@@ -239,7 +239,7 @@ where
+ }
+
+ cfg_if! {
+- if #[cfg(any(ossl110, libressl270))] {
++ if #[cfg(any(ossl110, libressl270, boringssl))] {
+ use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key};
+ } else {
+ #[allow(bad_style)]
diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs
index 248ced3e..c56f5da7 100644
--- a/openssl/src/ec.rs
@@ -214,17 +264,19 @@
+}
diff --git a/openssl/src/hmac.rs b/openssl/src/hmac.rs
new file mode 100644
-index 00000000..601ae01b
+index 00000000..465781e2
--- /dev/null
+++ b/openssl/src/hmac.rs
-@@ -0,0 +1,68 @@
-+use crate::cvt_p;
+@@ -0,0 +1,217 @@
+use crate::error::ErrorStack;
+use crate::md::MdRef;
++use crate::{cvt, cvt_p};
++use ffi::HMAC_CTX;
+use foreign_types::ForeignTypeRef;
++use libc::{c_uint, c_void};
+use openssl_macros::corresponds;
-+use libc::{c_void, c_uint};
+use std::convert::TryFrom;
++use std::ptr;
+
+/// Computes the HMAC as a one-shot operation.
+///
@@ -240,8 +292,9 @@
+ md: &MdRef,
+ key: &[u8],
+ data: &[u8],
-+ out: &'a mut [u8]
++ out: &'a mut [u8],
+) -> Result<&'a [u8], ErrorStack> {
++ assert!(out.len() >= md.size());
+ let mut out_len = c_uint::try_from(out.len()).unwrap();
+ unsafe {
+ cvt_p(ffi::HMAC(
@@ -251,43 +304,189 @@
+ data.as_ptr(),
+ data.len(),
+ out.as_mut_ptr(),
-+ &mut out_len
-+ ))?;
++ &mut out_len,
++ ))?;
+ }
+ Ok(&out[..out_len as usize])
+}
+
++/// A context object used to perform HMAC operations.
++///
++/// HMAC is a MAC (message authentication code), i.e. a keyed hash function used for message
++/// authentication, which is based on a hash function.
++///
++/// Note: Only available in boringssl. For openssl, use `PKey::hmac` instead.
++#[cfg(boringssl)]
++pub struct HmacCtx {
++ ctx: *mut HMAC_CTX,
++ output_size: usize,
++}
++
++#[cfg(boringssl)]
++impl HmacCtx {
++ /// Creates a new [HmacCtx] to use the hash function `md` and key `key`.
++ #[corresponds(HMAC_Init_ex)]
++ pub fn new(key: &[u8], md: &MdRef) -> Result<Self, ErrorStack> {
++ unsafe {
++ // Safety: If an error occurred, the resulting null from HMAC_CTX_new is converted into
++ // ErrorStack in the returned result by `cvt_p`.
++ let ctx = cvt_p(ffi::HMAC_CTX_new())?;
++ // Safety:
++ // - HMAC_Init_ex must be called with a context previously created with HMAC_CTX_new,
++ // which is the line above.
++ // - HMAC_Init_ex may return an error if key is null but the md is different from
++ // before. This is avoided here since key is guaranteed to be non-null.
++ cvt(ffi::HMAC_Init_ex(
++ ctx,
++ key.as_ptr() as *const c_void,
++ key.len(),
++ md.as_ptr(),
++ ptr::null_mut(),
++ ))?;
++ Ok(Self {
++ ctx,
++ output_size: md.size(),
++ })
++ }
++ }
++
++ /// `update` can be called repeatedly with chunks of the message `data` to be authenticated.
++ #[corresponds(HMAC_Update)]
++ pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
++ unsafe {
++ // Safety: HMAC_Update returns 0 on error, and that is converted into ErrorStack in the
++ // returned result by `cvt`.
++ cvt(ffi::HMAC_Update(self.ctx, data.as_ptr(), data.len())).map(|_| ())
++ }
++ }
++
++ /// Finishes the HMAC process, and places the message authentication code in `output`.
++ /// The number of bytes written to `output` is returned.
++ ///
++ /// # Panics
++ ///
++ /// Panics if the `output` is smaller than the required size. The output size is indicated by
++ /// `md.size()` for the `Md` instance passed in [new]. An output size of |EVP_MAX_MD_SIZE| will
++ /// always be large enough.
++ #[corresponds(HMAC_Final)]
++ pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
++ assert!(output.len() >= self.output_size);
++ unsafe {
++ // Safety: The length assertion above makes sure that `HMAC_Final` will not write longer
++ // than the length of `output`.
++ let mut size: c_uint = 0;
++ cvt(ffi::HMAC_Final(
++ self.ctx,
++ output.as_mut_ptr(),
++ &mut size as *mut c_uint,
++ ))
++ .map(|_| size as usize)
++ }
++ }
++}
++
++impl Drop for HmacCtx {
++ #[corresponds(HMAC_CTX_free)]
++ fn drop(&mut self) {
++ unsafe {
++ ffi::HMAC_CTX_free(self.ctx);
++ }
++ }
++}
++
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::md::Md;
-+ use crate::memcmp;
+
-+ const SHA_256_DIGEST_SIZE:usize = 32;
++ const SHA_256_DIGEST_SIZE: usize = 32;
+
+ #[test]
+ fn hmac_sha256_test() {
-+ let expected_hmac = [0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7];
++ let expected_hmac = [
++ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
++ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
++ 0x2e, 0x32, 0xcf, 0xf7,
++ ];
+ let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
-+ let key:[u8; 20] = [0x0b; 20];
++ let key: [u8; 20] = [0x0b; 20];
+ let data = b"Hi There";
-+ let hmac_result = hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-+ expect!(memcmp::eq(&hmac_result, &expected_hmac));
++ let hmac_result =
++ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
++ assert_eq!(&hmac_result, &expected_hmac);
++ }
++
++ #[test]
++ #[should_panic]
++ fn hmac_sha256_output_too_short() {
++ let mut out = vec![0_u8; 1];
++ let key: [u8; 20] = [0x0b; 20];
++ let data = b"Hi There";
++ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
+ }
+
+ #[test]
+ fn hmac_sha256_test_big_buffer() {
-+ let expected_hmac = [0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7];
++ let expected_hmac = [
++ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
++ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
++ 0x2e, 0x32, 0xcf, 0xf7,
++ ];
+ let mut out: [u8; 100] = [0; 100];
-+ let key:[u8;20] = [0x0b; 20];
++ let key: [u8; 20] = [0x0b; 20];
+ let data = b"Hi There";
-+ let hmac_result = hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-+ expect_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
-+ expect!(memcmp::eq(&hmac_result, &expected_hmac));
++ let hmac_result =
++ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
++ assert_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
++ assert_eq!(&hmac_result, &expected_hmac);
++ }
++
++ #[test]
++ fn hmac_sha256_update_test() {
++ let expected_hmac = [
++ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
++ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
++ 0x2e, 0x32, 0xcf, 0xf7,
++ ];
++ let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
++ let key: [u8; 20] = [0x0b; 20];
++ let data = b"Hi There";
++ let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap();
++ hmac_ctx.update(data).unwrap();
++ let size = hmac_ctx.finalize(&mut out).unwrap();
++ assert_eq!(&out, &expected_hmac);
++ assert_eq!(size, SHA_256_DIGEST_SIZE);
++ }
++
++ #[test]
++ fn hmac_sha256_update_chunks_test() {
++ let expected_hmac = [
++ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
++ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
++ 0x2e, 0x32, 0xcf, 0xf7,
++ ];
++ let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
++ let key: [u8; 20] = [0x0b; 20];
++ let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap();
++ hmac_ctx.update(b"Hi").unwrap();
++ hmac_ctx.update(b" There").unwrap();
++ let size = hmac_ctx.finalize(&mut out).unwrap();
++ assert_eq!(&out, &expected_hmac);
++ assert_eq!(size, SHA_256_DIGEST_SIZE);
++ }
++
++ #[test]
++ #[should_panic]
++ fn hmac_sha256_update_output_too_short() {
++ let mut out = vec![0_u8; 1];
++ let key: [u8; 20] = [0x0b; 20];
++ let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap();
++ hmac_ctx.update(b"Hi There").unwrap();
++ hmac_ctx.finalize(&mut out).unwrap();
+ }
+}
diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs
-index 035c90c6..fec22cd9 100644
+index 035c90c6..02a51dbb 100644
--- a/openssl/src/lib.rs
+++ b/openssl/src/lib.rs
@@ -120,6 +120,9 @@
@@ -311,6 +510,18 @@
#[cfg(ossl300)]
pub mod lib_ctx;
pub mod md;
+@@ -189,6 +196,11 @@ type LenType = libc::size_t;
+ #[cfg(not(boringssl))]
+ type LenType = libc::c_int;
+
++#[cfg(boringssl)]
++type SignedLenType = libc::ssize_t;
++#[cfg(not(boringssl))]
++type SignedLenType = libc::c_int;
++
+ #[inline]
+ fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
+ if r.is_null() {
diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs
index 780bd637..92daa882 100644
--- a/openssl/src/pkey.rs
@@ -494,7 +705,7 @@
unsafe { Cipher(ffi::EVP_bf_ecb()) }
}
diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs
-index 940c8c9c..34b86c10 100644
+index 940c8c9c..f9477e4a 100644
--- a/openssl/src/x509/mod.rs
+++ b/openssl/src/x509/mod.rs
@@ -356,6 +356,19 @@ impl X509Builder {
@@ -517,6 +728,70 @@
/// Consumes the builder, returning the certificate.
pub fn build(self) -> X509 {
self.0
+@@ -898,13 +911,13 @@ impl X509NameBuilder {
+ pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> {
+ unsafe {
+ let field = CString::new(field).unwrap();
+- assert!(value.len() <= c_int::max_value() as usize);
++ assert!(value.len() <= isize::max_value() as usize);
+ cvt(ffi::X509_NAME_add_entry_by_txt(
+ self.0.as_ptr(),
+ field.as_ptr() as *mut _,
+ ffi::MBSTRING_UTF8,
+ value.as_ptr(),
+- value.len() as c_int,
++ value.len() as isize,
+ -1,
+ 0,
+ ))
+@@ -925,13 +938,13 @@ impl X509NameBuilder {
+ ) -> Result<(), ErrorStack> {
+ unsafe {
+ let field = CString::new(field).unwrap();
+- assert!(value.len() <= c_int::max_value() as usize);
++ assert!(value.len() <= isize::max_value() as usize);
+ cvt(ffi::X509_NAME_add_entry_by_txt(
+ self.0.as_ptr(),
+ field.as_ptr() as *mut _,
+ ty.as_raw(),
+ value.as_ptr(),
+- value.len() as c_int,
++ value.len() as isize,
+ -1,
+ 0,
+ ))
+@@ -946,13 +959,13 @@ impl X509NameBuilder {
+ /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_add_entry_by_NID.html
+ pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> {
+ unsafe {
+- assert!(value.len() <= c_int::max_value() as usize);
++ assert!(value.len() <= isize::max_value() as usize);
+ cvt(ffi::X509_NAME_add_entry_by_NID(
+ self.0.as_ptr(),
+ field.as_raw(),
+ ffi::MBSTRING_UTF8,
+ value.as_ptr() as *mut _,
+- value.len() as c_int,
++ value.len() as isize,
+ -1,
+ 0,
+ ))
+@@ -972,13 +985,13 @@ impl X509NameBuilder {
+ ty: Asn1Type,
+ ) -> Result<(), ErrorStack> {
+ unsafe {
+- assert!(value.len() <= c_int::max_value() as usize);
++ assert!(value.len() <= isize::max_value() as usize);
+ cvt(ffi::X509_NAME_add_entry_by_NID(
+ self.0.as_ptr(),
+ field.as_raw(),
+ ty.as_raw(),
+ value.as_ptr() as *mut _,
+- value.len() as c_int,
++ value.len() as isize,
+ -1,
+ 0,
+ ))
@@ -1286,6 +1299,29 @@ impl X509ReqBuilder {
}
}
@@ -549,10 +824,10 @@
self.0
diff --git a/openssl/src/x509/mod.rs.orig b/openssl/src/x509/mod.rs.orig
new file mode 100644
-index 00000000..940c8c9c
+index 00000000..34b86c10
--- /dev/null
+++ b/openssl/src/x509/mod.rs.orig
-@@ -0,0 +1,1843 @@
+@@ -0,0 +1,1879 @@
+//! The standard defining the format of public key certificates.
+//!
+//! An `X509` certificate binds an identity to a public key, and is either
@@ -911,6 +1186,19 @@
+ unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) }
+ }
+
++ /// Signs the certificate with a private key but without a digest.
++ ///
++ /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null
++ /// message digest.
++ #[cfg(boringssl)]
++ #[corresponds(X509_sign)]
++ pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
++ where
++ T: HasPrivate,
++ {
++ unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), ptr::null())).map(|_| ()) }
++ }
++
+ /// Consumes the builder, returning the certificate.
+ pub fn build(self) -> X509 {
+ self.0
@@ -1841,6 +2129,29 @@
+ }
+ }
+
++ /// Sign the request using a private key without a digest.
++ ///
++ /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null
++ /// message digest.
++ ///
++ /// This corresponds to [`X509_REQ_sign`].
++ ///
++ /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html
++ #[cfg(boringssl)]
++ pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
++ where
++ T: HasPrivate,
++ {
++ unsafe {
++ cvt(ffi::X509_REQ_sign(
++ self.0.as_ptr(),
++ key.as_ptr(),
++ ptr::null(),
++ ))
++ .map(|_| ())
++ }
++ }
++
+ /// Returns the `X509Req`.
+ pub fn build(self) -> X509Req {
+ self.0
@@ -2397,5 +2708,5 @@
+ }
+}
--
-2.39.1.519.gcb327c4b5f-goog
+2.40.1.495.gc816e09b53d-goog
diff --git a/nearby/scripts/openssl-patches/0002-Make-openssl-buildable.patch b/nearby/scripts/openssl-patches/0002-Make-openssl-buildable.patch
deleted file mode 100644
index 46f8a4b..0000000
--- a/nearby/scripts/openssl-patches/0002-Make-openssl-buildable.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 4a7246ed78e8845dd2ac5477fb4abd490a83f6eb Mon Sep 17 00:00:00 2001
-From: Maurice Lam <yukl@google.com>
-Date: Thu, 2 Feb 2023 19:21:46 +0000
-Subject: [PATCH 2/3] Make openssl buildable
-
----
- openssl/src/bio.rs | 9 +++++++--
- openssl/src/dh.rs | 2 +-
- 2 files changed, 8 insertions(+), 3 deletions(-)
-
-diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs
-index 6a72552a..5007d677 100644
---- a/openssl/src/bio.rs
-+++ b/openssl/src/bio.rs
-@@ -7,6 +7,11 @@ use std::slice;
- use crate::cvt_p;
- use crate::error::ErrorStack;
-
-+#[cfg(boringssl)]
-+type SignedLenType = libc::ssize_t;
-+#[cfg(not(boringssl))]
-+type SignedLenType = libc::c_int;
-+
- pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>);
-
- impl<'a> Drop for MemBioSlice<'a> {
-@@ -25,7 +30,7 @@ impl<'a> MemBioSlice<'a> {
- let bio = unsafe {
- cvt_p(BIO_new_mem_buf(
- buf.as_ptr() as *const _,
-- buf.len() as c_int,
-+ buf.len() as SignedLenType,
- ))?
- };
-
-@@ -78,7 +83,7 @@ cfg_if! {
- use ffi::BIO_new_mem_buf;
- } else {
- #[allow(bad_style)]
-- unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: ::libc::c_int) -> *mut ffi::BIO {
-+ unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: SignedLenType) -> *mut ffi::BIO {
- ffi::BIO_new_mem_buf(buf as *mut _, len)
- }
- }
-diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs
-index 12170b99..e781543e 100644
---- a/openssl/src/dh.rs
-+++ b/openssl/src/dh.rs
-@@ -239,7 +239,7 @@ where
- }
-
- cfg_if! {
-- if #[cfg(any(ossl110, libressl270))] {
-+ if #[cfg(any(ossl110, libressl270, boringssl))] {
- use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key};
- } else {
- #[allow(bad_style)]
---
-2.39.1.519.gcb327c4b5f-goog
-
diff --git a/nearby/scripts/openssl-patches/0003-Add-HmacCtx-wrapper-for-BoringSSL.patch b/nearby/scripts/openssl-patches/0003-Add-HmacCtx-wrapper-for-BoringSSL.patch
deleted file mode 100644
index 9c3f3a6..0000000
--- a/nearby/scripts/openssl-patches/0003-Add-HmacCtx-wrapper-for-BoringSSL.patch
+++ /dev/null
@@ -1,183 +0,0 @@
-From 1ff6b4d427e85f290b68e3b9f547ca536360f32b Mon Sep 17 00:00:00 2001
-From: Maurice Lam <yukl@google.com>
-Date: Thu, 2 Feb 2023 19:45:12 +0000
-Subject: [PATCH 3/3] Add HmacCtx wrapper for BoringSSL
-
----
- openssl-sys/src/handwritten/hmac.rs | 2 +-
- openssl/src/hmac.rs | 111 ++++++++++++++++++++++++----
- 2 files changed, 96 insertions(+), 17 deletions(-)
-
-diff --git a/openssl-sys/src/handwritten/hmac.rs b/openssl-sys/src/handwritten/hmac.rs
-index 7cbb7cc9..7c0e0b5a 100644
---- a/openssl-sys/src/handwritten/hmac.rs
-+++ b/openssl-sys/src/handwritten/hmac.rs
-@@ -3,7 +3,7 @@ use libc::*;
- use *;
-
- cfg_if! {
-- if #[cfg(any(ossl110, libressl350))] {
-+ if #[cfg(any(ossl110, libressl350, boringssl))] {
- extern "C" {
- pub fn HMAC_CTX_new() -> *mut HMAC_CTX;
- pub fn HMAC_CTX_free(ctx: *mut HMAC_CTX);
-diff --git a/openssl/src/hmac.rs b/openssl/src/hmac.rs
-index 601ae01b..90fd2175 100644
---- a/openssl/src/hmac.rs
-+++ b/openssl/src/hmac.rs
-@@ -1,10 +1,12 @@
--use crate::cvt_p;
-+use crate::{cvt, cvt_p};
- use crate::error::ErrorStack;
- use crate::md::MdRef;
-+use ffi::HMAC_CTX;
- use foreign_types::ForeignTypeRef;
-+use libc::{c_uint, c_void};
- use openssl_macros::corresponds;
--use libc::{c_void, c_uint};
- use std::convert::TryFrom;
-+use std::ptr;
-
- /// Computes the HMAC as a one-shot operation.
- ///
-@@ -20,7 +22,7 @@ pub fn hmac<'a>(
- md: &MdRef,
- key: &[u8],
- data: &[u8],
-- out: &'a mut [u8]
-+ out: &'a mut [u8],
- ) -> Result<&'a [u8], ErrorStack> {
- let mut out_len = c_uint::try_from(out.len()).unwrap();
- unsafe {
-@@ -31,38 +33,115 @@ pub fn hmac<'a>(
- data.as_ptr(),
- data.len(),
- out.as_mut_ptr(),
-- &mut out_len
-- ))?;
-+ &mut out_len,
-+ ))?;
- }
- Ok(&out[..out_len as usize])
- }
-
-+/// Only available in boringssl. For openssl, use `PKey::hmac` instead.
-+#[cfg(boringssl)]
-+pub struct HmacCtx {
-+ ctx: *mut HMAC_CTX,
-+}
-+
-+#[cfg(boringssl)]
-+impl HmacCtx {
-+ #[corresponds(HMAC_CTX_new)]
-+ pub fn new(key: &[u8], md: &MdRef) -> Result<Self, ErrorStack> {
-+ unsafe {
-+ let ctx = cvt_p(ffi::HMAC_CTX_new())?;
-+ cvt(ffi::HMAC_Init_ex(
-+ ctx,
-+ key.as_ptr() as *const c_void,
-+ key.len(),
-+ md.as_ptr(),
-+ ptr::null_mut(),
-+ ))?;
-+ Ok(Self { ctx })
-+ }
-+ }
-+
-+ pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
-+ unsafe { cvt(ffi::HMAC_Update(self.ctx, data.as_ptr(), data.len())).map(|_| ()) }
-+ }
-+
-+ /// Finishes the HMAC process, writing any remaining data to `output`.
-+ /// The number of bytes written to `output` is returned.
-+ /// `update` should not be called after this method.
-+ pub fn finalize(&mut self, md: &mut [u8]) -> Result<usize, ErrorStack> {
-+ unsafe {
-+ let mut size: c_uint = 0;
-+ cvt(ffi::HMAC_Final(
-+ self.ctx,
-+ md.as_mut_ptr(),
-+ &mut size as *mut c_uint,
-+ ))
-+ .map(|_| size as usize)
-+ }
-+ }
-+}
-+
-+impl Drop for HmacCtx {
-+ #[corresponds(HMAC_CTX_free)]
-+ fn drop(&mut self) {
-+ unsafe {
-+ ffi::HMAC_CTX_free(self.ctx);
-+ }
-+ }
-+}
-+
- #[cfg(test)]
- mod tests {
- use super::*;
- use crate::md::Md;
-- use crate::memcmp;
-
-- const SHA_256_DIGEST_SIZE:usize = 32;
-+ const SHA_256_DIGEST_SIZE: usize = 32;
-
- #[test]
- fn hmac_sha256_test() {
-- let expected_hmac = [0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7];
-+ let expected_hmac = [
-+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
-+ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
-+ 0x2e, 0x32, 0xcf, 0xf7,
-+ ];
- let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
-- let key:[u8; 20] = [0x0b; 20];
-+ let key: [u8; 20] = [0x0b; 20];
- let data = b"Hi There";
-- let hmac_result = hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-- expect!(memcmp::eq(&hmac_result, &expected_hmac));
-+ let hmac_result =
-+ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-+ assert_eq!(&hmac_result, &expected_hmac);
- }
-
- #[test]
- fn hmac_sha256_test_big_buffer() {
-- let expected_hmac = [0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7];
-+ let expected_hmac = [
-+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
-+ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
-+ 0x2e, 0x32, 0xcf, 0xf7,
-+ ];
- let mut out: [u8; 100] = [0; 100];
-- let key:[u8;20] = [0x0b; 20];
-+ let key: [u8; 20] = [0x0b; 20];
-+ let data = b"Hi There";
-+ let hmac_result =
-+ hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-+ assert_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
-+ assert_eq!(&hmac_result, &expected_hmac);
-+ }
-+
-+ #[test]
-+ fn hmac_sha256_update_test() {
-+ let expected_hmac = [
-+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
-+ 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
-+ 0x2e, 0x32, 0xcf, 0xf7,
-+ ];
-+ let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE];
-+ let key: [u8; 20] = [0x0b; 20];
- let data = b"Hi There";
-- let hmac_result = hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
-- expect_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
-- expect!(memcmp::eq(&hmac_result, &expected_hmac));
-+ let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap();
-+ hmac_ctx.update(data).unwrap();
-+ hmac_ctx.finalize(&mut out).unwrap();
-+ assert_eq!(&out, &expected_hmac);
- }
- }
---
-2.39.1.519.gcb327c4b5f-goog
-
diff --git a/nearby/scripts/openssl-patches/README.md b/nearby/scripts/openssl-patches/README.md
index da6f7d0..8483cad 100644
--- a/nearby/scripts/openssl-patches/README.md
+++ b/nearby/scripts/openssl-patches/README.md
@@ -1,10 +1,38 @@
This directory contains patch files for `rust-openssl` for it to build successfully with
`--features=unstable_boringssl`.
-After running `prepare-boringssl.sh`, the `rust-openssl` git repo is cloned to
+After running `prepare_boringssl`, the `rust-openssl` git repo is cloned to
`beto-rust/boringssl-build/rust-openssl/openssl`, and the patches in this directory will be applied.
-If you make further changes, or update the "base commit" in `prepare-boringssl.sh`, you can
-regenerate the patch files by checking out to the desired state of the tree, with all changes
-committed, and run `git format-patch BASE_COMMIT`. (Note: `BASE_COMMIT` is set by
-`prepare-boringssl.sh`)
+If you make further changes, or update the "base commit" in `prepare_boringssl`, you can
+regenerate the patch files by following these steps:
+
+1. Run `(source nearby/scripts/build-script.sh && prepare_boringssl)`
+2. `cd boringssl-build/rust-openssl/` and make the necessary changes
+3. Commit the changes
+4. `git format-patch BASE_COMMIT`. (Note: `BASE_COMMIT` is set by `prepare_boringssl`)
+5. The patch files will be generated in the current working directory. Move them here in
+ `nearby/scripts/openssl-patches`.
+
+### Regenerate patches based on AOSP changes
+
+In the "make the necessary changes" part in Step 2 above, follow these steps:
+
+1. Download the patch files in https://googleplex-android.googlesource.com/platform/external/rust/crates/openssl/+/master/patches
+2. `cd` into the openssl directory since the AOSP project starts at that root:
+ ```sh
+ $ cd openssl
+ ```
+3. Reset your branch to `BASE_COMMIT` to ensure the AOSP patches apply cleanly.
+ ```sh
+ $ git co BASE_COMMIT
+ $ git co -b create-patch
+ ```
+4. Apply the patches from AOSP
+ ```sh
+ for i in /path/to/android/external/rust/crates/openssl/patches/*; do patch -p1 < $i; done
+ ```
+5. Remove unneeded files (like `.orig`). Commit the changes.
+6. Patches locally in `scripts/openssl-patches` but not in AOSP are lost in this process. Reapply
+ the appropriate ones at this point, using `git apply` or `git am`.
+7. Continue with `git format-patch` described in step 4 in the previous section.