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.