mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-05 20:40:02 -08:00
feat: Derandomize the rosenpass protocol by adding testvectors (#604)
This commit is contained in:
87
Cargo.lock
generated
87
Cargo.lock
generated
@@ -126,6 +126,34 @@ dependencies = [
|
|||||||
"derive_arbitrary",
|
"derive_arbitrary",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "assert_tv"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a4141926c2544d566b0c5815040151fa6c1e96398810b43951d3c68e13dfc2a"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"assert_tv_macros",
|
||||||
|
"base64",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_yaml",
|
||||||
|
"toml",
|
||||||
|
"zstd",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "assert_tv_macros"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49fe5672253d886b06afd14bf16aec6111e2d111cbc83cd094a4f5f69f003332"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic-polyfill"
|
name = "atomic-polyfill"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
@@ -157,6 +185,12 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64ct"
|
name = "base64ct"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
@@ -2041,6 +2075,8 @@ name = "rosenpass"
|
|||||||
version = "0.3.0-dev"
|
version = "0.3.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"assert_tv",
|
||||||
|
"base64",
|
||||||
"clap",
|
"clap",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"clap_mangen",
|
"clap_mangen",
|
||||||
@@ -2193,6 +2229,8 @@ dependencies = [
|
|||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
"allocator-api2-tests",
|
"allocator-api2-tests",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"assert_tv",
|
||||||
|
"base64",
|
||||||
"base64ct",
|
"base64ct",
|
||||||
"log",
|
"log",
|
||||||
"memsec",
|
"memsec",
|
||||||
@@ -2200,6 +2238,8 @@ dependencies = [
|
|||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rosenpass-to",
|
"rosenpass-to",
|
||||||
"rosenpass-util",
|
"rosenpass-util",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -2396,6 +2436,19 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_yaml"
|
||||||
|
version = "0.9.34+deprecated"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
"unsafe-libyaml",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serial_test"
|
name = "serial_test"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
@@ -2753,6 +2806,12 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unsafe-libyaml"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -3292,3 +3351,31 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.98",
|
"syn 2.0.98",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-safe",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-safe"
|
||||||
|
version = "7.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-sys"
|
||||||
|
version = "2.0.15+zstd.1.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ uds = { git = "https://github.com/rosenpass/uds" }
|
|||||||
lazy_static = "1.5"
|
lazy_static = "1.5"
|
||||||
|
|
||||||
#Dev dependencies
|
#Dev dependencies
|
||||||
|
assert_tv = { version = "0.6.4" }
|
||||||
|
base64 = { version = "0.22.1" }
|
||||||
serial_test = "3.2.0"
|
serial_test = "3.2.0"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
stacker = "0.1.17"
|
stacker = "0.1.17"
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ let
|
|||||||
"service"
|
"service"
|
||||||
"target"
|
"target"
|
||||||
"toml"
|
"toml"
|
||||||
|
"zstd" # used for offloaded test vector values
|
||||||
];
|
];
|
||||||
# Files to explicitly include
|
# Files to explicitly include
|
||||||
files = [ "to/README.md" ];
|
files = [ "to/README.md" ];
|
||||||
|
|||||||
351
rosenpass/.test_vectors/crypto_server_test_vector_1.toml
Normal file
351
rosenpass/.test_vectors/crypto_server_test_vector_1.toml
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
description = "test setup: peer a secret key"
|
||||||
|
name = "peer_a_sk"
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:95"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
offload = true
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
description = "test setup: peer a public key"
|
||||||
|
name = "peer_a_pk"
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:96"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
offload = true
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
description = "test setup: peer b secret key"
|
||||||
|
name = "peer_b_sk"
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:101"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
offload = true
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
description = "test setup: peer b public key"
|
||||||
|
name = "peer_b_pk"
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:102"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
offload = true
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
description = "pre-shared key"
|
||||||
|
name = "psk"
|
||||||
|
value = "Vw7bZ1vyXfZo4D5/633F5IbTOntNFBjZRCWf/0cP3Ss="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:105"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "CryptoServer::cookie_secrets[0]"
|
||||||
|
value = "COU/279CXvyB3mwVxT6fCQ=="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:167"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:69"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "CryptoServer::cookie_secrets[1]"
|
||||||
|
value = "5Q+e2O020FTcmBWlAPnWlw=="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:172"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:69"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "CryptoServer::biscuit_keys[0]"
|
||||||
|
value = "5h9KZ2KfLP5uNbEdimMNLHUjPFm0L3helyg8QE7pd/E="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:177"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:69"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "CryptoServer::biscuit_keys[1]"
|
||||||
|
value = "uwyhSvwuEeXwVUg4+9CBoPWPL0AY+oSVUhFpGpnBaY8="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:179"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:69"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "CryptoServer::cookie_secrets[0]"
|
||||||
|
value = "KtKzsfp1NMN3mrln54w0TA=="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:167"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:69"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "CryptoServer::cookie_secrets[1]"
|
||||||
|
value = "cc1hSqM+Jhal8AII5NIWLA=="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:172"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:69"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "CryptoServer::biscuit_keys[0]"
|
||||||
|
value = "ih8UroUklL5NLdegMFQAEWE6huLEO4HBNL44jpk0VsI="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:177"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:69"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "CryptoServer::biscuit_keys[1]"
|
||||||
|
value = "mXEYSvzhz5E9eUskbKJBZlXlYF2N3Q1MwmbGeXmhXoI="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:179"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:69"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "hs.cookie_value.value"
|
||||||
|
value = "BryZRk1KR5Gc+AEm0plH1Q=="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3559"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "hs.core.sidi"
|
||||||
|
value = "avpJ6g=="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3572"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "hs.eski"
|
||||||
|
value = "KpIH2rHL5MR1TQosRVTAUhpDGYUfE7FbeDA/VgN2shd0gdwBRkdeTEZqKKdAY+ikmKydZQwNlFQW8WuH8fwknbUt/SCzo2iPbDg22sAuClQFN1sXckmEpDG2G4cqXHqkdVSuwhymt9V0w1lKFotTwNIN9Fo0eKq19twT16DP+nIPwrkDveAAm8OqwNp1iAODI8GuB3aL3Str/HDC7YR8QtuuzJQwfEa8CbihEpk+zZqVCJVZDrlfH6ydcJsahypuWpJQ4RwS+NejEvJirvgKngsgdPkGXyYLzQQhS4qagQDMkklWaxwL5pdSqlB+M/Cbx1iqgXgOp2PEykkOpgpEBKfDoCQxBnIYNEisx9B8XuibzqQiq0qctty3GBUf+peApMdataC6WwGqH1KpQiW8aUufIWFDK8xW56t3/bMV/AIsMWx3XpaxbGOQOgqAmRAxeYh23TeQ6lVturw/aMsV2phXBkgG6iQnzyd9z6Zufgezz3Ui2hdeJ/iCzfG0A7SMWlS8zETM46wExxO5smNh8jCoTzeSMpOeH3GfFyRs44PFybSQHtAbdcpcA+pj2VljGfRzq5U1AjpdbSKm8JO6n2PDOQlXHaNp5wZMTHZeywq/BrRWO0FXU9davLcEqUJ2xkwRIvEo24ae0MSD1SSd0rRK5LFilFWZXpDCkaoHvst87mdMeIBUYppMD+WkSuKun0XMXXSSWNPIvrGKFJlt4yTCNYsdfRBthGEa5sEApYd4jmi49zKbRSGGm/u915gdo0AvsFYa85EZzzBI0wfK3uW0X+YvGSEzwHGOAMaAyJu3tCGHt2tuevqND2lybzkJS+ih80l3jyaBbNmqQzBRt8YZtLg+e0ijH/x8IyGq+efCioRQjeN50sBAJrsSgncVtgoSraWbPLNu9movqQMtLiwGkUaZSqVANtQPQuccOFyzK7XD8zy5V0Bx/We0ijOvlyUPJWW+1LoALiArHhG7xIRQL8oe9RDP1mzPoGQd1MNRvCuePNpRX+JAO7a49vwsqUtsK6iAY5C1WIxc1TAVhrIz2YzKuyOQYJCbtkOTx5EZ+AbCsTa/E7VHJacj5xQXtYpy3NogXpAnI/ubjABhCVKTfNFytwKkQUAR1ZcoqzJlngdFILIFBeTEUJChXpBb3/obCCQOFVWCKaYfuLam34JgWkmKYUoao4ZP68yn7yc1l4lDRswKSgFt6YI31PcWGAbKM9QeKLF1Tso2bQOXlEF8MssCQjhN+PimSYU/A1ANTHEyQMxM+uUGXBAJwViSGSshHpioLkF3nBc2h7FT5Fi6hMU4xqUwsBgkfZKYQ6gMsMIqZjd/gIkbawwGU6VdLNNf4tw1f4ssD3QbKSA9LfsSHHV8YjcJ3vVoIVVd/Pmbe/kV8Ccz0zLPYWxyrrEanTOJwPqzYxBqTOBilVWlEfREu1ddYaccILMGEMdsQ6eBj4ySZYhj24Ajc3R8afR+anR2NNorfgIlF1d7VuW1BQG+loA3UqdO9lE4mwrARoy87LZKagYHUshet/CAYxinr0UlfCKqbEydljslyafPC4x/mmRWqjTNsTAVfZdOc1ESLyQ6fCkZ/ewOMmsVgUZsBPHI5LgE/2qjYhgXxzg72OmYynR4+8EWunEd2JScjTAurTVZBEPDfGq9wvySBeMbyIGgY0yIfJF/oGRI6/oyNoOBMyKff7oCVNzH+UBGPQJE0De7U1wmEqBNIOu6MMx4nFVgdNzA3TyLrhaOT3uDoJMo/9NnnvWDS5xhp9l8URkcVsol12MhmZAhqlhtGIOR72e5Jml6DNkLvYCX49ZKfMGBbnHNk/RhN5k3dccuD+UvIwxR3irMUXt6jITE0RbPCYWX14N4Jlcdz2oxA6U+RXW8ccJ0YQYjsNgmj1xpsnwY8/O6LkiB+Sm/fsJAkRGsKrWeyPKRcNR1uioBr6YpqKa0aHC0meQX7YqKNWZujOQX6ZJb2aMgx4CRJOc/fbqrtgpQy8mEy4JG2dmEPCdYKmY3YTGlpiVb65pLciEtJRIRiCqh4QNmCwtrixM5QgO5Y5gNfX/fXULtbtZdCDgQJ8CKaJNgxosHESp7YfeW+bO2tmmEwSHG+/s4YEEVQZm2OfJ46gLFPIixcTmADwFGOKEgTRofmHFxOUlIH1gXBkuqH0zWp71FqEpAoucjrROw"
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3579"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "hs.core.ck"
|
||||||
|
value = "qUtsK6iAY5C1WIxc1TAVhrIz2YzKuyOQYJCbtkOTx5EZ+AbCsTa/E7VHJacj5xQXtYpy3NogXpAnI/ubjABhCVKTfNFytwKkQUAR1ZcoqzJlngdFILIFBeTEUJChXpBb3/obCCQOFVWCKaYfuLam34JgWkmKYUoao4ZP68yn7yc1l4lDRswKSgFt6YI31PcWGAbKM9QeKLF1Tso2bQOXlEF8MssCQjhN+PimSYU/A1ANTHEyQMxM+uUGXBAJwViSGSshHpioLkF3nBc2h7FT5Fi6hMU4xqUwsBgkfZKYQ6gMsMIqZjd/gIkbawwGU6VdLNNf4tw1f4ssD3QbKSA9LfsSHHV8YjcJ3vVoIVVd/Pmbe/kV8Ccz0zLPYWxyrrEanTOJwPqzYxBqTOBilVWlEfREu1ddYaccILMGEMdsQ6eBj4ySZYhj24Ajc3R8afR+anR2NNorfgIlF1d7VuW1BQG+loA3UqdO9lE4mwrARoy87LZKagYHUshet/CAYxinr0UlfCKqbEydljslyafPC4x/mmRWqjTNsTAVfZdOc1ESLyQ6fCkZ/ewOMmsVgUZsBPHI5LgE/2qjYhgXxzg72OmYynR4+8EWunEd2JScjTAurTVZBEPDfGq9wvySBeMbyIGgY0yIfJF/oGRI6/oyNoOBMyKff7oCVNzH+UBGPQJE0De7U1wmEqBNIOu6MMx4nFVgdNzA3TyLrhaOT3uDoJMo/9NnnvWDS5xhp9l8URkcVsol12MhmZAhqlhtGIOR72e5Jml6DNkLvYCX49ZKfMGBbnHNk/RhN5k3dccuD+UvIwxR3irMUXt6jITE0RbPCYWX14N4Jlcdz2oxA6U+RXW8ccJ0YQYjsNgmj1xpsnwY8/O6LkiB+Sm/fsJAkRGsKrWeyPKRcNR1uioBr6YpqKa0aHC0meQX7YqKNWZujOQX6ZJb2aMgx4CRJOc/fbqrtgpQy8mEy4JG2dmEPCdYKmY3YTGlpiVb65pLciEtJRIRiCqh4QNmCwtrixM5QgO5Y5gNfX/fXULtbtZdCDgQJ8CKaJNgxosHESp7YfeW+bM="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3580"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "hs.core.ck 1"
|
||||||
|
value = "z2JAxQ4DPIikqHMSpFDAlmhjSBumhLZatJMrFAP+D1U="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3587"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
value = "crPEWzqlCERLJr83BrZupxLUOxWHsYZalisk94tma0k="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3263"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:23"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
value = "eJXlj5zOJo/Eq85TzOTi7QY8zqWBP0QOOl3PAcpFDYnZyWmuzdpwDZJTbagAP52Md9r+j2vME4SW9UvdvOQo+jbNfuCHytU5K3yxI77srR4aWepM+xPAmxbyIwD4VGjDOQNAjP4Rn8n5L9cCju1tgit7yeM0S4Mx2KDR/Emr8V7gQnERob6LrPJgu6BMWkbZA2+dLVZOsvWPFmmn"
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3264"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:23"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "hs.core.ck 2"
|
||||||
|
value = "UVoOgm+xgnV9tXlaLrlBHiM8XDAH+4tPm3DTbP9uJzs="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3602"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "ih.pidic"
|
||||||
|
value = "Y3Wstn84+vmUb/a/CtWHFixkdyTFKEaE7joUFM0vBZPehPAeDOXls/u5I1PvViF6"
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3615"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "hs.core.ck 3"
|
||||||
|
value = "RTCFQy236fEakHlQn8Pq4+ZbWAg4zvkP5iSp+RU7CpQ="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3616"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "hs.core.ck 4"
|
||||||
|
value = "9bjg2ICzmCeqYMt4ACfX5UMQUde7WgeuI6H+vdQuWck="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3627"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "ih.auth"
|
||||||
|
value = "E+AP6wyOrpngo7vE9Vpkjg=="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3636"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "hs.core.ck 5"
|
||||||
|
value = "MkkapMEoAWftWlVPIcroCCTpqOrMv5TYSff5h8Un/OE="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3637"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:44"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
description = "message exchanged by the protocol parties"
|
||||||
|
name = "message"
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:136"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
offload = true
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr IHR 4"
|
||||||
|
value = "z2JAxQ4DPIikqHMSpFDAlmhjSBumhLZatJMrFAP+D1U="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3693"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr IHR 5"
|
||||||
|
value = "UVoOgm+xgnV9tXlaLrlBHiM8XDAH+4tPm3DTbP9uJzs="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3702"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr IHR 6"
|
||||||
|
value = "RTCFQy236fEakHlQn8Pq4+ZbWAg4zvkP5iSp+RU7CpQ="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3714"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr IHR 7"
|
||||||
|
value = "9bjg2ICzmCeqYMt4ACfX5UMQUde7WgeuI6H+vdQuWck="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3724"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr IHR 8"
|
||||||
|
value = "MkkapMEoAWftWlVPIcroCCTpqOrMv5TYSff5h8Un/OE="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3733"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
name = "session_id"
|
||||||
|
value = "+qqWGQ=="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3741"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr RHR 3"
|
||||||
|
value = "rPSnj3sQzMcnolHZJZpDlZ71VcFEtIEENGLWUPyRZws="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3749"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
value = "aQGM2N7OhVgSlsa7pEaqdiRZLacxgDhwuEplHORsv3s="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3263"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:23"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
value = "XIOzetMa7cemW0Qq+vEu1frv9J/MhfFiT68mfbWZrZbzM5AI2lVPLXi75KvjbNC7YrqVG20d2DhZ38g9vjIAG50Lc8LHw3C+tQV2g/lCa4p1XySyQOJUAj/CpBGito8MdcdcxpFzLhCnq0owBSonbgyboxZq/hsX5z+unJu+5UiJYlxpcvu++w954OQiXi9lJpfnC4biY8Mw+8UL5d2UgWp8Yn3y3ZoIKSNGA5hR5/JUg1QStbSvWrhNiiDrfNUR0k2zKmLPXPS1pmaBvSuWQptq3WiA1OtkRsCSrAzjOtyUPWSZyXrttAZ4VJCBkEnd4OZy7eC/mBa3FjwJAfcvVY7i8mU1yDpLtS7MtdAZKMeGn0fQDWOx5z+vM+jbwOxXer79jPKPcdigxjTfARz+SxhfWfqGO5hBh86Ra0F+vgw3KH/YQgTchroWVF8WIwZlNwp6DqvwXBXwRPbtrv+uxmRHT9Oe+ZxJr88Nd1gRtjL0FN6faE1quGDAHWPuAfhFcxa7kdPpHN46cHSC+nzO1gtabPX/b0PM2awmNPB5QPpWoGHzz4HTYV7MYHmC4mxdKU7BT+U3vJd4+vl+7wGQSVxSCwzWHqCjRwOkIDLeiyZss7iz8BnOeErDySbPTMYI/Jv/R7lalOk4+73a1m2m4uZKetXRGEjg8btiKfhFaPZMc9p8xZeJNbsUbqoMl8/R1QGRqXHxzk9tTZW0AHV0t4uLnvHJgu9mR6LApZ99sAJpNcuU9TnsSPfT32DlXWNxtb0DnTQXxLQ7TnSWFYPCYyv7hbfNk8lDdGJqStSvnCe16KYoYjxpExEIfCAFicYhhar5MOpkinJMeyhMhVd2ctVIIIzZXePfZXcdOod2JbYh6+dmp0bnTyussHv9R+qYCCv5AyU/crKSmTbjgyOsmaVpyoTljsozC32uhqZh4M7KBUz1XyPJfD6L4NE1ovCKSfwJepYOqBw0MkdWoXwScyhMWNpVhS8X1aZ/QOZFVIuyYxoiwqpF/y3xV6QYFZmd"
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3264"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:23"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr RHR 4"
|
||||||
|
value = "WCh3N6kKat+5vvn3WNTxsF9yXGYTQS7hlMUplMac/14="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3764"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
value = "Sx7y7DSdVQVHWxR4OOMjyrDr8vuZa7MPX/U8GnPCIHY="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3263"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:23"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
value = "VwqEOlvdW0Evc1CasejxXQ0dN3mZ4HPMA6ogk3Q7OUzzgCIvbTU8BvBK6d1UH2R7Y5Nd/JdHgag42f5FpjVljX2vlXMk3XxUtREpORxqJ5qUgHejsgJyRO9caOPX/ZXmUZ6vORP7pIulLt2i47ykPNNlWuJmxVJj6NK+lE1BDMIuivHebR31atigV/fFFJui26vy5V9y6xZmnCJm"
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3264"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:23"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr RHR 5"
|
||||||
|
value = "7gd9Mw7X0ZFmkIkP/JDofflRSAw21F1RjG4HXeMJfTI="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3779"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
value = "QyffgzBjc8qAqK18vYsH9TKs9lc6Njg8Q8nANsF/FMMBAAAAAAAAAAAAAADuB30zDtfRkWaQiQ/8kOh9+VFIDDbUXVGMbgdd4wl9Mg=="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3336"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:31"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
description = "Biscuit key after being cycled"
|
||||||
|
name = "CryptoServer::biscuit_key[r]"
|
||||||
|
value = "TIDswcSHh8WKsEsuwMCyldE0zVH8IEjV97ES8v3nHw0="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:1430"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:127"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Const"
|
||||||
|
value = "iSR2RKOw5VeBICb4b+i8P4QtF8XnJq2N"
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3353"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:31"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
value = "iSR2RKOw5VeBICb4b+i8P4QtF8XnJq2Nq1gaCMgEJ+v1LulDYsjbfU5O0alWStfs4fBy7zS69RkzT8p0m3mVcK0TY9RRdWfxmCzU1U8DP7CbhfZxZHJC9CO8xwIa5r1NjVE1gxJJUEJCTHvtCc3PtFj861c="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3361"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:31"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr RHR 6"
|
||||||
|
value = "urS3a0/ufhUxj7bAnafEQ3j7it4q2XOfO+DVCeQJp4U="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3788"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
name = "chaining_key_ihr RHR 7"
|
||||||
|
value = "bbWd4iHXPK6helZLik4t96JKB7yiyw+qcNWbvlDiaQs="
|
||||||
|
code_location = "rosenpass/src/protocol/protocol.rs:3797"
|
||||||
|
test_vec_set_code_location = "rosenpass/src/protocol/test_vector_sets.rs:84"
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
description = "message exchanged by the protocol parties"
|
||||||
|
name = "message"
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:136"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
offload = true
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
description = "message exchanged by the protocol parties"
|
||||||
|
name = "message"
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:136"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
offload = true
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
description = "message exchanged by the protocol parties"
|
||||||
|
name = "message"
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:136"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
|
offload = true
|
||||||
|
|
||||||
|
[[entries]]
|
||||||
|
entry_type = "Output"
|
||||||
|
description = "final exchanged key"
|
||||||
|
name = "exchanged_key"
|
||||||
|
value = "NKG5/vCPc0akKnm5RxctcPigO8fvd0zqJeO2+xbDpq4="
|
||||||
|
code_location = "tests/test_vector_crypto_server.rs:153"
|
||||||
|
test_vec_set_code_location = "rosenpass/tests/test_vector_crypto_server.rs:33"
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -79,6 +79,9 @@ command-fds = { workspace = true, optional = true }
|
|||||||
rustix = { workspace = true, optional = true }
|
rustix = { workspace = true, optional = true }
|
||||||
uds = { workspace = true, optional = true, features = ["mio_1xx"] }
|
uds = { workspace = true, optional = true, features = ["mio_1xx"] }
|
||||||
libcrux-test-utils = { workspace = true, optional = true }
|
libcrux-test-utils = { workspace = true, optional = true }
|
||||||
|
assert_tv = { workspace = true }
|
||||||
|
base64 = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ pub mod constants;
|
|||||||
pub mod cookies;
|
pub mod cookies;
|
||||||
pub mod index;
|
pub mod index;
|
||||||
pub mod osk_domain_separator;
|
pub mod osk_domain_separator;
|
||||||
|
pub mod test_vector_sets;
|
||||||
pub mod testutils;
|
pub mod testutils;
|
||||||
pub mod timing;
|
pub mod timing;
|
||||||
pub mod zerocopy;
|
pub mod zerocopy;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{bail, ensure, Context, Result};
|
use anyhow::{bail, ensure, Context, Result};
|
||||||
|
use assert_tv::{TestVector, TestVectorNOP};
|
||||||
use memoffset::span_of;
|
use memoffset::span_of;
|
||||||
use zerocopy::{AsBytes, FromBytes, Ref};
|
use zerocopy::{AsBytes, FromBytes, Ref};
|
||||||
|
|
||||||
@@ -33,6 +34,10 @@ use rosenpass_util::{
|
|||||||
time::Timebase,
|
time::Timebase,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::protocol::test_vector_sets::{
|
||||||
|
CycledBiscuitSecretKeyTestValues, EncapsAndMixTestValues, HandleInitHelloTestValues,
|
||||||
|
HandleInitiationTestValues, StoreBiscuitTestValues,
|
||||||
|
};
|
||||||
use crate::{hash_domains, msgs::*, RosenpassError};
|
use crate::{hash_domains, msgs::*, RosenpassError};
|
||||||
|
|
||||||
use super::basic_types::{
|
use super::basic_types::{
|
||||||
@@ -1392,6 +1397,20 @@ impl CryptoServer {
|
|||||||
///
|
///
|
||||||
/// Swap the biscuit keys, also advancing both biscuit key's mortality
|
/// Swap the biscuit keys, also advancing both biscuit key's mortality
|
||||||
pub fn active_biscuit_key(&mut self) -> BiscuitKeyPtr {
|
pub fn active_biscuit_key(&mut self) -> BiscuitKeyPtr {
|
||||||
|
self.active_biscuit_key_with_test_vector::<TestVectorNOP>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic variant of [`Self::active_biscuit_key`] that allows selecting
|
||||||
|
/// a [`TestVector`] implementation.
|
||||||
|
///
|
||||||
|
/// This function is primarily intended for testing with different
|
||||||
|
/// test vector strategies. In production code, prefer using
|
||||||
|
/// [`Self::active_biscuit_key`], which defaults to [`assert_tv::TestVectorNOP`].
|
||||||
|
///
|
||||||
|
/// Use this function with [`assert_tv::TestVectorActive`] in tests that require
|
||||||
|
/// applying actual test vectors. See the `tests::test_vector_crypto_server`
|
||||||
|
/// test for an example
|
||||||
|
pub fn active_biscuit_key_with_test_vector<TV: TestVector>(&mut self) -> BiscuitKeyPtr {
|
||||||
let (a, b) = (BiscuitKeyPtr(0), BiscuitKeyPtr(1));
|
let (a, b) = (BiscuitKeyPtr(0), BiscuitKeyPtr(1));
|
||||||
let (t, u) = (a.get(self).created_at, b.get(self).created_at);
|
let (t, u) = (a.get(self).created_at, b.get(self).created_at);
|
||||||
|
|
||||||
@@ -1407,6 +1426,11 @@ impl CryptoServer {
|
|||||||
let r = if t < u { a } else { b };
|
let r = if t < u { a } else { b };
|
||||||
let tb = self.timebase.clone();
|
let tb = self.timebase.clone();
|
||||||
r.get_mut(self).randomize(&tb);
|
r.get_mut(self).randomize(&tb);
|
||||||
|
let test_values: CycledBiscuitSecretKeyTestValues = TV::initialize_values();
|
||||||
|
TV::expose_mut_value(
|
||||||
|
&test_values.cycled_biscuit_secret_key,
|
||||||
|
&mut self.biscuit_keys[r.0].value,
|
||||||
|
);
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1725,6 +1749,7 @@ impl Mortal for KnownInitConfResponsePtr {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
/// use assert_tv::TestVector;
|
||||||
/// use rosenpass::protocol::{timing::Timing, Mortal, MortalExt, Lifecycle, CryptoServer, ProtocolVersion};
|
/// use rosenpass::protocol::{timing::Timing, Mortal, MortalExt, Lifecycle, CryptoServer, ProtocolVersion};
|
||||||
/// use rosenpass::protocol::testutils::{ServerForTesting, time_travel_forward};
|
/// use rosenpass::protocol::testutils::{ServerForTesting, time_travel_forward};
|
||||||
///
|
///
|
||||||
@@ -1865,13 +1890,31 @@ impl CryptoServer {
|
|||||||
///
|
///
|
||||||
/// See [Self::poll] on how to use this function with poll.
|
/// See [Self::poll] on how to use this function with poll.
|
||||||
pub fn initiate_handshake(&mut self, peer: PeerPtr, tx_buf: &mut [u8]) -> Result<usize> {
|
pub fn initiate_handshake(&mut self, peer: PeerPtr, tx_buf: &mut [u8]) -> Result<usize> {
|
||||||
|
self.initiate_handshake_with_test_vector::<TestVectorNOP>(peer, tx_buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic variant of [`Self::initiate_handshake`] that allows selecting
|
||||||
|
/// a [`TestVector`] implementation.
|
||||||
|
///
|
||||||
|
/// This function is primarily intended for testing with different
|
||||||
|
/// test vector strategies. In production code, prefer using
|
||||||
|
/// [`Self::initiate_handshake`], which defaults to [`assert_tv::TestVectorNOP`].
|
||||||
|
///
|
||||||
|
/// Use this function with [`assert_tv::TestVectorActive`] in tests that require
|
||||||
|
/// applying actual test vectors. See the `tests::test_vector_crypto_server`
|
||||||
|
/// test for an example
|
||||||
|
pub fn initiate_handshake_with_test_vector<TV: TestVector>(
|
||||||
|
&mut self,
|
||||||
|
peer: PeerPtr,
|
||||||
|
tx_buf: &mut [u8],
|
||||||
|
) -> Result<usize> {
|
||||||
// NOTE retransmission? yes if initiator, no if responder
|
// NOTE retransmission? yes if initiator, no if responder
|
||||||
// TODO remove unnecessary copying between global tx_buf and per-peer buf
|
// TODO remove unnecessary copying between global tx_buf and per-peer buf
|
||||||
// TODO move retransmission storage to io server
|
// TODO move retransmission storage to io server
|
||||||
//
|
//
|
||||||
// Envelope::<InitHello>::default(); // TODO
|
// Envelope::<InitHello>::default(); // TODO
|
||||||
let mut msg = truncating_cast_into::<Envelope<InitHello>>(tx_buf)?;
|
let mut msg = truncating_cast_into::<Envelope<InitHello>>(tx_buf)?;
|
||||||
self.handle_initiation(peer, &mut msg.payload)?;
|
self.handle_initiation_with_test_vector::<TV>(peer, &mut msg.payload)?;
|
||||||
let len = self.seal_and_commit_msg(peer, MsgType::InitHello, &mut msg)?;
|
let len = self.seal_and_commit_msg(peer, MsgType::InitHello, &mut msg)?;
|
||||||
peer.hs()
|
peer.hs()
|
||||||
.store_msg_for_retransmission(self, msg.as_bytes())?;
|
.store_msg_for_retransmission(self, msg.as_bytes())?;
|
||||||
@@ -2111,6 +2154,24 @@ impl CryptoServer {
|
|||||||
///
|
///
|
||||||
/// See [Self::poll] on how to use this function with poll.
|
/// See [Self::poll] on how to use this function with poll.
|
||||||
pub fn handle_msg(&mut self, rx_buf: &[u8], tx_buf: &mut [u8]) -> Result<HandleMsgResult> {
|
pub fn handle_msg(&mut self, rx_buf: &[u8], tx_buf: &mut [u8]) -> Result<HandleMsgResult> {
|
||||||
|
self.handle_msg_with_test_vector::<TestVectorNOP>(rx_buf, tx_buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic message handler that allows selecting a [`TestVector`]
|
||||||
|
/// implementation.
|
||||||
|
///
|
||||||
|
/// This function is primarily intended for **testing** with different
|
||||||
|
/// test vector strategies. In production code, prefer using
|
||||||
|
/// [`Self::handle_msg`], which defaults to [`assert_tv::TestVectorNOP`].
|
||||||
|
///
|
||||||
|
/// Use this function with [`assert_tv::TestVectorActive`] in tests that require
|
||||||
|
/// applying actual test vectors. See the `tests::test_vector_crypto_server`
|
||||||
|
/// test for an example
|
||||||
|
pub fn handle_msg_with_test_vector<TV: TestVector>(
|
||||||
|
&mut self,
|
||||||
|
rx_buf: &[u8],
|
||||||
|
tx_buf: &mut [u8],
|
||||||
|
) -> Result<HandleMsgResult> {
|
||||||
let seal_broken = "Message seal broken!";
|
let seal_broken = "Message seal broken!";
|
||||||
// length of the response. We assume no response, so None for now
|
// length of the response. We assume no response, so None for now
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
@@ -2131,7 +2192,7 @@ impl CryptoServer {
|
|||||||
|
|
||||||
// At this point, we do not know the hash functon used by the peer, thus we try both,
|
// At this point, we do not know the hash functon used by the peer, thus we try both,
|
||||||
// with a preference for SHAKE256.
|
// with a preference for SHAKE256.
|
||||||
let peer_shake256 = self.handle_init_hello(
|
let peer_shake256 = self.handle_init_hello_with_test_vector::<TV>(
|
||||||
&msg_in.payload,
|
&msg_in.payload,
|
||||||
&mut msg_out.payload,
|
&mut msg_out.payload,
|
||||||
KeyedHash::keyed_shake256(),
|
KeyedHash::keyed_shake256(),
|
||||||
@@ -2139,7 +2200,7 @@ impl CryptoServer {
|
|||||||
let (peer, peer_hash_choice) = match peer_shake256 {
|
let (peer, peer_hash_choice) = match peer_shake256 {
|
||||||
Ok(peer) => (peer, KeyedHash::keyed_shake256()),
|
Ok(peer) => (peer, KeyedHash::keyed_shake256()),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let peer_blake2b = self.handle_init_hello(
|
let peer_blake2b = self.handle_init_hello_with_test_vector::<TV>(
|
||||||
&msg_in.payload,
|
&msg_in.payload,
|
||||||
&mut msg_out.payload,
|
&mut msg_out.payload,
|
||||||
KeyedHash::incorrect_hmac_blake2b(),
|
KeyedHash::incorrect_hmac_blake2b(),
|
||||||
@@ -3159,8 +3220,48 @@ impl HandshakeState {
|
|||||||
ct: &mut [u8; KEM_CT_LEN],
|
ct: &mut [u8; KEM_CT_LEN],
|
||||||
pk: &[u8; KEM_PK_LEN],
|
pk: &[u8; KEM_PK_LEN],
|
||||||
) -> Result<&mut Self> {
|
) -> Result<&mut Self> {
|
||||||
|
self.encaps_and_mix_with_test_vector(kem, ct, pk, std::marker::PhantomData::<TestVectorNOP>)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic variant of [`Self::encaps_and_mix`] that allows selecting
|
||||||
|
/// a [`TestVector`] implementation.
|
||||||
|
///
|
||||||
|
/// This function is primarily intended for testing with different
|
||||||
|
/// test vector strategies. In production code, prefer using
|
||||||
|
/// [`Self::encaps_and_mix`], which defaults to [`assert_tv::TestVectorNOP`].
|
||||||
|
///
|
||||||
|
/// Use this function with [`assert_tv::TestVectorActive`] in tests that require
|
||||||
|
/// applying actual test vectors. See the `tests::test_vector_crypto_server`
|
||||||
|
/// test for an example.
|
||||||
|
///
|
||||||
|
/// Note on `_tv: PhantomData<TV>` parameter:
|
||||||
|
/// - Rust’s type inference ties generic parameter specification together;
|
||||||
|
/// explicitly selecting `TV` with turbofish can force you to also spell
|
||||||
|
/// out the const generics.
|
||||||
|
/// - By adding a value parameter of type `PhantomData<TV>`, you can choose
|
||||||
|
/// `TV` at the call site while allowing the compiler to infer `KEM_*`
|
||||||
|
/// const generics from `ct` and `pk`.
|
||||||
|
/// - Call like: `encaps_and_mix_with_test_vector(&StaticKem, &mut ct, pk,
|
||||||
|
/// PhantomData::<TestVectorActive>)?;`
|
||||||
|
pub fn encaps_and_mix_with_test_vector<
|
||||||
|
const KEM_SK_LEN: usize,
|
||||||
|
const KEM_PK_LEN: usize,
|
||||||
|
const KEM_CT_LEN: usize,
|
||||||
|
const KEM_SHK_LEN: usize,
|
||||||
|
KemImpl: Kem<KEM_SK_LEN, KEM_PK_LEN, KEM_CT_LEN, KEM_SHK_LEN>,
|
||||||
|
TV: TestVector,
|
||||||
|
>(
|
||||||
|
&mut self,
|
||||||
|
kem: &KemImpl,
|
||||||
|
ct: &mut [u8; KEM_CT_LEN],
|
||||||
|
pk: &[u8; KEM_PK_LEN],
|
||||||
|
_tv: std::marker::PhantomData<TV>,
|
||||||
|
) -> Result<&mut Self> {
|
||||||
|
let test_values: EncapsAndMixTestValues<KEM_CT_LEN, KEM_SHK_LEN> = TV::initialize_values();
|
||||||
let mut shk = Secret::<KEM_SHK_LEN>::zero();
|
let mut shk = Secret::<KEM_SHK_LEN>::zero();
|
||||||
kem.encaps(shk.secret_mut(), ct, pk)?;
|
kem.encaps(shk.secret_mut(), ct, pk)?;
|
||||||
|
TV::expose_mut_value(&test_values.shk, &mut shk);
|
||||||
|
TV::expose_mut_value(&test_values.ct, ct);
|
||||||
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
self.mix(pk)?.mix(shk.secret())?.mix(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3199,6 +3300,26 @@ impl HandshakeState {
|
|||||||
peer: PeerPtr,
|
peer: PeerPtr,
|
||||||
biscuit_ct: &mut [u8],
|
biscuit_ct: &mut [u8],
|
||||||
) -> Result<&mut Self> {
|
) -> Result<&mut Self> {
|
||||||
|
self.store_biscuit_with_test_vector::<TestVectorNOP>(srv, peer, biscuit_ct)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic variant of [`Self::store_biscuit`] that allows selecting
|
||||||
|
/// a [`TestVector`] implementation.
|
||||||
|
///
|
||||||
|
/// This function is primarily intended for testing with different
|
||||||
|
/// test vector strategies. In production code, prefer using
|
||||||
|
/// [`Self::store_biscuit`], which defaults to [`assert_tv::TestVectorNOP`].
|
||||||
|
///
|
||||||
|
/// Use this function with [`assert_tv::TestVectorActive`] in tests that require
|
||||||
|
/// applying actual test vectors. See the `tests::test_vector_crypto_server`
|
||||||
|
/// test for an example
|
||||||
|
pub fn store_biscuit_with_test_vector<TV: TestVector>(
|
||||||
|
&mut self,
|
||||||
|
srv: &mut CryptoServer,
|
||||||
|
peer: PeerPtr,
|
||||||
|
biscuit_ct: &mut [u8],
|
||||||
|
) -> Result<&mut Self> {
|
||||||
|
let test_values: StoreBiscuitTestValues = TV::initialize_values();
|
||||||
let mut biscuit = Secret::<BISCUIT_PT_LEN>::zero(); // pt buffer
|
let mut biscuit = Secret::<BISCUIT_PT_LEN>::zero(); // pt buffer
|
||||||
let mut biscuit: Ref<&mut [u8], Biscuit> =
|
let mut biscuit: Ref<&mut [u8], Biscuit> =
|
||||||
Ref::new(biscuit.secret_mut().as_mut_slice()).unwrap();
|
Ref::new(biscuit.secret_mut().as_mut_slice()).unwrap();
|
||||||
@@ -3212,6 +3333,8 @@ impl HandshakeState {
|
|||||||
.ck
|
.ck
|
||||||
.copy_from_slice(self.ck.clone().danger_into_secret().secret());
|
.copy_from_slice(self.ck.clone().danger_into_secret().secret());
|
||||||
|
|
||||||
|
TV::check_value(&test_values.biscuit, &biscuit.as_bytes().to_vec());
|
||||||
|
|
||||||
// calculate ad contents
|
// calculate ad contents
|
||||||
let ad = hash_domains::biscuit_ad(peer.get(srv).protocol_version.keyed_hash())?
|
let ad = hash_domains::biscuit_ad(peer.get(srv).protocol_version.keyed_hash())?
|
||||||
.mix(srv.spkm.deref())?
|
.mix(srv.spkm.deref())?
|
||||||
@@ -3224,14 +3347,18 @@ impl HandshakeState {
|
|||||||
|
|
||||||
// The first bit of the nonce indicates which biscuit key was used
|
// The first bit of the nonce indicates which biscuit key was used
|
||||||
// TODO: This is premature optimization. Remove!
|
// TODO: This is premature optimization. Remove!
|
||||||
let bk = srv.active_biscuit_key();
|
let bk = srv.active_biscuit_key_with_test_vector::<TV>();
|
||||||
let mut n = XAEADNonce::random();
|
let mut n = XAEADNonce::random();
|
||||||
|
|
||||||
|
TV::expose_mut_value(&test_values.n, &mut n);
|
||||||
|
|
||||||
n[0] &= 0b0111_1111;
|
n[0] &= 0b0111_1111;
|
||||||
n[0] |= (bk.0 as u8 & 0x1) << 7;
|
n[0] |= (bk.0 as u8 & 0x1) << 7;
|
||||||
|
|
||||||
let k = bk.get(srv).value.secret();
|
let k = bk.get(srv).value.secret();
|
||||||
let pt = biscuit.as_bytes();
|
let pt = biscuit.as_bytes();
|
||||||
XAead.encrypt_with_nonce_in_ctxt(biscuit_ct, k, &n, &ad, pt)?;
|
XAead.encrypt_with_nonce_in_ctxt(biscuit_ct, k, &n, &ad, pt)?;
|
||||||
|
TV::check_value(&test_values.biscuit_ct, &biscuit_ct.to_vec());
|
||||||
|
|
||||||
self.mix(biscuit_ct)
|
self.mix(biscuit_ct)
|
||||||
}
|
}
|
||||||
@@ -3400,6 +3527,26 @@ impl CryptoServer {
|
|||||||
/// Core cryptographic protocol implementation: Kicks of the handshake
|
/// Core cryptographic protocol implementation: Kicks of the handshake
|
||||||
/// on the initiator side, producing the InitHello message.
|
/// on the initiator side, producing the InitHello message.
|
||||||
pub fn handle_initiation(&mut self, peer: PeerPtr, ih: &mut InitHello) -> Result<PeerPtr> {
|
pub fn handle_initiation(&mut self, peer: PeerPtr, ih: &mut InitHello) -> Result<PeerPtr> {
|
||||||
|
self.handle_initiation_with_test_vector::<TestVectorNOP>(peer, ih)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic variant of [`Self::handle_initiation`] that allows selecting
|
||||||
|
/// a [`TestVector`] implementation.
|
||||||
|
///
|
||||||
|
/// This function is primarily intended for testing with different
|
||||||
|
/// test vector strategies. In production code, prefer using
|
||||||
|
/// [`Self::handle_initiation`], which defaults to [`assert_tv::TestVectorNOP`].
|
||||||
|
///
|
||||||
|
/// Use this function with [`assert_tv::TestVectorActive`] in tests that require
|
||||||
|
/// applying actual test vectors. See the `tests::test_vector_crypto_server`
|
||||||
|
/// test for an example
|
||||||
|
pub fn handle_initiation_with_test_vector<TV: TestVector>(
|
||||||
|
&mut self,
|
||||||
|
peer: PeerPtr,
|
||||||
|
ih: &mut InitHello,
|
||||||
|
) -> Result<PeerPtr> {
|
||||||
|
let test_values: HandleInitiationTestValues = TV::initialize_values();
|
||||||
|
|
||||||
#[cfg(feature = "trace_bench")]
|
#[cfg(feature = "trace_bench")]
|
||||||
let _span_guard = rosenpass_util::trace_bench::trace().emit_span("handle_initiation");
|
let _span_guard = rosenpass_util::trace_bench::trace().emit_span("handle_initiation");
|
||||||
|
|
||||||
@@ -3408,6 +3555,12 @@ impl CryptoServer {
|
|||||||
peer.get(self).protocol_version.keyed_hash(),
|
peer.get(self).protocol_version.keyed_hash(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// hs.cookie_value.created_at = tv_const!(hs.cookie_value.created_at, "init_handshake-cookie-created_at");
|
||||||
|
TV::expose_mut_value(
|
||||||
|
&test_values.init_handshake_cookie,
|
||||||
|
&mut hs.cookie_value.value,
|
||||||
|
);
|
||||||
|
|
||||||
// IHI1
|
// IHI1
|
||||||
protocol_section!("IHI1", {
|
protocol_section!("IHI1", {
|
||||||
hs.core.init(peer.get(self).spkt.deref())?;
|
hs.core.init(peer.get(self).spkt.deref())?;
|
||||||
@@ -3416,24 +3569,40 @@ impl CryptoServer {
|
|||||||
// IHI2
|
// IHI2
|
||||||
protocol_section!("IHI2", {
|
protocol_section!("IHI2", {
|
||||||
hs.core.sidi.randomize();
|
hs.core.sidi.randomize();
|
||||||
|
TV::expose_mut_value(&test_values.init_handshake_sidi, &mut hs.core.sidi);
|
||||||
ih.sidi.copy_from_slice(&hs.core.sidi.value);
|
ih.sidi.copy_from_slice(&hs.core.sidi.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// IHI3
|
// IHI3
|
||||||
protocol_section!("IHI3", {
|
protocol_section!("IHI3", {
|
||||||
EphemeralKem.keygen(hs.eski.secret_mut(), &mut hs.epki)?;
|
EphemeralKem.keygen(hs.eski.secret_mut(), &mut hs.epki)?;
|
||||||
|
TV::expose_mut_value(&test_values.init_handshake_eski, &mut hs.eski);
|
||||||
|
TV::expose_mut_value(&test_values.init_handshake_epki, &mut hs.epki);
|
||||||
ih.epki.copy_from_slice(&hs.epki.value);
|
ih.epki.copy_from_slice(&hs.epki.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// IHI4
|
// IHI4
|
||||||
protocol_section!("IHI4", {
|
protocol_section!("IHI4", {
|
||||||
hs.core.mix(ih.sidi.as_slice())?.mix(ih.epki.as_slice())?;
|
hs.core.mix(ih.sidi.as_slice())?.mix(ih.epki.as_slice())?;
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.init_handshake_mix_1,
|
||||||
|
&hs.core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// IHI5
|
// IHI5
|
||||||
protocol_section!("IHI5", {
|
protocol_section!("IHI5", {
|
||||||
hs.core
|
use std::marker::PhantomData;
|
||||||
.encaps_and_mix(&StaticKem, &mut ih.sctr, peer.get(self).spkt.deref())?;
|
hs.core.encaps_and_mix_with_test_vector(
|
||||||
|
&StaticKem,
|
||||||
|
&mut ih.sctr,
|
||||||
|
peer.get(self).spkt.deref(),
|
||||||
|
PhantomData::<TV>,
|
||||||
|
)?;
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.init_handshake_mix_2,
|
||||||
|
&hs.core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// IHI6
|
// IHI6
|
||||||
@@ -3443,6 +3612,11 @@ impl CryptoServer {
|
|||||||
self.pidm(peer.get(self).protocol_version.keyed_hash())?
|
self.pidm(peer.get(self).protocol_version.keyed_hash())?
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)?;
|
)?;
|
||||||
|
TV::check_value(&test_values.init_hello_pidic, &ih.pidic);
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.init_handshake_mix_3,
|
||||||
|
&hs.core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// IHI7
|
// IHI7
|
||||||
@@ -3450,16 +3624,24 @@ impl CryptoServer {
|
|||||||
hs.core
|
hs.core
|
||||||
.mix(self.spkm.deref())?
|
.mix(self.spkm.deref())?
|
||||||
.mix(peer.get(self).psk.secret())?;
|
.mix(peer.get(self).psk.secret())?;
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.init_handshake_mix_4,
|
||||||
|
&hs.core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// IHI8
|
// IHI8
|
||||||
protocol_section!("IHI8", {
|
protocol_section!("IHI8", {
|
||||||
hs.core.encrypt_and_mix(ih.auth.as_mut_slice(), &[])?;
|
hs.core.encrypt_and_mix(ih.auth.as_mut_slice(), &[])?;
|
||||||
|
TV::check_value(&test_values.init_hello_auth, &ih.auth);
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.init_handshake_mix_5,
|
||||||
|
&hs.core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update the handshake hash last (not changing any state on prior error
|
// Update the handshake hash last (not changing any state on prior error
|
||||||
peer.hs().insert(self, hs)?;
|
peer.hs().insert(self, hs)?;
|
||||||
|
|
||||||
Ok(peer)
|
Ok(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3471,6 +3653,27 @@ impl CryptoServer {
|
|||||||
rh: &mut RespHello,
|
rh: &mut RespHello,
|
||||||
keyed_hash: KeyedHash,
|
keyed_hash: KeyedHash,
|
||||||
) -> Result<PeerPtr> {
|
) -> Result<PeerPtr> {
|
||||||
|
self.handle_init_hello_with_test_vector::<TestVectorNOP>(ih, rh, keyed_hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generic variant of [`Self::handle_init_hello`] that allows selecting
|
||||||
|
/// a [`TestVector`] implementation.
|
||||||
|
///
|
||||||
|
/// This function is primarily intended for testing with different
|
||||||
|
/// test vector strategies. In production code, prefer using
|
||||||
|
/// [`Self::handle_init_hello`], which defaults to [`assert_tv::TestVectorNOP`].
|
||||||
|
///
|
||||||
|
/// Use this function with [`assert_tv::TestVectorActive`] in tests that require
|
||||||
|
/// applying actual test vectors. See the `tests::test_vector_crypto_server`
|
||||||
|
/// test for an example
|
||||||
|
pub fn handle_init_hello_with_test_vector<TV: TestVector>(
|
||||||
|
&mut self,
|
||||||
|
ih: &InitHello,
|
||||||
|
rh: &mut RespHello,
|
||||||
|
keyed_hash: KeyedHash,
|
||||||
|
) -> Result<PeerPtr> {
|
||||||
|
let test_values: HandleInitHelloTestValues = TV::initialize_values();
|
||||||
|
|
||||||
#[cfg(feature = "trace_bench")]
|
#[cfg(feature = "trace_bench")]
|
||||||
let _span_guard = rosenpass_util::trace_bench::trace().emit_span("handle_init_hello");
|
let _span_guard = rosenpass_util::trace_bench::trace().emit_span("handle_init_hello");
|
||||||
|
|
||||||
@@ -3487,11 +3690,19 @@ impl CryptoServer {
|
|||||||
protocol_section!("IHR4", {
|
protocol_section!("IHR4", {
|
||||||
core.mix(&ih.sidi)?.mix(&ih.epki)?;
|
core.mix(&ih.sidi)?.mix(&ih.epki)?;
|
||||||
});
|
});
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_ihr_4,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
|
|
||||||
// IHR5
|
// IHR5
|
||||||
protocol_section!("IHR5", {
|
protocol_section!("IHR5", {
|
||||||
core.decaps_and_mix(&StaticKem, self.sskm.secret(), self.spkm.deref(), &ih.sctr)?;
|
core.decaps_and_mix(&StaticKem, self.sskm.secret(), self.spkm.deref(), &ih.sctr)?;
|
||||||
});
|
});
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_ihr_5,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
|
|
||||||
// IHR6
|
// IHR6
|
||||||
let peer = protocol_section!("IHR6", {
|
let peer = protocol_section!("IHR6", {
|
||||||
@@ -3500,21 +3711,34 @@ impl CryptoServer {
|
|||||||
self.find_peer(peerid)
|
self.find_peer(peerid)
|
||||||
.with_context(|| format!("No such peer {peerid:?}."))?
|
.with_context(|| format!("No such peer {peerid:?}."))?
|
||||||
});
|
});
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_ihr_6,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
|
|
||||||
// IHR7
|
// IHR7
|
||||||
protocol_section!("IHR7", {
|
protocol_section!("IHR7", {
|
||||||
core.mix(peer.get(self).spkt.deref())?
|
core.mix(peer.get(self).spkt.deref())?
|
||||||
.mix(peer.get(self).psk.secret())?;
|
.mix(peer.get(self).psk.secret())?;
|
||||||
});
|
});
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_ihr_7,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
|
|
||||||
// IHR8
|
// IHR8
|
||||||
protocol_section!("IHR8", {
|
protocol_section!("IHR8", {
|
||||||
core.decrypt_and_mix(&mut [0u8; 0], &ih.auth)?;
|
core.decrypt_and_mix(&mut [0u8; 0], &ih.auth)?;
|
||||||
});
|
});
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_ihr_8,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
|
|
||||||
// RHR1
|
// RHR1
|
||||||
protocol_section!("RHR1", {
|
protocol_section!("RHR1", {
|
||||||
core.sidr.randomize();
|
core.sidr.randomize();
|
||||||
|
TV::expose_mut_value(&test_values.session_id, &mut core.sidr);
|
||||||
rh.sidi.copy_from_slice(core.sidi.as_ref());
|
rh.sidi.copy_from_slice(core.sidi.as_ref());
|
||||||
rh.sidr.copy_from_slice(core.sidr.as_ref());
|
rh.sidr.copy_from_slice(core.sidr.as_ref());
|
||||||
});
|
});
|
||||||
@@ -3522,28 +3746,59 @@ impl CryptoServer {
|
|||||||
// RHR3
|
// RHR3
|
||||||
protocol_section!("RHR3", {
|
protocol_section!("RHR3", {
|
||||||
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
core.mix(&rh.sidr)?.mix(&rh.sidi)?;
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_rhr_3,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// RHR4
|
// RHR4
|
||||||
protocol_section!("RHR4", {
|
protocol_section!("RHR4", {
|
||||||
core.encaps_and_mix(&EphemeralKem, &mut rh.ecti, &ih.epki)?;
|
use std::marker::PhantomData;
|
||||||
|
core.encaps_and_mix_with_test_vector(
|
||||||
|
&EphemeralKem,
|
||||||
|
&mut rh.ecti,
|
||||||
|
&ih.epki,
|
||||||
|
PhantomData::<TV>,
|
||||||
|
)?;
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_rhr_4,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// RHR5
|
// RHR5
|
||||||
protocol_section!("RHR5", {
|
protocol_section!("RHR5", {
|
||||||
core.encaps_and_mix(&StaticKem, &mut rh.scti, peer.get(self).spkt.deref())?;
|
use std::marker::PhantomData;
|
||||||
|
core.encaps_and_mix_with_test_vector(
|
||||||
|
&StaticKem,
|
||||||
|
&mut rh.scti,
|
||||||
|
peer.get(self).spkt.deref(),
|
||||||
|
PhantomData::<TV>,
|
||||||
|
)?;
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_rhr_5,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// RHR6
|
// RHR6
|
||||||
protocol_section!("RHR6", {
|
protocol_section!("RHR6", {
|
||||||
core.store_biscuit(self, peer, &mut rh.biscuit)?;
|
core.store_biscuit_with_test_vector::<TV>(self, peer, &mut rh.biscuit)?;
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_rhr_6,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// RHR7
|
// RHR7
|
||||||
protocol_section!("RHR7", {
|
protocol_section!("RHR7", {
|
||||||
core.encrypt_and_mix(&mut rh.auth, &[])?;
|
core.encrypt_and_mix(&mut rh.auth, &[])?;
|
||||||
|
TV::check_value(
|
||||||
|
&test_values.chaining_key_rhr_7,
|
||||||
|
&core.ck.clone().danger_into_secret(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(peer)
|
Ok(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
176
rosenpass/src/protocol/test_vector_sets.rs
Normal file
176
rosenpass/src/protocol/test_vector_sets.rs
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
//! Test vector definitions for derandomizing protocol internals.
|
||||||
|
//!
|
||||||
|
//! This module contains the definitions of internal test vector values used by
|
||||||
|
//! `CryptoServer` and the functions in `protocol.rs`. These values allow the
|
||||||
|
//! protocol implementation to be derandomized for deterministic testing and
|
||||||
|
//! reproducible behavior across runs.
|
||||||
|
//!
|
||||||
|
//! For an example of a test that uses these test vector values, see:
|
||||||
|
//! `rosenpass/tests/test_vector_crypto_server.rs`.
|
||||||
|
|
||||||
|
use crate::msgs::SESSION_ID_LEN;
|
||||||
|
use crate::protocol::basic_types::SessionId;
|
||||||
|
use crate::protocol::constants::COOKIE_VALUE_LEN;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use assert_tv::TestValue;
|
||||||
|
use assert_tv::TestVectorSet;
|
||||||
|
use base64::Engine;
|
||||||
|
use rosenpass_cipher_traits::primitives::{Aead, Kem};
|
||||||
|
use rosenpass_ciphers::{EphemeralKem, XAead, KEY_LEN};
|
||||||
|
use rosenpass_secret_memory::{Public, PublicBox, Secret};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
#[derive(TestVectorSet)]
|
||||||
|
pub struct EncapsAndMixTestValues<const KEM_CT_LEN: usize, const KEM_SHK_LEN: usize> {
|
||||||
|
#[test_vec(serialize_with = "serialize_byte_arr")]
|
||||||
|
#[test_vec(deserialize_with = "deserialize_byte_arr")]
|
||||||
|
pub ct: TestValue<[u8; KEM_CT_LEN]>,
|
||||||
|
pub shk: TestValue<Secret<KEM_SHK_LEN>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(TestVectorSet)]
|
||||||
|
pub struct StoreBiscuitTestValues {
|
||||||
|
#[test_vec(serialize_with = "serialize_byte_vec")]
|
||||||
|
#[test_vec(deserialize_with = "deserialize_byte_vec")]
|
||||||
|
pub biscuit: TestValue<Vec<u8>>,
|
||||||
|
|
||||||
|
pub n: TestValue<Public<{ XAead::NONCE_LEN }>>,
|
||||||
|
|
||||||
|
#[test_vec(serialize_with = "serialize_byte_vec")]
|
||||||
|
#[test_vec(deserialize_with = "deserialize_byte_vec")]
|
||||||
|
pub biscuit_ct: TestValue<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(TestVectorSet)]
|
||||||
|
pub struct HandleInitiationTestValues {
|
||||||
|
#[test_vec(name = "hs.cookie_value.value")]
|
||||||
|
pub init_handshake_cookie: TestValue<Secret<COOKIE_VALUE_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "hs.core.sidi")]
|
||||||
|
pub init_handshake_sidi: TestValue<Public<SESSION_ID_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "hs.eski")]
|
||||||
|
pub init_handshake_eski: TestValue<Secret<{ EphemeralKem::SK_LEN }>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "hs.core.ck")]
|
||||||
|
pub init_handshake_epki: TestValue<Public<{ EphemeralKem::PK_LEN }>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "hs.core.ck 1")]
|
||||||
|
pub init_handshake_mix_1: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "hs.core.ck 2")]
|
||||||
|
pub init_handshake_mix_2: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "ih.pidic")]
|
||||||
|
#[test_vec(serialize_with = "serialize_byte_arr")]
|
||||||
|
#[test_vec(deserialize_with = "deserialize_byte_arr")]
|
||||||
|
pub init_hello_pidic: TestValue<[u8; rosenpass_ciphers::Aead::TAG_LEN + 32]>,
|
||||||
|
|
||||||
|
#[test_vec(name = "hs.core.ck 3")]
|
||||||
|
pub init_handshake_mix_3: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "hs.core.ck 4")]
|
||||||
|
pub init_handshake_mix_4: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "ih.auth")]
|
||||||
|
#[test_vec(serialize_with = "serialize_byte_arr")]
|
||||||
|
#[test_vec(deserialize_with = "deserialize_byte_arr")]
|
||||||
|
pub init_hello_auth: TestValue<[u8; rosenpass_ciphers::Aead::TAG_LEN]>,
|
||||||
|
|
||||||
|
#[test_vec(name = "hs.core.ck 5")]
|
||||||
|
pub init_handshake_mix_5: TestValue<Secret<KEY_LEN>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(TestVectorSet)]
|
||||||
|
pub struct HandleInitHelloTestValues {
|
||||||
|
#[test_vec(name = "chaining_key_ihr IHR 4")]
|
||||||
|
pub chaining_key_ihr_4: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr IHR 5")]
|
||||||
|
pub chaining_key_ihr_5: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr IHR 6")]
|
||||||
|
pub chaining_key_ihr_6: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr IHR 7")]
|
||||||
|
pub chaining_key_ihr_7: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr IHR 8")]
|
||||||
|
pub chaining_key_ihr_8: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "session_id")]
|
||||||
|
pub session_id: TestValue<SessionId>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr RHR 3")]
|
||||||
|
pub chaining_key_rhr_3: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr RHR 4")]
|
||||||
|
pub chaining_key_rhr_4: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr RHR 5")]
|
||||||
|
pub chaining_key_rhr_5: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr RHR 6")]
|
||||||
|
pub chaining_key_rhr_6: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "chaining_key_ihr RHR 7")]
|
||||||
|
pub chaining_key_rhr_7: TestValue<Secret<KEY_LEN>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(TestVectorSet)]
|
||||||
|
pub struct InitHandshakeTestValues {
|
||||||
|
#[test_vec(serialize_with = "serialize_byte_vec")]
|
||||||
|
#[test_vec(deserialize_with = "deserialize_byte_vec")]
|
||||||
|
pub msg: TestValue<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(TestVectorSet)]
|
||||||
|
pub struct CycledBiscuitSecretKeyTestValues {
|
||||||
|
#[test_vec(name = "CryptoServer::biscuit_key[r]")]
|
||||||
|
#[test_vec(description = "Biscuit key after being cycled")]
|
||||||
|
pub cycled_biscuit_secret_key: TestValue<Secret<KEY_LEN>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialization helpers for raw byte arrays and vectors.
|
||||||
|
//
|
||||||
|
// These functions provide a small bridge implementation to serialize/deserialize
|
||||||
|
// standard values that do not carry serde implementations with the desired
|
||||||
|
// base64 format by default. They are used by the test vector machinery to
|
||||||
|
// encode `[u8; N]` and `Vec<u8>` values consistently.
|
||||||
|
|
||||||
|
/// Serialize a byte array as a base64 JSON string (bridge for `[u8; N]`).
|
||||||
|
pub fn serialize_byte_arr<const N: usize>(observed_value: &[u8; N]) -> anyhow::Result<Value> {
|
||||||
|
let encoded = base64::engine::general_purpose::STANDARD.encode(observed_value);
|
||||||
|
Ok(Value::String(encoded))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize a base64 JSON string into a byte array (bridge for `[u8; N]`).
|
||||||
|
pub fn deserialize_byte_arr<const N: usize>(value: &Value) -> anyhow::Result<[u8; N]> {
|
||||||
|
let value: &str = value
|
||||||
|
.as_str()
|
||||||
|
.ok_or_else(|| anyhow!("Unexpected value, expected string"))?;
|
||||||
|
let decoded = base64::engine::general_purpose::STANDARD
|
||||||
|
.decode(value.as_bytes())
|
||||||
|
.map_err(|e| anyhow!("Couldn't decode value: {e}"))?;
|
||||||
|
decoded
|
||||||
|
.as_slice()
|
||||||
|
.try_into()
|
||||||
|
.map_err(|e| anyhow!("Couldn't convert to array of size={}: {e}", N))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialize a byte vector as a base64 JSON string (bridge for `Vec<u8>`).
|
||||||
|
pub fn serialize_byte_vec(observed_value: &Vec<u8>) -> anyhow::Result<Value> {
|
||||||
|
let encoded = base64::engine::general_purpose::STANDARD.encode(observed_value);
|
||||||
|
Ok(Value::String(encoded))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserialize a base64 JSON string into a byte vector (bridge for `Vec<u8>`).
|
||||||
|
pub fn deserialize_byte_vec(value: &Value) -> anyhow::Result<Vec<u8>> {
|
||||||
|
let value: &str = value
|
||||||
|
.as_str()
|
||||||
|
.ok_or_else(|| anyhow!("Unexpected value, expected string"))?;
|
||||||
|
let decoded = base64::engine::general_purpose::STANDARD
|
||||||
|
.decode(value.as_bytes())
|
||||||
|
.map_err(|e| anyhow!("Couldn't decode value: {e}"))?;
|
||||||
|
Ok(decoded)
|
||||||
|
}
|
||||||
180
rosenpass/tests/test_vector_crypto_server.rs
Normal file
180
rosenpass/tests/test_vector_crypto_server.rs
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
//! # Deterministic protocol test based on captured internal randomness
|
||||||
|
//!
|
||||||
|
//! This test validates the rosenpass protocol implementation by recording all internal randomness
|
||||||
|
//! during execution and saving it to a test vector file (`crypto_server_test_vector_1.toml`).
|
||||||
|
//! On subsequent runs, the test replays this randomness to enforce deterministic behavior,
|
||||||
|
//! making any changes to the protocol's internal logic observable through test failures.
|
||||||
|
//!
|
||||||
|
//! ## Reinitializing the Test Vector
|
||||||
|
//!
|
||||||
|
//! If the test fails due to a mismatch between current output and the recorded test vector,
|
||||||
|
//! it likely indicates a change in implementation. To accept and re-record the new behavior,
|
||||||
|
//! re-run the test in initialization mode by setting the environment variable:
|
||||||
|
//!
|
||||||
|
//! ```bash
|
||||||
|
//! TEST_MODE=init cargo test crypto_server_test_vector_1
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
use assert_tv::{test_vec_case, TestValue, TestVector, TestVectorActive, TestVectorSet};
|
||||||
|
use rosenpass::protocol::basic_types::{MsgBuf, SPk, SSk, SymKey};
|
||||||
|
use rosenpass::protocol::osk_domain_separator::OskDomainSeparator;
|
||||||
|
use rosenpass::protocol::test_vector_sets::deserialize_byte_vec;
|
||||||
|
use rosenpass::protocol::test_vector_sets::serialize_byte_vec;
|
||||||
|
use rosenpass::protocol::{CryptoServer, PeerPtr, ProtocolVersion};
|
||||||
|
use rosenpass_cipher_traits::primitives::Kem;
|
||||||
|
use rosenpass_ciphers::StaticKem;
|
||||||
|
use rosenpass_secret_memory::policy::*;
|
||||||
|
use rosenpass_secret_memory::{PublicBox, Secret};
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
|
||||||
|
use rosenpass::protocol::constants::COOKIE_SECRET_LEN;
|
||||||
|
use rosenpass_ciphers::KEY_LEN;
|
||||||
|
|
||||||
|
#[derive(TestVectorSet)]
|
||||||
|
pub struct TestCaseValues {
|
||||||
|
#[test_vec(name = "peer_a_sk")]
|
||||||
|
#[test_vec(description = "test setup: peer a secret key")]
|
||||||
|
#[test_vec(offload = true)]
|
||||||
|
peer_a_sk: TestValue<Secret<{ StaticKem::SK_LEN }>>,
|
||||||
|
#[test_vec(name = "peer_a_pk")]
|
||||||
|
#[test_vec(description = "test setup: peer a public key")]
|
||||||
|
#[test_vec(offload = true)]
|
||||||
|
peer_a_pk: TestValue<PublicBox<{ StaticKem::PK_LEN }>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "peer_b_sk")]
|
||||||
|
#[test_vec(description = "test setup: peer b secret key")]
|
||||||
|
#[test_vec(offload = true)]
|
||||||
|
peer_b_sk: TestValue<Secret<{ StaticKem::SK_LEN }>>,
|
||||||
|
#[test_vec(name = "peer_b_pk")]
|
||||||
|
#[test_vec(description = "test setup: peer b public key")]
|
||||||
|
#[test_vec(offload = true)]
|
||||||
|
peer_b_pk: TestValue<PublicBox<{ StaticKem::PK_LEN }>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "psk")]
|
||||||
|
#[test_vec(description = "pre-shared key")]
|
||||||
|
psk: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "message")]
|
||||||
|
#[test_vec(description = "message exchanged by the protocol parties")]
|
||||||
|
#[test_vec(serialize_with = "serialize_byte_vec")]
|
||||||
|
#[test_vec(deserialize_with = "deserialize_byte_vec")]
|
||||||
|
#[test_vec(offload = true)]
|
||||||
|
message: TestValue<Vec<u8>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "exchanged_key")]
|
||||||
|
#[test_vec(description = "final exchanged key")]
|
||||||
|
exchanged_key: TestValue<Secret<KEY_LEN>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(TestVectorSet)]
|
||||||
|
struct CryptoServerTestValues {
|
||||||
|
#[test_vec(name = "CryptoServer::cookie_secrets[0]")]
|
||||||
|
cookie_secret_0: TestValue<Secret<COOKIE_SECRET_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "CryptoServer::cookie_secrets[1]")]
|
||||||
|
cookie_secret_1: TestValue<Secret<COOKIE_SECRET_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "CryptoServer::biscuit_keys[0]")]
|
||||||
|
biscuit_key_0: TestValue<Secret<KEY_LEN>>,
|
||||||
|
|
||||||
|
#[test_vec(name = "CryptoServer::biscuit_keys[1]")]
|
||||||
|
biscuit_key_1: TestValue<Secret<KEY_LEN>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_vec_case(format = "toml")]
|
||||||
|
fn crypto_server_test_vector_1() -> anyhow::Result<()> {
|
||||||
|
type TV = TestVectorActive;
|
||||||
|
let test_values: TestCaseValues = TV::initialize_values();
|
||||||
|
|
||||||
|
// Set security policy for storing secrets
|
||||||
|
secret_policy_try_use_memfd_secrets();
|
||||||
|
|
||||||
|
// initialize secret and public key for peer a ...
|
||||||
|
let (mut peer_a_sk, mut peer_a_pk) = gen_keypair::<TV>();
|
||||||
|
|
||||||
|
TV::expose_mut_value(&test_values.peer_a_sk, &mut peer_a_sk);
|
||||||
|
TV::expose_mut_value(&test_values.peer_a_pk, &mut peer_a_pk);
|
||||||
|
|
||||||
|
// ... and for peer b
|
||||||
|
let (mut peer_b_sk, mut peer_b_pk) = gen_keypair::<TV>();
|
||||||
|
|
||||||
|
TV::expose_mut_value(&test_values.peer_b_sk, &mut peer_b_sk);
|
||||||
|
TV::expose_mut_value(&test_values.peer_b_pk, &mut peer_b_pk);
|
||||||
|
|
||||||
|
// initialize server and a pre-shared key
|
||||||
|
let psk = TV::expose_value(&test_values.psk, SymKey::random());
|
||||||
|
|
||||||
|
let mut a = CryptoServer::new(peer_a_sk, peer_a_pk.clone());
|
||||||
|
de_randomize_time_base_cookie_secrets::<TV>(&mut a);
|
||||||
|
|
||||||
|
let mut b = CryptoServer::new(peer_b_sk, peer_b_pk.clone());
|
||||||
|
de_randomize_time_base_cookie_secrets::<TV>(&mut b);
|
||||||
|
|
||||||
|
// introduce peers to each other
|
||||||
|
a.add_peer(
|
||||||
|
Some(psk.clone()),
|
||||||
|
peer_b_pk,
|
||||||
|
ProtocolVersion::V03,
|
||||||
|
OskDomainSeparator::default(),
|
||||||
|
)?;
|
||||||
|
b.add_peer(
|
||||||
|
Some(psk),
|
||||||
|
peer_a_pk,
|
||||||
|
ProtocolVersion::V03,
|
||||||
|
OskDomainSeparator::default(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// declare buffers for message exchange
|
||||||
|
let (mut a_buf, mut b_buf) = (MsgBuf::zero(), MsgBuf::zero());
|
||||||
|
|
||||||
|
// let a initiate a handshake
|
||||||
|
let mut maybe_len =
|
||||||
|
Some(a.initiate_handshake_with_test_vector::<TV>(PeerPtr(0), a_buf.as_mut_slice())?);
|
||||||
|
|
||||||
|
// let a and b communicate
|
||||||
|
while let Some(len) = maybe_len {
|
||||||
|
TV::check_value(&test_values.message, &a_buf[..len].to_vec());
|
||||||
|
maybe_len = b
|
||||||
|
.handle_msg_with_test_vector::<TV>(&a_buf[..len], &mut b_buf[..])?
|
||||||
|
.resp;
|
||||||
|
std::mem::swap(&mut a, &mut b);
|
||||||
|
std::mem::swap(&mut a_buf, &mut b_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// all done! Extract the shared keys and ensure they are identical
|
||||||
|
let a_key = a.osk(PeerPtr(0))?;
|
||||||
|
let b_key = b.osk(PeerPtr(0))?;
|
||||||
|
assert_eq!(
|
||||||
|
a_key.secret(),
|
||||||
|
b_key.secret(),
|
||||||
|
"the key exchanged failed to establish a shared secret"
|
||||||
|
);
|
||||||
|
|
||||||
|
TV::check_value(&test_values.exchanged_key, &a_key);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn gen_keypair<TV: TestVector>() -> (SSk, SPk) {
|
||||||
|
let (mut sk, mut pk) = (SSk::zero(), SPk::zero());
|
||||||
|
StaticKem
|
||||||
|
.keygen(sk.secret_mut(), pk.deref_mut())
|
||||||
|
.expect("Error generating keypair");
|
||||||
|
(sk, pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn de_randomize_time_base_cookie_secrets<TV: TestVector>(cs: &mut CryptoServer) {
|
||||||
|
let test_values: CryptoServerTestValues = TV::initialize_values();
|
||||||
|
|
||||||
|
TV::expose_mut_value(
|
||||||
|
&test_values.cookie_secret_0,
|
||||||
|
&mut cs.cookie_secrets[0].value,
|
||||||
|
);
|
||||||
|
|
||||||
|
TV::expose_mut_value(
|
||||||
|
&test_values.cookie_secret_1,
|
||||||
|
&mut cs.cookie_secrets[1].value,
|
||||||
|
);
|
||||||
|
|
||||||
|
TV::expose_mut_value(&test_values.biscuit_key_0, &mut cs.biscuit_keys[0].value);
|
||||||
|
|
||||||
|
TV::expose_mut_value(&test_values.biscuit_key_1, &mut cs.biscuit_keys[1].value);
|
||||||
|
}
|
||||||
@@ -19,6 +19,10 @@ rand = { workspace = true }
|
|||||||
memsec = { workspace = true }
|
memsec = { workspace = true }
|
||||||
allocator-api2 = { workspace = true }
|
allocator-api2 = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
|
assert_tv = { workspace = true }
|
||||||
|
base64 = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
allocator-api2-tests = { workspace = true }
|
allocator-api2-tests = { workspace = true }
|
||||||
|
|||||||
@@ -47,4 +47,6 @@ mod secret;
|
|||||||
pub use crate::secret::Secret;
|
pub use crate::secret::Secret;
|
||||||
|
|
||||||
pub mod policy;
|
pub mod policy;
|
||||||
|
mod serialization;
|
||||||
|
|
||||||
pub use crate::policy::*;
|
pub use crate::policy::*;
|
||||||
|
|||||||
214
secret-memory/src/serialization.rs
Normal file
214
secret-memory/src/serialization.rs
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
use crate::{Public, PublicBox, Secret};
|
||||||
|
use base64::Engine;
|
||||||
|
use serde::de::{Error as DeError, Visitor};
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
fn encode_b64(bytes: &[u8]) -> String {
|
||||||
|
base64::engine::general_purpose::STANDARD.encode(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_b64(s: &str) -> Result<Vec<u8>, String> {
|
||||||
|
base64::engine::general_purpose::STANDARD
|
||||||
|
.decode(s.as_bytes())
|
||||||
|
.map_err(|e| format!("Couldn't decode base64: {e}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
struct B64BytesVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for B64BytesVisitor {
|
||||||
|
type Value = Vec<u8>;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "a base64-encoded string")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E: DeError>(self, v: &str) -> Result<Self::Value, E> {
|
||||||
|
decode_b64(v).map_err(E::custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E: DeError>(self, v: String) -> Result<Self::Value, E> {
|
||||||
|
self.visit_str(&v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Serialize for Secret<N> {
|
||||||
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
serializer.serialize_str(&encode_b64(self.secret()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, const N: usize> Deserialize<'de> for Secret<N> {
|
||||||
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
|
let bytes: Vec<u8> = deserializer.deserialize_string(B64BytesVisitor)?;
|
||||||
|
if bytes.len() != N {
|
||||||
|
return Err(D::Error::custom(format!(
|
||||||
|
"Unexpected length: got {}, expected {}",
|
||||||
|
bytes.len(),
|
||||||
|
N
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
// Copies from heap bytes into the internal storage;
|
||||||
|
// no large stack temporaries.
|
||||||
|
Ok(Secret::<N>::from_slice(bytes.as_slice()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Serialize for Public<N> {
|
||||||
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
serializer.serialize_str(&encode_b64(&self.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, const N: usize> Deserialize<'de> for Public<N> {
|
||||||
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
|
let bytes: Vec<u8> = deserializer.deserialize_string(B64BytesVisitor)?;
|
||||||
|
if bytes.len() != N {
|
||||||
|
return Err(D::Error::custom(format!(
|
||||||
|
"Unexpected length: got {}, expected {}",
|
||||||
|
bytes.len(),
|
||||||
|
N
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
Ok(Public::<N>::from_slice(bytes.as_slice()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> Serialize for PublicBox<N> {
|
||||||
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
serializer.serialize_str(&encode_b64(self.inner.value.as_slice()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, const N: usize> Deserialize<'de> for PublicBox<N> {
|
||||||
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
|
let bytes: Vec<u8> = deserializer.deserialize_string(B64BytesVisitor)?;
|
||||||
|
if bytes.len() != N {
|
||||||
|
return Err(D::Error::custom(format!(
|
||||||
|
"Unexpected length: got {}, expected {}",
|
||||||
|
bytes.len(),
|
||||||
|
N
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
// Allocate Public<N> on the heap and copy bytes into it
|
||||||
|
let mut inner = Box::new(Public::<N>::zero());
|
||||||
|
inner.copy_from_slice(bytes.as_slice());
|
||||||
|
Ok(PublicBox { inner })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::secret_policy_use_only_malloc_secrets;
|
||||||
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
|
// Generic helper: serialize to JSON, then deserialize back.
|
||||||
|
fn roundtrip_json<T>(value: &T) -> T
|
||||||
|
where
|
||||||
|
T: Serialize + DeserializeOwned,
|
||||||
|
{
|
||||||
|
let json = serde_json::to_string(value).expect("serialize");
|
||||||
|
serde_json::from_str::<T>(&json).expect("deserialize")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test_init_secret_memory_policy() {
|
||||||
|
secret_policy_use_only_malloc_secrets();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn secret_roundtrip_json() {
|
||||||
|
test_init_secret_memory_policy();
|
||||||
|
const N: usize = 32;
|
||||||
|
let src = [0xABu8; N];
|
||||||
|
let original = Secret::<N>::from_slice(&src);
|
||||||
|
let recovered: Secret<N> = roundtrip_json(&original);
|
||||||
|
assert_eq!(
|
||||||
|
original.secret(),
|
||||||
|
recovered.secret(),
|
||||||
|
"Secret bytes must match after roundtrip"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn public_roundtrip_json() {
|
||||||
|
const N: usize = 48;
|
||||||
|
let src = [0x11u8; N];
|
||||||
|
let original = Public::<N>::from_slice(&src);
|
||||||
|
let json = serde_json::to_string(&original).expect("serialize");
|
||||||
|
let recovered: Public<N> = serde_json::from_str(&json).expect("deserialize");
|
||||||
|
// Avoid relying on private fields: compare canonical serialization strings.
|
||||||
|
let json2 = serde_json::to_string(&recovered).expect("re-serialize");
|
||||||
|
assert_eq!(
|
||||||
|
json, json2,
|
||||||
|
"Public must serialize identically after roundtrip"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn public_box_roundtrip_json() {
|
||||||
|
const N: usize = 64;
|
||||||
|
let src = [0x7Fu8; N];
|
||||||
|
|
||||||
|
let original = PublicBox::<N>::new(src);
|
||||||
|
|
||||||
|
let json = serde_json::to_string(&original).expect("serialize");
|
||||||
|
let recovered: PublicBox<N> = serde_json::from_str(&json).expect("deserialize");
|
||||||
|
let json2 = serde_json::to_string(&recovered).expect("re-serialize");
|
||||||
|
assert_eq!(
|
||||||
|
json, json2,
|
||||||
|
"PublicBox must serialize identically after roundtrip"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn secret_len_mismatch_is_error() {
|
||||||
|
test_init_secret_memory_policy();
|
||||||
|
const N_SMALL: usize = 16;
|
||||||
|
const N_BIG: usize = 32;
|
||||||
|
|
||||||
|
let src = [0x55u8; N_SMALL];
|
||||||
|
let small = Secret::<N_SMALL>::from_slice(&src);
|
||||||
|
let json = serde_json::to_string(&small).expect("serialize");
|
||||||
|
|
||||||
|
// Attempt to deserialize a 16-byte payload into Secret<32> should fail.
|
||||||
|
let res = serde_json::from_str::<Secret<N_BIG>>(&json);
|
||||||
|
assert!(
|
||||||
|
res.is_err(),
|
||||||
|
"Deserializing into a larger fixed size must error"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn public_len_mismatch_is_error() {
|
||||||
|
const N_SMALL: usize = 24;
|
||||||
|
const N_BIG: usize = 40;
|
||||||
|
|
||||||
|
let src = [0x33u8; N_SMALL];
|
||||||
|
let small = Public::<N_SMALL>::from_slice(&src);
|
||||||
|
let json = serde_json::to_string(&small).expect("serialize");
|
||||||
|
|
||||||
|
let res = serde_json::from_str::<Public<N_BIG>>(&json);
|
||||||
|
assert!(
|
||||||
|
res.is_err(),
|
||||||
|
"Deserializing into a larger fixed size must error"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn public_box_len_mismatch_is_error() {
|
||||||
|
const N_SMALL: usize = 8;
|
||||||
|
const N_BIG: usize = 12;
|
||||||
|
|
||||||
|
let src = [0xE0u8; N_SMALL];
|
||||||
|
let small = PublicBox::<N_SMALL>::new(src);
|
||||||
|
let json = serde_json::to_string(&small).expect("serialize");
|
||||||
|
|
||||||
|
let res = serde_json::from_str::<PublicBox<N_BIG>>(&json);
|
||||||
|
assert!(
|
||||||
|
res.is_err(),
|
||||||
|
"Deserializing into a different fixed size must error"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,27 @@
|
|||||||
|
|
||||||
# cargo-vet audits file
|
# cargo-vet audits file
|
||||||
|
|
||||||
[audits]
|
[[audits.assert_tv]]
|
||||||
|
who = "Amin Faez <amin.faez.inbox@gmail.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
version = "0.5.1"
|
||||||
|
|
||||||
|
[[audits.assert_tv]]
|
||||||
|
who = "Amin Faez <amin.faez.inbox@gmail.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
version = "0.5.1"
|
||||||
|
|
||||||
|
[[audits.assert_tv_macros]]
|
||||||
|
who = "Amin Faez <amin.faez.inbox@gmail.com>"
|
||||||
|
criteria = "safe-to-run"
|
||||||
|
version = "0.5.1"
|
||||||
|
|
||||||
|
[[audits.ryu]]
|
||||||
|
who = "Amin Faez <amin.faez.inbox@gmail.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
version = "1.0.10"
|
||||||
|
|
||||||
|
[[audits.serde_json]]
|
||||||
|
who = "Amin Faez <amin.faez.inbox@gmail.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
version = "1.0.138"
|
||||||
|
|||||||
@@ -77,6 +77,14 @@ criteria = "safe-to-deploy"
|
|||||||
version = "1.0.98"
|
version = "1.0.98"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
|
[[exemptions.assert_tv]]
|
||||||
|
version = "0.6.4"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
|
[[exemptions.assert_tv_macros]]
|
||||||
|
version = "0.6.4"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
[[exemptions.atomic-polyfill]]
|
[[exemptions.atomic-polyfill]]
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
@@ -597,10 +605,6 @@ criteria = "safe-to-deploy"
|
|||||||
version = "0.38.44"
|
version = "0.38.44"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
[[exemptions.ryu]]
|
|
||||||
version = "1.0.19"
|
|
||||||
criteria = "safe-to-deploy"
|
|
||||||
|
|
||||||
[[exemptions.scc]]
|
[[exemptions.scc]]
|
||||||
version = "2.3.3"
|
version = "2.3.3"
|
||||||
criteria = "safe-to-run"
|
criteria = "safe-to-run"
|
||||||
@@ -621,6 +625,10 @@ criteria = "safe-to-deploy"
|
|||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
|
[[exemptions.serde_yaml]]
|
||||||
|
version = "0.9.34+deprecated"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
[[exemptions.serial_test]]
|
[[exemptions.serial_test]]
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
criteria = "safe-to-run"
|
criteria = "safe-to-run"
|
||||||
@@ -721,6 +729,10 @@ criteria = "safe-to-deploy"
|
|||||||
version = "1.0.17"
|
version = "1.0.17"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
|
[[exemptions.unsafe-libyaml]]
|
||||||
|
version = "0.2.11"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
[[exemptions.uuid]]
|
[[exemptions.uuid]]
|
||||||
version = "1.14.0"
|
version = "1.14.0"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
@@ -952,3 +964,15 @@ criteria = "safe-to-deploy"
|
|||||||
[[exemptions.zerocopy-derive]]
|
[[exemptions.zerocopy-derive]]
|
||||||
version = "0.8.24"
|
version = "0.8.24"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
|
[[exemptions.zstd]]
|
||||||
|
version = "0.13.3"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
|
[[exemptions.zstd-safe]]
|
||||||
|
version = "7.2.4"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
|
||||||
|
[[exemptions.zstd-sys]]
|
||||||
|
version = "2.0.15+zstd.1.5.7"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
|||||||
@@ -59,6 +59,17 @@ who = "Nick Fitzgerald <fitzgen@gmail.com>"
|
|||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
|
||||||
|
[[audits.bytecode-alliance.audits.base64]]
|
||||||
|
who = "Pat Hickey <phickey@fastly.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
version = "0.21.0"
|
||||||
|
notes = "This crate has no dependencies, no build.rs, and contains no unsafe code."
|
||||||
|
|
||||||
|
[[audits.bytecode-alliance.audits.base64]]
|
||||||
|
who = "Andrew Brown <andrew.brown@intel.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.21.3 -> 0.22.1"
|
||||||
|
|
||||||
[[audits.bytecode-alliance.audits.bitflags]]
|
[[audits.bytecode-alliance.audits.bitflags]]
|
||||||
who = "Jamey Sharp <jsharp@fastly.com>"
|
who = "Jamey Sharp <jsharp@fastly.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
@@ -1138,6 +1149,21 @@ criteria = "safe-to-run"
|
|||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
|
aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT"
|
||||||
|
|
||||||
|
[[audits.isrg.audits.base64]]
|
||||||
|
who = "Tim Geoghegan <timg@letsencrypt.org>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.21.0 -> 0.21.1"
|
||||||
|
|
||||||
|
[[audits.isrg.audits.base64]]
|
||||||
|
who = "Brandon Pitman <bran@bran.land>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.21.1 -> 0.21.2"
|
||||||
|
|
||||||
|
[[audits.isrg.audits.base64]]
|
||||||
|
who = "David Cook <dcook@divviup.org>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.21.2 -> 0.21.3"
|
||||||
|
|
||||||
[[audits.isrg.audits.block-buffer]]
|
[[audits.isrg.audits.block-buffer]]
|
||||||
who = "David Cook <dcook@divviup.org>"
|
who = "David Cook <dcook@divviup.org>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
@@ -1567,6 +1593,24 @@ version = "1.1.0"
|
|||||||
notes = "Straightforward crate with no unsafe code, does what it says on the tin."
|
notes = "Straightforward crate with no unsafe code, does what it says on the tin."
|
||||||
aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
|
aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
|
||||||
|
|
||||||
|
[[audits.mozilla.audits.ryu]]
|
||||||
|
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "1.0.10 -> 1.0.11"
|
||||||
|
aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
|
||||||
|
|
||||||
|
[[audits.mozilla.audits.ryu]]
|
||||||
|
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "1.0.11 -> 1.0.12"
|
||||||
|
aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
|
||||||
|
|
||||||
|
[[audits.mozilla.audits.ryu]]
|
||||||
|
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "1.0.12 -> 1.0.19"
|
||||||
|
aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
|
||||||
|
|
||||||
[[audits.mozilla.audits.semver]]
|
[[audits.mozilla.audits.semver]]
|
||||||
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
|
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|||||||
Reference in New Issue
Block a user