From 87ed678913ea74e9377c465717e0cad813cc22a8 Mon Sep 17 00:00:00 2001 From: Wojciech Ozga Date: Thu, 17 Sep 2026 13:05:30 +0000 Subject: [PATCH] Introduce heapless where possible to reduce runtime heap allocations Signed-off-by: Wojciech Ozga --- security-monitor/Cargo.lock | 348 ++++++++------ security-monitor/Cargo.toml | 3 + .../rust-crates/riscv_cove_tap/Cargo.toml | 3 +- .../rust-crates/riscv_cove_tap/src/error.rs | 8 + .../rust-crates/riscv_cove_tap/src/parser.rs | 124 +++-- .../riscv_cove_tap/src/serializer.rs | 164 ++++--- .../rust-crates/riscv_cove_tap/src/spec.rs | 195 +++++--- .../confidential_flow/finite_state_machine.rs | 4 +- .../riscv/extensions/vector_unit.rs | 1 - .../riscv/general_purpose_registers.rs | 1 - .../core/architecture/riscv/mmu/page_table.rs | 2 +- .../core/control_data/confidential_hart.rs | 2 +- .../src/core/control_data/confidential_vm.rs | 68 +-- .../src/core/hardware_setup/mod.rs | 15 +- .../src/core/initialization/mod.rs | 30 +- .../confidential_memory_address.rs | 3 +- .../non_confidential_memory_address.rs | 5 +- .../src/core/page_allocator/allocator.rs | 60 ++- .../src/core/page_allocator/page.rs | 4 +- security-monitor/src/debug.rs | 3 +- security-monitor/src/lib.rs | 1 - .../promote_to_confidential_vm.rs | 48 +- tools/cove_tap_tool/Cargo.lock | 433 ++++++++++-------- tools/cove_tap_tool/Cargo.toml | 1 + tools/cove_tap_tool/src/generate.rs | 123 +++-- 25 files changed, 1000 insertions(+), 649 deletions(-) diff --git a/security-monitor/Cargo.lock b/security-monitor/Cargo.lock index 5850a31c..e0223f30 100644 --- a/security-monitor/Cargo.lock +++ b/security-monitor/Cargo.lock @@ -4,53 +4,53 @@ version = 4 [[package]] name = "aead" -version = "0.6.0-rc.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" +checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99" dependencies = [ - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.2", "inout", ] [[package]] name = "aes" -version = "0.9.0-rc.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e713c57c2a2b19159e7be83b9194600d7e8eb3b7c2cd67e671adf47ce189a05" +checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" dependencies = [ - "cfg-if", "cipher", - "cpufeatures", + "cpubits", + "cpufeatures 0.3.1", ] [[package]] name = "aes-gcm" -version = "0.11.0-rc.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686ba04dc80c816104c96cd7782b748f6ad58c5dd4ee619ff3258cf68e83d54" +checksum = "7f2b8006a0c83f52b62ba44a97b58bf76fe2f70a329e588f67f89691d93d498f" dependencies = [ "aead", "aes", "cipher", "ctr", + "ctutils", "ghash", - "subtle", ] [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "bindgen" @@ -69,14 +69,14 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.107", + "syn 2.0.119", ] [[package]] name = "bitflags" -version = "2.10.0" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "block-buffer" @@ -84,18 +84,24 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.9", + "generic-array 0.14.7", ] [[package]] name = "block-buffer" -version = "0.11.0-rc.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ - "hybrid-array 0.4.5", + "hybrid-array 0.4.15", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cexpr" version = "0.6.0" @@ -107,32 +113,44 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "cipher" -version = "0.5.0-rc.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" dependencies = [ - "block-buffer 0.11.0-rc.5", - "crypto-common 0.2.0-rc.4", + "block-buffer 0.12.1", + "crypto-common 0.2.2", "inout", ] [[package]] name = "clang-sys" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" dependencies = [ "glob", "libc", "libloading", ] +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -142,35 +160,53 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "generic-array 0.14.9", + "generic-array 0.14.7", "typenum", ] [[package]] name = "crypto-common" -version = "0.2.0-rc.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "hybrid-array 0.4.5", - "rand_core 0.9.3", + "hybrid-array 0.4.15", + "rand_core", ] [[package]] name = "ctr" -version = "0.10.0-rc.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e41d01c6f73b9330177f5cf782ae5b581b5f2c7840e298e0275ceee5001434" +checksum = "baaca1c4b237092596f64d571e9db6ce4109c4ef9742e27590f1709594461f21" dependencies = [ "cipher", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "digest" version = "0.10.7" @@ -178,14 +214,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "crypto-common 0.1.6", + "crypto-common 0.1.7", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "crypto-common 0.2.2", ] [[package]] name = "either" -version = "1.15.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" [[package]] name = "endian-type-rs" @@ -225,9 +271,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.9" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -235,9 +281,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "1.3.4" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985a5578ebdb02351d484a77fb27e7cb79272f1ba9bc24692d8243c3cfe40660" +checksum = "337d46834ee672ab3e48caca2cb0c78cc174fb12b3a68d0d88f99a0519a5e36e" dependencies = [ "rustversion", "typenum", @@ -245,18 +291,37 @@ dependencies = [ [[package]] name = "ghash" -version = "0.6.0-rc.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f88107cb02ed63adcc4282942e60c4d09d80208d33b360ce7c729ce6dae1739" +checksum = "2eecf2d5dc9b66b732b97707a0210906b1d30523eb773193ab777c0c84b3e8d5" dependencies = [ "polyval", ] [[package]] name = "glob" -version = "0.3.3" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "hash32" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] [[package]] name = "hybrid-array" @@ -269,20 +334,21 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.5" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" dependencies = [ + "ctutils", "typenum", ] [[package]] name = "inout" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7357b6e7aa75618c7864ebd0634b115a7218b0615f4cb1df33ac3eca23943d4" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ - "hybrid-array 0.4.5", + "hybrid-array 0.4.15", ] [[package]] @@ -296,28 +362,38 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", +] + +[[package]] +name = "keccak" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f198d1db720e4940b5a493201d199d9f24f568f8f746bd13706243a2f71598" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", ] [[package]] name = "kem" -version = "0.3.0-pre.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8645470337db67b01a7f966decf7d0bafedbae74147d33e641c67a91df239f" +checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd" dependencies = [ - "rand_core 0.6.4", - "zeroize", + "crypto-common 0.2.2", + "rand_core", ] [[package]] name = "libc" -version = "0.2.177" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libloading" @@ -331,15 +407,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.28" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memoffset" @@ -367,14 +443,26 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "ml-kem" -version = "0.3.0-pre" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fde1200e61dd95a2c6143baa22dbab79d8dad2644f55e955dd8a3d535f5d9f" +checksum = "5e15f3e5b957493873e396a66914e83e616b6afe335cdef7efe5c6e1216aba66" dependencies = [ - "hybrid-array 0.2.3", + "hybrid-array 0.4.15", "kem", - "rand_core 0.6.4", - "sha3", + "module-lattice", + "rand_core", + "sha3 0.11.0", +] + +[[package]] +name = "module-lattice" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c61b87c9683ab7cb1c6871d261ad5479b6b10ceb52c4352aaca3b5d35a8febe" +dependencies = [ + "ctutils", + "hybrid-array 0.4.15", + "num-traits", ] [[package]] @@ -423,12 +511,12 @@ dependencies = [ [[package]] name = "polyval" -version = "0.7.0-rc.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffd40cc99d0fbb02b4b3771346b811df94194bc103983efa0203c8893755085" +checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd" dependencies = [ - "cfg-if", - "cpufeatures", + "cpubits", + "cpufeatures 0.3.1", "universal-hash", ] @@ -439,44 +527,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.107", + "syn 2.0.119", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.41" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] [[package]] name = "rand_core" -version = "0.6.4" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "regex" -version = "1.12.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -486,9 +568,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -497,9 +579,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "riscv-decode" @@ -512,7 +594,8 @@ name = "riscv_cove_tap" version = "0.2.0" dependencies = [ "aes-gcm", - "generic-array 1.3.4", + "generic-array 1.4.5", + "heapless", "hybrid-array 0.2.3", "ml-kem", "thiserror-no-std", @@ -520,9 +603,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -535,22 +618,23 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "security-monitor" version = "0.4.0" dependencies = [ "flattened_device_tree", - "generic-array 0.14.9", + "generic-array 0.14.7", + "heapless", "memoffset 0.9.1", "opensbi-sys", "pointers_utility", "riscv-decode", "riscv_cove_tap", - "sha3", + "sha3 0.10.9", "spin", "thiserror-no-std", ] @@ -572,12 +656,22 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "sha3" -version = "0.10.8" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" +dependencies = [ + "digest 0.10.7", + "keccak 0.1.6", +] + +[[package]] +name = "sha3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" dependencies = [ - "digest", - "keccak", + "digest 0.11.3", + "keccak 0.2.2", ] [[package]] @@ -588,21 +682,21 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "spin" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" [[package]] -name = "static_assertions" -version = "1.1.0" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] -name = "subtle" -version = "2.6.1" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" @@ -617,9 +711,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.107" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -648,24 +742,24 @@ dependencies = [ [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" [[package]] name = "universal-hash" -version = "0.6.0-rc.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" +checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96" dependencies = [ - "crypto-common 0.2.0-rc.4", - "subtle", + "crypto-common 0.2.2", + "ctutils", ] [[package]] @@ -685,9 +779,3 @@ name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" diff --git a/security-monitor/Cargo.toml b/security-monitor/Cargo.toml index 95fb9344..230cf0b0 100644 --- a/security-monitor/Cargo.toml +++ b/security-monitor/Cargo.toml @@ -24,6 +24,9 @@ pointers_utility = {path = "rust-crates/pointers_utility"} # This crate decodes RISC-V instructions unfortunately it does not support the C-instructions yet riscv-decode = "0.2" +# Fixed capacity, heapless collections +heapless = { version = "0.8", default-features = false } + # The `spin` crate provides synchronization primitives (Mutexes etc) using spinlocks spin = {version="0.10", default-features = false, features = ["once", "rwlock", "spin_mutex"]} diff --git a/security-monitor/rust-crates/riscv_cove_tap/Cargo.toml b/security-monitor/rust-crates/riscv_cove_tap/Cargo.toml index ec7da892..52350a08 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/Cargo.toml +++ b/security-monitor/rust-crates/riscv_cove_tap/Cargo.toml @@ -6,10 +6,11 @@ description = "Library to parse the RISC-V CoVE's TEE attestation payload" edition = "2024" [dependencies] +heapless = { version = "0.8", default-features = false } rand = {version = "0.8.5", optional=true} hybrid-array = "0.2.3" -ml-kem = {version = "0.3.0-pre", default-features=false, features = [] } +ml-kem = {version = "0.3.2", default-features=false, features = [] } # for symmetric encryption of payload aes-gcm = {version="0.11.0-rc.1", default-features = false, features=["aes", "alloc", "rand_core"]} diff --git a/security-monitor/rust-crates/riscv_cove_tap/src/error.rs b/security-monitor/rust-crates/riscv_cove_tap/src/error.rs index a74e233b..fec6e2f5 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/src/error.rs +++ b/security-monitor/rust-crates/riscv_cove_tap/src/error.rs @@ -17,6 +17,14 @@ pub enum TapError { InvalidMagicStart(), #[error("Invalid size of the TAP")] InvalidSize(), + #[error("TAP contains more lockboxes than MAX_NUMBER_OF_LOCKBOXES")] + TooManyLockboxes(), + #[error("TAP contains more digests than MAX_NUMBER_OF_DIGESTS")] + TooManyDigests(), + #[error("TAP contains more secrets than MAX_NUMBER_OF_SECRETS")] + TooManySecrets(), + #[error("A value in the TAP exceeds the maximum allowed size")] + ValueTooLarge(), #[error("Aes error {0}")] AesError(#[from] aes_gcm::Error), #[error("Key from slice error")] diff --git a/security-monitor/rust-crates/riscv_cove_tap/src/parser.rs b/security-monitor/rust-crates/riscv_cove_tap/src/parser.rs index 9a1ad32d..bc1b6666 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/src/parser.rs +++ b/security-monitor/rust-crates/riscv_cove_tap/src/parser.rs @@ -2,10 +2,8 @@ // SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich // SPDX-License-Identifier: Apache-2.0 pub use crate::error::TapError; -use alloc::vec::Vec; -use crate::spec::*; -use alloc::vec; use crate::ensure; +use crate::spec::*; pub struct AttestationPayloadParser { pub pointer: *const u8, @@ -19,110 +17,136 @@ impl AttestationPayloadParser { pub fn parse_and_verify(&mut self, decapsulation_key: &[u8]) -> Result { ensure!(self.read_u32()? == ACE_MAGIC_TAP_START, TapError::InvalidMagicStart())?; - self.read_u16()?; - // if self.read_u16()? as usize != self.size { - // return Err(TapError::InvalidSize()); - // } + self.read_u16()?; // reserved / total-size field (ignored for now) let number_of_lockboxes = self.read_u16()?; - ensure!(usize::from(number_of_lockboxes) <= MAX_NUMBER_OF_LOCKBOXES, TapError::InvalidSize())?; + ensure!(usize::from(number_of_lockboxes) <= MAX_NUMBER_OF_LOCKBOXES, TapError::TooManyLockboxes())?; - let mut symmetric_key = vec![]; + let mut symmetric_key: heapless::Vec = heapless::Vec::new(); for _ in 0..number_of_lockboxes { let _size = self.read_u16()? as usize; - // TODO: decide based on the lockbox name if this lockbox is intended for this device or not let _name = self.read_u64()?; let algorithm = LockboxAlgorithm::from_u16(self.read_u16()?)?; + let esk_size = self.read_u16()? as usize; - ensure!(esk_size < 100_000, TapError::InvalidSize())?; - let esk = self.read_exact(esk_size)?; + ensure!(esk_size <= MAX_ESK_SIZE, TapError::ValueTooLarge())?; + let esk_ptr = self.pointer; + self.pointer = self.pointer.wrapping_add(esk_size); + let nonce_size = self.read_u16()? as usize; - ensure!(nonce_size < 100_000, TapError::InvalidSize())?; - let nonce = self.read_exact(nonce_size)?; + ensure!(nonce_size <= MAX_NONCE_SIZE, TapError::ValueTooLarge())?; + let nonce_buf = self.read_exact_n::(nonce_size)?; + let tag_size = self.read_u16()? as usize; - ensure!(tag_size < 100_000, TapError::InvalidSize())?; - let tag = self.read_exact(tag_size)?; + ensure!(tag_size <= MAX_TAG_SIZE, TapError::ValueTooLarge())?; + let tag_buf = self.read_exact_n::(tag_size)?; + let tsk_size = self.read_u16()? as usize; - ensure!(tsk_size < 100_000, TapError::InvalidSize())?; - symmetric_key = self.read_exact(tsk_size)?; - algorithm.decode(decapsulation_key, &esk, &nonce, &tag, &mut symmetric_key)?; + ensure!(tsk_size <= MAX_TSK_SIZE, TapError::ValueTooLarge())?; + symmetric_key.clear(); + let tsk_buf = self.read_exact_n::(tsk_size)?; + symmetric_key.extend_from_slice(&tsk_buf).map_err(|_| TapError::ValueTooLarge())?; + + let esk: &[u8] = unsafe { core::slice::from_raw_parts(esk_ptr, esk_size) }; + ensure!(decapsulation_key.len() <= MAX_DK_SIZE, TapError::ValueTooLarge())?; + algorithm.decode(decapsulation_key, esk, &nonce_buf, &tag_buf, &mut symmetric_key)?; } ensure!(!symmetric_key.is_empty(), TapError::NoLockboxFound())?; let payload_encryption_algorithm = PayloadEncryptionAlgorithm::from_u16(self.read_u16()?)?; match payload_encryption_algorithm { - PayloadEncryptionAlgorithm::Debug => {}, + PayloadEncryptionAlgorithm::Debug => {} PayloadEncryptionAlgorithm::AesGcm256 => self.decrypt_aes_gcm_256(&symmetric_key)?, } let number_of_digests = self.read_u16()?; - let mut digests = Vec::with_capacity(number_of_digests.into()); + ensure!(usize::from(number_of_digests) <= MAX_NUMBER_OF_DIGESTS, TapError::TooManyDigests())?; + let mut digests: heapless::Vec = heapless::Vec::new(); for _ in 0..number_of_digests { let size = self.read_u16()? as usize; - ensure!(4 <= size && size < 100_000, TapError::InvalidSize())?; + ensure!(4 <= size, TapError::InvalidSize())?; let pcr_id = self.read_u16()?; let algorithm = DigestAlgorithm::from_u16(self.read_u16()?)?; - let value = self.read_exact(size-4)?; - digests.push(Digest { - pcr_id, - algorithm, - value - }); + let value_len = size - 4; + ensure!(value_len <= MAX_DIGEST_VALUE_SIZE, TapError::ValueTooLarge())?; + let value = self.read_exact_n::(value_len)?; + digests.push(Digest { pcr_id, algorithm, value }).map_err(|_| TapError::TooManyDigests())?; } let number_of_secrets = self.read_u16()?; - let mut secrets = vec![]; + ensure!(usize::from(number_of_secrets) <= MAX_NUMBER_OF_SECRETS, TapError::TooManySecrets())?; + let mut secrets: heapless::Vec = heapless::Vec::new(); for _ in 0..number_of_secrets { let size = self.read_u16()? as usize; - ensure!(10 <= size && size < 100_000, TapError::InvalidSize())?; - let name = self.read_u64()? as u64; - let value = self.read_exact(size-10)?; - secrets.push(Secret { name, value }); + ensure!(10 <= size, TapError::InvalidSize())?; + let name = self.read_u64()?; + let value_len = size - 10; + ensure!(value_len <= MAX_SECRET_VALUE_SIZE, TapError::ValueTooLarge())?; + let value = self.read_exact_n::(value_len)?; + secrets.push(Secret { name, value }).map_err(|_| TapError::TooManySecrets())?; } Ok(AttestationPayload { digests, secrets }) } fn decrypt_aes_gcm_256(&mut self, symmetric_key: &[u8]) -> Result<(), TapError> { - use aes_gcm::{Aes256Gcm, AeadInOut, Key, KeyInit, Tag, Nonce}; + use aes_gcm::{AeadInOut, Aes256Gcm, Key, KeyInit, Nonce, Tag}; use aes_gcm::aead::inout::InOutBuf; let nonce_size = self.read_u16()? as usize; - ensure!(nonce_size < 100_000, TapError::InvalidSize())?; - let nonce = self.read_exact(nonce_size)?; + ensure!(nonce_size <= MAX_NONCE_SIZE, TapError::ValueTooLarge())?; + let nonce_buf = self.read_exact_n::(nonce_size)?; + let tag_size = self.read_u16()? as usize; - ensure!(tag_size < 100_000, TapError::InvalidSize())?; - let tag = self.read_exact(tag_size)?; + ensure!(tag_size <= MAX_TAG_SIZE, TapError::ValueTooLarge())?; + let tag_buf = self.read_exact_n::(tag_size)?; + let payload_size = self.read_u16()? as usize; - ensure!(payload_size < 100_000, TapError::InvalidSize())?; + ensure!(payload_size <= ACE_MAX_TAP_SIZE, TapError::InvalidSize())?; ensure!(symmetric_key.len() == 32, TapError::InvalidTskSize())?; let cipher = Aes256Gcm::new(&Key::::try_from(symmetric_key)?); - let nonce = Nonce::try_from(nonce.as_slice())?; - let tag = Tag::try_from(tag.as_slice())?; - let data_slice = unsafe{ core::slice::from_raw_parts_mut(self.pointer as *mut u8, payload_size) }; + let nonce = Nonce::try_from(nonce_buf.as_slice())?; + let tag = Tag::try_from(tag_buf.as_slice())?; + let data_slice = unsafe { core::slice::from_raw_parts_mut(self.pointer as *mut u8, payload_size) }; cipher.decrypt_inout_detached(&nonce, b"", InOutBuf::from(data_slice), &tag)?; Ok(()) } fn read_u16(&mut self) -> Result { - Ok(u16::from_le_bytes(self.read_exact(2)?.try_into().map_err(|_| TapError::InvalidSize())?)) + let mut buf = [0u8; 2]; + for b in buf.iter_mut() { + *b = unsafe { self.pointer.read_volatile() }; + self.pointer = self.pointer.wrapping_add(1); + } + Ok(u16::from_le_bytes(buf)) } fn read_u32(&mut self) -> Result { - Ok(u32::from_le_bytes(self.read_exact(4)?.try_into().map_err(|_| TapError::InvalidSize())?)) + let mut buf = [0u8; 4]; + for b in buf.iter_mut() { + *b = unsafe { self.pointer.read_volatile() }; + self.pointer = self.pointer.wrapping_add(1); + } + Ok(u32::from_le_bytes(buf)) } fn read_u64(&mut self) -> Result { - Ok(u64::from_le_bytes(self.read_exact(8)?.try_into().map_err(|_| TapError::InvalidSize())?)) + let mut buf = [0u8; 8]; + for b in buf.iter_mut() { + *b = unsafe { self.pointer.read_volatile() }; + self.pointer = self.pointer.wrapping_add(1); + } + Ok(u64::from_le_bytes(buf)) } - fn read_exact(&mut self, size: usize) -> Result, TapError> { - let mut result = Vec::with_capacity(size); + fn read_exact_n(&mut self, size: usize) -> Result, TapError> { + ensure!(size <= N, TapError::ValueTooLarge())?; + let mut result: heapless::Vec = heapless::Vec::new(); for _ in 0..size { - let value = unsafe { self.pointer.read_volatile() }; + let byte = unsafe { self.pointer.read_volatile() }; self.pointer = self.pointer.wrapping_add(1); - result.push(value); + result.push(byte).map_err(|_| TapError::ValueTooLarge())?; } Ok(result) } -} \ No newline at end of file +} diff --git a/security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs b/security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs index e7035bda..de90ca77 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs +++ b/security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs @@ -2,123 +2,135 @@ // SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich // SPDX-License-Identifier: Apache-2.0 use crate::error::TapError; -use alloc::vec; use crate::spec::*; -use alloc::vec::Vec; +use heapless::Vec; -pub struct AttestationPayloadSerializer { +/// Type alias for a bounded wire output buffer sized to the maximum TAP blob. +type WireBuffer = Vec; +#[inline] +fn push_u16(buf: &mut WireBuffer, value: u16) -> Result<(), TapError> { + buf.extend_from_slice(&value.to_le_bytes()).map_err(|_| TapError::InvalidSize()) } +#[inline] +fn push_u32(buf: &mut WireBuffer, value: u32) -> Result<(), TapError> { + buf.extend_from_slice(&value.to_le_bytes()).map_err(|_| TapError::InvalidSize()) +} + +#[inline] +fn push_u64(buf: &mut WireBuffer, value: u64) -> Result<(), TapError> { + buf.extend_from_slice(&value.to_le_bytes()).map_err(|_| TapError::InvalidSize()) +} + +#[inline] +fn push_bytes(buf: &mut WireBuffer, bytes: &[u8]) -> Result<(), TapError> { + buf.extend_from_slice(bytes).map_err(|_| TapError::InvalidSize()) +} + +pub struct AttestationPayloadSerializer {} + impl AttestationPayloadSerializer { pub fn new() -> Self { Self {} } - pub fn serialize(&self, lockboxes: Vec, mut payload: AttestationPayload) -> Result, TapError> { - let digests = self.serialize_digests(&mut payload)?; - let secrets = self.serialize_secrets(&mut payload)?; - let mut encrypted_part = self.encrypt_aes_gcm_256(digests, secrets)?; - let mut lockboxes = self.serialize_lockboxes(lockboxes)?; + pub fn serialize( + &self, + lockboxes: Vec, + payload: AttestationPayload, + ) -> Result { + let digests = self.serialize_digests(&payload)?; + let secrets = self.serialize_secrets(&payload)?; + let encrypted_part = self.encrypt_aes_gcm_256(digests, secrets)?; + let lockboxes_buf = self.serialize_lockboxes(lockboxes)?; - let total_size = lockboxes.len() + encrypted_part.len(); + let total_size = lockboxes_buf.len() + encrypted_part.len(); - let mut result = vec![]; - result.append(&mut ACE_MAGIC_TAP_START.to_le_bytes().to_vec()); - result.append(&mut (total_size as u16).to_le_bytes().to_vec()); - result.append(&mut lockboxes); - result.append(&mut encrypted_part); + let mut result = WireBuffer::new(); + push_u32(&mut result, ACE_MAGIC_TAP_START)?; + push_u16(&mut result, total_size as u16)?; + result.extend_from_slice(&lockboxes_buf).map_err(|_| TapError::InvalidSize())?; + result.extend_from_slice(&encrypted_part).map_err(|_| TapError::InvalidSize())?; Ok(result) } - fn serialize_lockboxes(&self, mut lockboxes: Vec) -> Result, TapError> { - // TODO: sanity check: lockboxes < 1024 - let mut result = vec![]; - result.append(&mut (lockboxes.len() as u16).to_le_bytes().to_vec()); - for mut lockbox in lockboxes.drain(..) { + fn serialize_lockboxes(&self, lockboxes: Vec) -> Result { + let mut result = WireBuffer::new(); + push_u16(&mut result, lockboxes.len() as u16)?; + for lockbox in lockboxes.into_iter() { let entry_size = lockbox.esk.len() + lockbox.nonce.len() + lockbox.tag.len() + lockbox.tsk.len() + 18; - result.append(&mut (entry_size as u16).to_le_bytes().to_vec()); - result.append(&mut (lockbox.name as u64).to_le_bytes().to_vec()); - result.append(&mut (lockbox.algorithm as u16).to_le_bytes().to_vec()); - result.append(&mut (lockbox.esk.len() as u16).to_le_bytes().to_vec()); - result.append(&mut lockbox.esk); - result.append(&mut (lockbox.nonce.len() as u16).to_le_bytes().to_vec()); - result.append(&mut lockbox.nonce); - result.append(&mut (lockbox.tag.len() as u16).to_le_bytes().to_vec()); - result.append(&mut lockbox.tag); - result.append(&mut (lockbox.tsk.len() as u16).to_le_bytes().to_vec()); - result.append(&mut lockbox.tsk); + push_u16(&mut result, entry_size as u16)?; + push_u64(&mut result, lockbox.name)?; + push_u16(&mut result, lockbox.algorithm as u16)?; + push_u16(&mut result, lockbox.esk.len() as u16)?; + push_bytes(&mut result, &lockbox.esk)?; + push_u16(&mut result, lockbox.nonce.len() as u16)?; + push_bytes(&mut result, &lockbox.nonce)?; + push_u16(&mut result, lockbox.tag.len() as u16)?; + push_bytes(&mut result, &lockbox.tag)?; + push_u16(&mut result, lockbox.tsk.len() as u16)?; + push_bytes(&mut result, &lockbox.tsk)?; } Ok(result) } - fn serialize_digests(&self, payload: &mut AttestationPayload) -> Result, TapError> { - // TODO: sanity check: digests < 1024 - let mut result = vec![]; - result.append(&mut (payload.digests.len() as u16).to_le_bytes().to_vec()); - for mut digest in payload.digests.drain(..) { + fn serialize_digests(&self, payload: &AttestationPayload) -> Result { + let mut result = WireBuffer::new(); + push_u16(&mut result, payload.digests.len() as u16)?; + for digest in payload.digests.iter() { let entry_size = digest.value.len() + 2 + 2; - result.append(&mut (entry_size as u16).to_le_bytes().to_vec()); - result.append(&mut (digest.pcr_id).to_le_bytes().to_vec()); - result.append(&mut (digest.algorithm as u16).to_le_bytes().to_vec()); - result.append(&mut digest.value); + push_u16(&mut result, entry_size as u16)?; + push_u16(&mut result, digest.pcr_id)?; + push_u16(&mut result, digest.algorithm as u16)?; + push_bytes(&mut result, &digest.value)?; } Ok(result) } - fn serialize_secrets(&self, payload: &mut AttestationPayload) -> Result, TapError> { - // TODO: sanity check: secrets < 1024 - let mut result = vec![]; - result.append(&mut (payload.secrets.len() as u16).to_le_bytes().to_vec()); - for mut secret in payload.secrets.drain(..) { + fn serialize_secrets(&self, payload: &AttestationPayload) -> Result { + let mut result = WireBuffer::new(); + push_u16(&mut result, payload.secrets.len() as u16)?; + for secret in payload.secrets.iter() { let entry_size = secret.value.len() + 10; - result.append(&mut (entry_size as u16).to_le_bytes().to_vec()); - result.append(&mut (secret.name).to_le_bytes().to_vec()); - result.append(&mut secret.value); + push_u16(&mut result, entry_size as u16)?; + push_u64(&mut result, secret.name)?; + push_bytes(&mut result, &secret.value)?; } Ok(result) } - fn encrypt_aes_gcm_256(&self, mut digests: Vec, mut secrets: Vec) -> Result, TapError> { + fn encrypt_aes_gcm_256( + &self, + digests: WireBuffer, + secrets: WireBuffer, + ) -> Result { use aes_gcm::{AeadInOut, Aes256Gcm, Key, KeyInit}; use aes_gcm::aead::inout::InOutBuf; - let mut encrypted_part = vec![]; - encrypted_part.append(&mut digests); - encrypted_part.append(&mut secrets); + let mut plaintext = WireBuffer::new(); + push_bytes(&mut plaintext, &digests)?; + push_bytes(&mut plaintext, &secrets)?; let symmetric_key = [0u8; 32]; - // rand::thread_rng().fill_bytes(&mut symmetric_key); - let key: Key = symmetric_key.into(); let cipher = Aes256Gcm::new(&key); - let nonce = [0u8; 12]; - // let nonce = Aes256Gcm::generate_nonce(&mut OsRng); - let nonce = aes_gcm::Nonce::try_from(nonce.as_slice())?; + let nonce_bytes = [0u8; MAX_NONCE_SIZE]; + let nonce = aes_gcm::Nonce::try_from(nonce_bytes.as_slice())?; let tag = cipher - .encrypt_inout_detached(&nonce, b"", InOutBuf::from(encrypted_part.as_mut_slice())) + .encrypt_inout_detached(&nonce, b"", InOutBuf::from(plaintext.as_mut_slice())) .unwrap(); - let mut result = vec![]; - result.append(&mut (PayloadEncryptionAlgorithm::AesGcm256 as u16).to_le_bytes().to_vec()); - result.append(&mut (nonce.as_slice().len() as u16).to_le_bytes().to_vec()); - result.append(&mut nonce.as_slice().to_vec()); - result.append(&mut (tag.as_slice().len() as u16).to_le_bytes().to_vec()); - result.append(&mut tag.as_slice().to_vec()); - result.append(&mut (encrypted_part.len() as u16).to_le_bytes().to_vec()); - result.append(&mut encrypted_part); + let mut result = WireBuffer::new(); + push_u16(&mut result, PayloadEncryptionAlgorithm::AesGcm256 as u16)?; + push_u16(&mut result, nonce_bytes.len() as u16)?; + push_bytes(&mut result, &nonce_bytes)?; + push_u16(&mut result, tag.as_slice().len() as u16)?; + push_bytes(&mut result, tag.as_slice())?; + push_u16(&mut result, plaintext.len() as u16)?; + push_bytes(&mut result, &plaintext)?; Ok(result) } - - // fn encrypt_rsa_2048_sha256_oasp(value: &[u8], public_key_file: String) -> Result, Error> { - // use rsa::pkcs1::DecodeRsaPublicKey; - // let public_key_pem: Vec = std::fs::read(public_key_file.clone()) - // .map_err(|_| Error::CannotOpenFile(public_key_file))?; - // let public_key = rsa::RsaPublicKey::from_pkcs1_pem(&String::from_utf8_lossy(&public_key_pem))?; - // let padding = rsa::Oaep::new::(); - // let encrypted_data = public_key.encrypt(&mut rand::thread_rng(), padding, value)?; - // Ok(encrypted_data) - // } -} \ No newline at end of file +} diff --git a/security-monitor/rust-crates/riscv_cove_tap/src/spec.rs b/security-monitor/rust-crates/riscv_cove_tap/src/spec.rs index 07419ec3..c4f94d08 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/src/spec.rs +++ b/security-monitor/rust-crates/riscv_cove_tap/src/spec.rs @@ -2,46 +2,87 @@ // SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich // SPDX-License-Identifier: Apache-2.0 use crate::error::TapError; -use alloc::vec::Vec; +use heapless::Vec; pub const ACE_HEADER_SIZE: usize = 8; pub const ACE_FOOTER_SIZE: usize = 8; pub const ACE_MAGIC_TAP_START: u32 = 0xACE0ACE0; pub const ACE_MAGIC_TAP_END: u32 = 0xACE1ACE1; -pub const ACE_MAX_TAP_SIZE: usize = 4096; // size of the 4KiB page -pub const MAX_NUMBER_OF_LOCKBOXES: usize = 1024; +/// Maximum total wire size of a TAP blob (one 4 KiB page). +pub const ACE_MAX_TAP_SIZE: usize = 4096; + +/// Maximum number of lockboxes (key-encapsulations) in one TAP. +/// Each lockbox targets one device identity; 16 is more than enough for any +/// realistic deployment while keeping the parser's stack budget bounded. +pub const MAX_NUMBER_OF_LOCKBOXES: usize = 16; + +/// Maximum number of measurement digests (PCR values) in one TAP. +/// CoVE defines at most 24 PCR slots; we round up to 32 for headroom. +pub const MAX_NUMBER_OF_DIGESTS: usize = 32; + +/// Maximum number of secrets carried in one TAP. +/// A VM rarely needs more than a handful of symmetric keys at provisioning. +pub const MAX_NUMBER_OF_SECRETS: usize = 8; + +/// Maximum byte length of a single secret value. +/// 256 bytes covers all standard symmetric key material: +/// AES-256 (32 B), HMAC-SHA-512 key (64 B), two AES keys + nonce (76 B), etc. +pub const MAX_SECRET_VALUE_SIZE: usize = 256; + +/// Maximum byte length of a single digest value. +/// SHA-512 produces 64 bytes; 128 bytes gives comfortable headroom. +pub const MAX_DIGEST_VALUE_SIZE: usize = 128; + +/// Maximum size of the encapsulated symmetric key (esk). +/// ML-KEM-1024 ciphertext is exactly 1568 bytes (FIPS 203, K=4, Du=11, Dv=5: +/// 32*(Du*K + Dv) = 32*49 = 1568). +pub const MAX_ESK_SIZE: usize = 1568; + +/// Maximum size of an AES-GCM nonce. +/// AES-256-GCM uses a 96-bit (12-byte) nonce. +pub const MAX_NONCE_SIZE: usize = 12; + +/// Maximum size of an AES-GCM authentication tag. +/// AES-256-GCM produces a 128-bit (16-byte) tag. +pub const MAX_TAG_SIZE: usize = 16; + +/// Maximum size of the transport symmetric key (tsk) stored in a Lockbox. +/// Reuses MAX_SECRET_VALUE_SIZE: the tsk is used to decrypt the payload that +/// carries the secrets, so it must fit within the same bound. +pub const MAX_TSK_SIZE: usize = MAX_SECRET_VALUE_SIZE; + +/// Maximum size of the ML-KEM-1024 decapsulation key accepted by the parser. +/// FIPS 203: dk size = 768*K + 96 = 768*4 + 96 = 3168 bytes. +pub const MAX_DK_SIZE: usize = 3168; pub struct AttestationPayload { - pub digests: Vec, - pub secrets: Vec, + pub digests: Vec, + pub secrets: Vec, } pub struct Lockbox { pub name: u64, pub algorithm: LockboxAlgorithm, - pub esk: Vec, - pub nonce: Vec, - pub tag: Vec, - pub tsk: Vec + pub esk: Vec, + pub nonce: Vec, + pub tag: Vec, + pub tsk: Vec, } impl Lockbox { #[cfg(feature = "serializer")] - pub fn new(lockbox_algorithm: LockboxAlgorithm, encapsulation_key: &Vec, tsk: &mut Vec) -> Result { + pub fn new( + lockbox_algorithm: LockboxAlgorithm, + encapsulation_key: &[u8], + tsk: &mut Vec, + ) -> Result { let (esk, nonce, tag, tsk) = lockbox_algorithm.encode(encapsulation_key, tsk)?; - Ok(Self { - name: 0, - algorithm: lockbox_algorithm, - esk, - nonce, - tag, - tsk - }) + Ok(Self { name: 0, algorithm: lockbox_algorithm, esk, nonce, tag, tsk }) } } #[repr(u16)] -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum LockboxAlgorithm { Debug = 0, MlKem1024Aes256 = 1, @@ -57,62 +98,92 @@ impl LockboxAlgorithm { } #[cfg(feature = "serializer")] - pub fn encode(&self, encapsulation_key: &Vec, tsk: &mut Vec) -> Result<(Vec, Vec, Vec, Vec), TapError> { - use alloc::vec; + pub fn encode( + &self, + encapsulation_key: &[u8], + tsk: &mut Vec, + ) -> Result<( + Vec, + Vec, + Vec, + Vec, + ), TapError> { match self { LockboxAlgorithm::Debug => { - Ok((vec![], vec![], vec![], tsk.to_vec())) + // Debug mode: all fields empty, tsk is passed through unchanged. + Ok((Vec::new(), Vec::new(), Vec::new(), Vec::new())) } LockboxAlgorithm::MlKem1024Aes256 => { - use rand::rngs::OsRng; use rand::Rng; let mut rng = rand::thread_rng(); - use ml_kem::{MlKem1024, KemCore, MlKem1024Params, Encoded, EncodedSizeUser, kem::{Encapsulate, EncapsulationKey}}; + use ml_kem::{B32, ml_kem_1024::EncapsulationKey, kem::Key as KemKey}; - let ek_bytes = Encoded::>::try_from(encapsulation_key.as_slice())?; - let ek = ::EncapsulationKey::from_bytes(&ek_bytes); - let (esk, aes_key) = match ek.encapsulate(&mut OsRng) { - Ok(v) => v, - Err(_) => return Err(TapError::KemError()) - }; + let ek_key_arr = KemKey::::try_from(encapsulation_key) + .map_err(|_| TapError::KemError())?; + let ek = EncapsulationKey::new(&ek_key_arr).map_err(|_| TapError::KemError())?; + let mut m_bytes = [0u8; 32]; + rng.fill(&mut m_bytes); + let m = B32::try_from(m_bytes.as_slice()).map_err(|_| TapError::KemError())?; + let (esk_arr, aes_key) = ek.encapsulate_deterministic(&m); use aes_gcm::{AeadInOut, Aes256Gcm, Key, KeyInit}; use aes_gcm::aead::inout::InOutBuf; - let mut nonce = [0u8; 12]; - rng.fill(&mut nonce); + let mut nonce_bytes = [0u8; MAX_NONCE_SIZE]; + rng.fill(&mut nonce_bytes); let key: &Key = &Key::::try_from(aes_key.as_slice())?; - let cipher = Aes256Gcm::new(&key); - //let nonce = Aes256Gcm::generate_nonce_with_rng(&mut OsRng); - let nonce = aes_gcm::Nonce::try_from(nonce.as_slice())?; - let tag = cipher.encrypt_inout_detached(&nonce, b"", InOutBuf::from(tsk.as_mut_slice()))?; + let cipher = Aes256Gcm::new(key); + let nonce = aes_gcm::Nonce::try_from(nonce_bytes.as_slice())?; + let tag_arr = cipher.encrypt_inout_detached(&nonce, b"", InOutBuf::from(tsk.as_mut_slice()))?; + + let mut esk: Vec = Vec::new(); + esk.extend_from_slice(esk_arr.as_slice()).map_err(|_| TapError::ValueTooLarge())?; + let mut nonce_out: Vec = Vec::new(); + nonce_out.extend_from_slice(nonce.as_slice()).map_err(|_| TapError::ValueTooLarge())?; + let mut tag_out: Vec = Vec::new(); + tag_out.extend_from_slice(tag_arr.as_slice()).map_err(|_| TapError::ValueTooLarge())?; + let mut tsk_out: Vec = Vec::new(); + tsk_out.extend_from_slice(tsk.as_slice()).map_err(|_| TapError::ValueTooLarge())?; - Ok((esk.to_vec(), nonce.as_slice().to_vec(), tag.as_slice().to_vec(), tsk.to_vec())) + Ok((esk, nonce_out, tag_out, tsk_out)) } } } #[cfg(feature = "parser")] - pub fn decode(&self, decapsulation_key: &[u8], esk: &[u8], nonce: &[u8], tag: &[u8], tsk: &mut Vec) -> Result<(), TapError> { + pub fn decode( + &self, decapsulation_key: &[u8], esk: &[u8], nonce: &[u8], tag: &[u8], + tsk: &mut Vec, + ) -> Result<(), TapError> { match self { - LockboxAlgorithm::Debug => { - Ok(()) - }, + LockboxAlgorithm::Debug => Ok(()), LockboxAlgorithm::MlKem1024Aes256 => { - use aes_gcm::{AeadInOut, Aes256Gcm, Key, KeyInit, Tag, Nonce}; + use aes_gcm::{AeadInOut, Aes256Gcm, Key, KeyInit, Nonce, Tag}; use aes_gcm::aead::inout::InOutBuf; - use hybrid_array::Array; - use ml_kem::{MlKem1024, KemCore, MlKem1024Params, Encoded, EncodedSizeUser,kem::{Decapsulate, DecapsulationKey}}; - - let m = Array::try_from(esk)?; - let dk_bytes = Encoded::>::try_from(decapsulation_key)?; - let dk = ::DecapsulationKey::from_bytes(&dk_bytes); - let sk = match dk.decapsulate(&m) { - Ok(v) => v, - Err(_) => return Err(TapError::KemError()) + use ml_kem::{ + ml_kem_1024::{Ciphertext, DecapsulationKey}, + kem::Decapsulate, + ExpandedDecapsulationKey, }; + let ct_arr = Ciphertext::try_from(esk).map_err(|_| TapError::KemError())?; + let dk_expanded = ExpandedDecapsulationKey::::try_from(decapsulation_key) + .map_err(|_| TapError::KemError())?; + // `from_expanded` is the correct API for loading a pre-existing 3168-byte key; + // the deprecation warning points at `from_seed` which takes a 64-byte random seed + // and is not equivalent. Suppress until ml-kem stabilises a replacement. + #[allow(deprecated)] + let dk = DecapsulationKey::from_expanded(&dk_expanded).map_err(|_| TapError::KemError())?; + let sk = dk.decapsulate(&ct_arr); + let cipher = Aes256Gcm::new(&Key::::try_from(sk.as_slice())?); - cipher.decrypt_inout_detached(&Nonce::try_from(nonce)?, b"", InOutBuf::from(tsk.as_mut_slice()), &Tag::try_from(tag)?).unwrap(); + cipher + .decrypt_inout_detached( + &Nonce::try_from(nonce)?, + b"", + InOutBuf::from(tsk.as_mut_slice()), + &Tag::try_from(tag)?, + ) + .unwrap(); Ok(()) } } @@ -122,13 +193,17 @@ impl LockboxAlgorithm { pub struct Digest { pub pcr_id: u16, pub algorithm: DigestAlgorithm, - pub value: Vec, + pub value: Vec, } impl Digest { pub fn value_in_hex(&self) -> alloc::string::String { use crate::alloc::string::ToString; - self.value.iter().map(|b| alloc::format!("{:02x}", b).to_string()).collect::>().join("") + self.value + .iter() + .map(|b| alloc::format!("{:02x}", b).to_string()) + .collect::>() + .join("") } pub fn pcr_id(&self) -> u16 { @@ -137,7 +212,7 @@ impl Digest { } #[repr(u16)] -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DigestAlgorithm { Debug = 0, Sha512 = 1, @@ -154,19 +229,19 @@ impl DigestAlgorithm { pub fn digest_size(&self) -> u16 { match self { - &Self::Debug => 0, - &Self::Sha512 => 512 / 8, + Self::Debug => 0, + Self::Sha512 => 512 / 8, } } } pub struct Secret { pub name: u64, - pub value: Vec, + pub value: Vec, } #[repr(u16)] -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum PayloadEncryptionAlgorithm { Debug = 0, AesGcm256 = 1, @@ -180,4 +255,4 @@ impl PayloadEncryptionAlgorithm { v => Err(TapError::UnsupportedPayloadEncryptionAlgorithm(v)), } } -} \ No newline at end of file +} diff --git a/security-monitor/src/confidential_flow/finite_state_machine.rs b/security-monitor/src/confidential_flow/finite_state_machine.rs index 8928d0a5..71acaaa9 100644 --- a/security-monitor/src/confidential_flow/finite_state_machine.rs +++ b/security-monitor/src/confidential_flow/finite_state_machine.rs @@ -264,12 +264,12 @@ impl<'a> ConfidentialFlow<'a> { confidential_vm.try_confidential_hart_remote_commands( self.confidential_hart_id(), |ref mut confidential_hart_remote_commands| { - confidential_hart_remote_commands.drain(..).for_each(|confidential_hart_remote_command| { + while let Some(confidential_hart_remote_command) = confidential_hart_remote_commands.pop() { // The confidential flow has an ownership of the confidential hart because the confidential hart // is assigned to the hardware hart. self.confidential_hart_mut().execute(&confidential_hart_remote_command); requests_processed = true; - }); + } Ok(()) }, ) diff --git a/security-monitor/src/core/architecture/riscv/extensions/vector_unit.rs b/security-monitor/src/core/architecture/riscv/extensions/vector_unit.rs index 8403b853..484e4e51 100644 --- a/security-monitor/src/core/architecture/riscv/extensions/vector_unit.rs +++ b/security-monitor/src/core/architecture/riscv/extensions/vector_unit.rs @@ -2,7 +2,6 @@ // SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich // SPDX-License-Identifier: Apache-2.0 #![allow(unused)] -use alloc::vec::Vec; use core::ops::Range; pub const MAX_NUMBER_OF_REGISTER_LENGTH: usize = 32; diff --git a/security-monitor/src/core/architecture/riscv/general_purpose_registers.rs b/security-monitor/src/core/architecture/riscv/general_purpose_registers.rs index fd48024b..fcfa072f 100644 --- a/security-monitor/src/core/architecture/riscv/general_purpose_registers.rs +++ b/security-monitor/src/core/architecture/riscv/general_purpose_registers.rs @@ -2,7 +2,6 @@ // SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich // SPDX-License-Identifier: Apache-2.0 use crate::core::control_data::{DigestType, MeasurementDigest}; -use alloc::vec::Vec; use core::ops::Range; #[repr(C)] diff --git a/security-monitor/src/core/architecture/riscv/mmu/page_table.rs b/security-monitor/src/core/architecture/riscv/mmu/page_table.rs index b41d1c80..46f1228a 100644 --- a/security-monitor/src/core/architecture/riscv/mmu/page_table.rs +++ b/security-monitor/src/core/architecture/riscv/mmu/page_table.rs @@ -308,7 +308,7 @@ impl PageTable { self.serialized_representation.write(self.paging_system.entry_size() * virtual_page_number, entry.serialize()).unwrap(); let entry_to_remove = core::mem::replace(&mut self.logical_representation[virtual_page_number], entry); if let LogicalPageTableEntry::PageWithConfidentialVmData(page) = entry_to_remove { - PageAllocator::release_pages(alloc::vec![page.deallocate()]); + PageAllocator::release_page(page.deallocate()); } } diff --git a/security-monitor/src/core/control_data/confidential_hart.rs b/security-monitor/src/core/control_data/confidential_hart.rs index 39d63aa2..7f486cef 100644 --- a/security-monitor/src/core/control_data/confidential_hart.rs +++ b/security-monitor/src/core/control_data/confidential_hart.rs @@ -97,7 +97,7 @@ impl ConfidentialHart { confidential_hart_state.csrs_mut().mie.save_value_in_main_memory(Self::ENABLED_INTERRUPTS); confidential_hart_state.csrs_mut().htimedelta.save_value_in_main_memory(htimedelta); // Setup the M-mode trap handler to the security monitor's entry point - confidential_hart_state.csrs_mut().mtvec.save_value_in_main_memory(enter_from_confidential_hart_asm as usize); + confidential_hart_state.csrs_mut().mtvec.save_value_in_main_memory(enter_from_confidential_hart_asm as *const () as usize); // There is a subset of S-mode CSRs that have no VS equivalent and preserve their function when virtualization is enabled (see // `Hypervisor and Virtual Supervisor CSRs` in Volume II: RISC-V Privileged Architectures V20211203). diff --git a/security-monitor/src/core/control_data/confidential_vm.rs b/security-monitor/src/core/control_data/confidential_vm.rs index a22fec71..4ececd0d 100644 --- a/security-monitor/src/core/control_data/confidential_vm.rs +++ b/security-monitor/src/core/control_data/confidential_vm.rs @@ -7,30 +7,33 @@ use crate::core::control_data::{ }; use crate::core::memory_protector::ConfidentialVmMemoryProtector; use crate::error::Error; -use alloc::collections::BTreeMap; -use alloc::vec::Vec; +use heapless::{FnvIndexMap, Vec}; use riscv_cove_tap::Secret; use spin::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; pub struct ConfidentialVm { id: ConfidentialVmId, - confidential_harts: Vec>, + confidential_harts: Vec, { Self::MAX_NUMBER_OF_HARTS_PER_VM }>, _measurements: StaticMeasurements, - secrets: Vec, - remote_commands: BTreeMap>>, + secrets: Vec, + remote_commands: FnvIndexMap< + usize, + Mutex>, + { Self::MAX_NUMBER_OF_HARTS_PER_VM }, + >, memory_protector: RwLock, allowed_external_interrupts: usize, - mmio_regions: Vec, + mmio_regions: Vec, } impl ConfidentialVm { - pub const MAX_NUMBER_OF_HARTS_PER_VM: usize = 1024; - /// An average number of inter hart requests that can be buffered before being processed. - const AVG_NUMBER_OF_COMMANDS: usize = 3; + pub const MAX_NUMBER_OF_HARTS_PER_VM: usize = 16; + /// A maximum number of secrets per VM + pub const MAX_NUMBER_OF_SECRETS: usize = 8; /// A maximum number of inter hart requests that can be buffered. - const MAX_NUMBER_OF_COMMANDS: usize = 64; + pub const MAX_NUMBER_OF_COMMANDS: usize = 32; /// A maximum number of MMIO regions that a confidential VM can register - const MAX_NUMBER_OF_MMIO_REGIONS: usize = 1024; + const MAX_NUMBER_OF_MMIO_REGIONS: usize = 64; /// Constructs a new confidential VM. /// @@ -38,27 +41,29 @@ impl ConfidentialVm { /// /// The id of the confidential VM must be unique. pub fn new( - id: ConfidentialVmId, mut confidential_harts: Vec, _measurements: StaticMeasurements, secrets: Vec, + id: ConfidentialVmId, confidential_harts: Vec, { Self::MAX_NUMBER_OF_HARTS_PER_VM }>, + remote_commands: FnvIndexMap< + usize, + Mutex>, + { Self::MAX_NUMBER_OF_HARTS_PER_VM }, + >, + _measurements: StaticMeasurements, secrets: Vec, mut memory_protector: ConfidentialVmMemoryProtector, - ) -> Self { + ) -> Result { memory_protector.set_confidential_vm_id(id); - let remote_commands = confidential_harts - .iter_mut() - .map(|confidential_hart| { - confidential_hart.set_confidential_vm_id(id); - (confidential_hart.confidential_hart_id(), Mutex::new(Vec::with_capacity(Self::AVG_NUMBER_OF_COMMANDS))) - }) - .collect(); - Self { + for hart_lock in confidential_harts.iter() { + hart_lock.write().set_confidential_vm_id(id); + } + Ok(Self { id, - confidential_harts: confidential_harts.into_iter().map(|h| RwLock::new(h)).collect(), + confidential_harts, _measurements, secrets, remote_commands, memory_protector: RwLock::new(memory_protector), allowed_external_interrupts: 0, - mmio_regions: Vec::with_capacity(8), - } + mmio_regions: Vec::new(), + }) } pub fn confidential_vm_id(&self) -> ConfidentialVmId { @@ -73,12 +78,8 @@ impl ConfidentialVm { self.memory_protector.write() } - pub fn secret(&self, secret_id: usize) -> Result, Error> { - self.secrets - .iter() - .find(|ref s| s.name == secret_id as u64) - .and_then(|s| Some(s.value.to_vec())) - .ok_or_else(|| Error::InvalidParameter()) + pub fn secret(&self, secret_id: usize) -> Result, Error> { + self.secrets.iter().find(|s| s.name == secret_id as u64).map(|s| s.value.clone()).ok_or_else(|| Error::InvalidParameter()) } pub(super) fn deallocate(self) { @@ -138,7 +139,8 @@ impl ConfidentialVm { pub fn add_mmio_region(&mut self, region: ConfidentialVmMmioRegion) -> Result<(), Error> { ensure!(self.mmio_regions.len() < Self::MAX_NUMBER_OF_MMIO_REGIONS, Error::ReachedMaxNumberOfMmioRegions())?; ensure!(!self.mmio_regions.iter().any(|x| x.overlaps(®ion)), Error::OverlappingMmioRegion())?; - Ok(self.mmio_regions.push(region)) + self.mmio_regions.push(region).map_err(|_| Error::ReachedMaxNumberOfMmioRegions())?; + Ok(()) } pub fn remove_mmio_region(&mut self, region: &ConfidentialVmMmioRegion) { @@ -195,7 +197,7 @@ impl ConfidentialVm { self.try_confidential_hart_remote_commands(confidential_hart_id, |ref mut remote_commands| { ensure!(remote_commands.len() < Self::MAX_NUMBER_OF_COMMANDS, Error::ReachedMaxNumberOfRemoteCommands())?; if remote_commands.iter().find(|c| **c == remote_command).is_none() { - remote_commands.push(remote_command.clone()); + remote_commands.push(remote_command.clone()).map_err(|_| Error::ReachedMaxNumberOfRemoteCommands())?; } Ok(()) })?; @@ -206,7 +208,7 @@ impl ConfidentialVm { } pub fn try_confidential_hart_remote_commands(&self, confidential_hart_id: usize, op: O) -> Result - where O: FnOnce(MutexGuard<'_, Vec>) -> Result { + where O: FnOnce(MutexGuard<'_, Vec>) -> Result { op(self.remote_commands.get(&confidential_hart_id).ok_or(Error::InvalidHartId())?.lock()) } } diff --git a/security-monitor/src/core/hardware_setup/mod.rs b/security-monitor/src/core/hardware_setup/mod.rs index cd082036..65ccef9b 100644 --- a/security-monitor/src/core/hardware_setup/mod.rs +++ b/security-monitor/src/core/hardware_setup/mod.rs @@ -4,7 +4,7 @@ use crate::core::architecture::HardwareExtension; use crate::core::architecture::riscv::specification::*; use crate::error::Error; -use alloc::vec::Vec; +use heapless::Vec; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; /// Global static description of hardware setup. It is created during the system initiization and used in runtime to perform operations that @@ -12,7 +12,7 @@ use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; static HARDWARE_SETUP: Once> = Once::new(); pub struct HardwareSetup { - isa_extensions: Vec, + isa_extensions: Vec, } impl HardwareSetup { @@ -31,16 +31,17 @@ impl HardwareSetup { // example prop value rv64imafdch_zicsr_zifencei_zba_zbb_zbc_zbs debug!("{}", prop); ensure!(prop.starts_with(RISCV_ARCH), Error::InvalidCpuArch())?; - let extensions = &prop.split('_').collect::>(); - Self::REQUIRED_BASE_EXTENSIONS + let mut extensions = prop.split('_'); + let base = extensions.next().unwrap_or(""); + Self::REQUIRED_BASE_EXTENSIONS.into_iter().try_for_each(|ext| ensure!(base.contains(*ext), Error::MissingCpuExtension()))?; + Self::REQUIRED_EXTENSIONS .into_iter() - .try_for_each(|ext| ensure!(extensions[0].contains(*ext), Error::MissingCpuExtension()))?; - Self::REQUIRED_EXTENSIONS.into_iter().try_for_each(|ext| ensure!(extensions.contains(ext), Error::MissingCpuExtension()))?; + .try_for_each(|ext| ensure!(prop.split('_').any(|item| item == *ext), Error::MissingCpuExtension()))?; Ok(()) } pub fn add_extension(extension: HardwareExtension) -> Result<(), Error> { - Self::try_write(|hardware_setup| Ok(hardware_setup.isa_extensions.push(extension))) + Self::try_write(|hardware_setup| hardware_setup.isa_extensions.push(extension).map_err(|_| Error::Failed())) } pub fn is_extension_supported(extension: HardwareExtension) -> bool { diff --git a/security-monitor/src/core/initialization/mod.rs b/security-monitor/src/core/initialization/mod.rs index ad292b15..2ace3e0f 100644 --- a/security-monitor/src/core/initialization/mod.rs +++ b/security-monitor/src/core/initialization/mod.rs @@ -11,13 +11,15 @@ use crate::core::memory_layout::{ConfidentialMemoryAddress, MemoryLayout}; use crate::core::memory_protector::HypervisorMemoryProtector; use crate::core::page_allocator::{Page, PageAllocator, UnAllocated}; use crate::error::Error; -use alloc::vec::Vec; use core::mem::size_of; +use core::sync::atomic::{AtomicBool, Ordering}; use flattened_device_tree::FlattenedDeviceTree; +use heapless::Vec; use pointers_utility::ptr_byte_add_mut; -use spin::{Mutex, Once}; +use spin::Mutex; const NUMBER_OF_HEAP_PAGES: usize = 80 * 1024; +pub const MAX_SUPPORTED_PHYSICAL_HARTS: usize = 16; unsafe extern "C" { // Assembly function that is an entry point to the security monitor from the hypervisor or a virtual machine. @@ -32,7 +34,10 @@ unsafe extern "C" { /// /// Initialization procedure must guarantee that the mscratch register contains the address of the memory region that /// stores the state of the executing hart. -static HARTS_STATES: Once>> = Once::new(); +static HARTS_STATES: Mutex> = Mutex::new(Vec::new()); + +/// Set to `true` by the cold-boot hart once `prepare_harts()` completes. All other harts spin-wait on this flag +static HARTS_READY: AtomicBool = AtomicBool::new(false); /// The entry point to the security monitor initialization procedure. It should be called by the booting firmware (e.g., /// OpenSBI) during the boot process to initialize ACE. After the return, the control flow returns to the booting @@ -95,8 +100,8 @@ fn verify_harts(fdt: &FlattenedDeviceTree) -> Result { HardwareExtension::all().into_iter().for_each(|ext| { let is_extension_supported_by_all_harts = fdt.harts().all(|hart| { let prop = hart.property_str(FDT_RISCV_ISA).ok_or(Error::FdtParsing()).unwrap_or(""); - let extensions = &prop.split('_').collect::>(); - extensions[0].contains(&ext.code()) || extensions.contains(&ext.code()) + let base = prop.split('_').next().unwrap_or(""); + base.contains(&ext.code()) || prop.split('_').any(|item| item == ext.code()) }); if is_extension_supported_by_all_harts { debug!("Enabling support for extension: {:?}", ext); @@ -193,16 +198,17 @@ fn initalize_security_monitor_state( } fn prepare_harts(number_of_harts: usize) -> Result<(), Error> { + ensure!(number_of_harts <= MAX_SUPPORTED_PHYSICAL_HARTS, Error::InvalidNumberOfHartsInFdt())?; // We need to allocate stack for the dumped state of each physical hart. - let mut harts_states = Vec::with_capacity(number_of_harts); for hart_id in 0..number_of_harts { let stack = PageAllocator::acquire_page(PageSize::Size2MiB)?; let hypervisor_memory_protector = HypervisorMemoryProtector::create(); debug!("Hart[{}] stack \t 0x{:x}-0x{:x}", hart_id, stack.start_address(), stack.end_address()); - harts_states.insert(hart_id, HardwareHart::init(hart_id, stack, hypervisor_memory_protector)); + HARTS_STATES.lock().push(HardwareHart::init(hart_id, stack, hypervisor_memory_protector)).map_err(|_| Error::Failed())?; } - HARTS_STATES.call_once(|| Mutex::new(harts_states)); fence_wo(); + // Signal other harts that HARTS_STATES is fully populated. + HARTS_READY.store(true, Ordering::Release); Ok(()) } @@ -211,7 +217,7 @@ fn prepare_harts(number_of_harts: usize) -> Result<(), Error> { #[unsafe(no_mangle)] extern "C" fn ace_setup_this_hart() { // wait until the boot hart initializes the security monitor's data structures - while !HARTS_STATES.is_completed() { + while !HARTS_READY.load(Ordering::Acquire) { fence_wo(); } @@ -220,8 +226,8 @@ extern "C" fn ace_setup_this_hart() { // OpenSBI requires that mscratch points to an internal OpenSBI's structure. We have to store this pointer during // init and restore it every time we delegate exception/interrupt to the Sbi firmware (e.g., OpenSbi). - let mut harts = HARTS_STATES.get().expect("Bug. Could not set mscratch before initializing memory region for harts states").lock(); - let hart = harts.get_mut(hart_id).expect("Bug. Incorrectly setup memory region for harts states"); + let mut harts = HARTS_STATES.lock(); + let hart = harts.get_mut(hart_id).expect("Bug. Incorrectly set up memory region for harts states"); // The mscratch must point to the memory region when the security monitor stores the dumped states of // confidential harts. This is crucial for context switches because assembly code will use the mscratch @@ -242,7 +248,7 @@ extern "C" fn ace_setup_this_hart() { } // Set up the trap vector, so that the exceptions are handled by the security monitor. - let trap_vector_address = enter_from_hypervisor_or_vm_asm as usize; + let trap_vector_address = enter_from_hypervisor_or_vm_asm as *const () as usize; debug!("Hardware hart id={} registered trap handler at address: {:x}", hart_id, trap_vector_address); hart.hypervisor_hart_mut().csrs_mut().mtvec.write((trap_vector_address >> MTVEC_BASE_SHIFT) << MTVEC_BASE_SHIFT); } diff --git a/security-monitor/src/core/memory_layout/confidential_memory_address.rs b/security-monitor/src/core/memory_layout/confidential_memory_address.rs index c74a4dcf..dafbfe31 100644 --- a/security-monitor/src/core/memory_layout/confidential_memory_address.rs +++ b/security-monitor/src/core/memory_layout/confidential_memory_address.rs @@ -1,9 +1,9 @@ // SPDX-FileCopyrightText: 2023 IBM Corporation // SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich // SPDX-License-Identifier: Apache-2.0 +use super::MemoryLayout; use crate::error::Error; use pointers_utility::{ptr_byte_add_mut, ptr_byte_offset}; -use super::MemoryLayout; /// The wrapper over a raw pointer that is guaranteed to be an address located in the confidential memory region. #[repr(transparent)] @@ -38,7 +38,6 @@ impl ConfidentialMemoryAddress { self.0 as *const u8 } - #[rr::returns("self.(loc_a)")] pub fn as_usize(&self) -> usize { self.0.addr() diff --git a/security-monitor/src/core/memory_layout/non_confidential_memory_address.rs b/security-monitor/src/core/memory_layout/non_confidential_memory_address.rs index a8fa77ef..0e93b05d 100644 --- a/security-monitor/src/core/memory_layout/non_confidential_memory_address.rs +++ b/security-monitor/src/core/memory_layout/non_confidential_memory_address.rs @@ -58,7 +58,10 @@ impl NonConfidentialMemoryAddress { pub unsafe fn add(&self, offset_in_bytes: usize, upper_bound: *const usize) -> Result { let memory_layout = MemoryLayout::read(); ensure!(upper_bound <= memory_layout.non_confidential_memory_end, Error::AddressNotInNonConfidentialMemory())?; - let pointer = ptr_byte_add_mut(self.0, offset_in_bytes, upper_bound).map_err(#[rr::verify] |_| Error::AddressNotInNonConfidentialMemory())?; + let pointer = ptr_byte_add_mut(self.0, offset_in_bytes, upper_bound).map_err( + #[rr::verify] + |_| Error::AddressNotInNonConfidentialMemory(), + )?; Ok(NonConfidentialMemoryAddress(pointer)) } diff --git a/security-monitor/src/core/page_allocator/allocator.rs b/security-monitor/src/core/page_allocator/allocator.rs index 928f7348..57cce0d3 100644 --- a/security-monitor/src/core/page_allocator/allocator.rs +++ b/security-monitor/src/core/page_allocator/allocator.rs @@ -48,8 +48,6 @@ pub struct PageAllocator { #[rr::context("onceG Σ unit")] #[rr::context("MachineConfig")] impl PageAllocator { - const NOT_INITIALIZED: &'static str = "Bug. Page allocator not initialized."; - /// Initializes the global memory allocator with the given memory region as confidential memory. Must be called only once during the /// system initialization. /// @@ -269,13 +267,26 @@ impl PageAllocator { #[rr::ok] #[rr::ensures("if_Ok ret (λ tok, tok.(page_sz) = {page_size_to_allocate})")] |page_allocator| { + let base_address = page_allocator.base_address; + let page_size = page_allocator.page_size; + Ok(page_allocator.root.acquire_page_token(base_address, page_size, page_size_to_allocate)) + }, + )? + } + + /// Consumes the page tokens given by the caller, allowing for their further acquisition. This is equivalent to deallocation of the + /// Releases a single page token back to the PageAllocator without dynamic allocation. + pub fn release_page(released_page: Page) { + let _ = Self::try_write(|page_allocator| { let base_address = page_allocator.base_address; let page_size = page_allocator.page_size; - Ok(page_allocator.root.acquire_page_token(base_address, page_size, page_size_to_allocate)) - })? + let root_node = &mut page_allocator.root; + root_node.store_page_token(base_address, page_size, released_page); + Ok(()) + }) + .unwrap(); } - /// Consumes the page tokens given by the caller, allowing for their further acquisition. This is equivalent to deallocation of the /// physical memory region owned by the returned page tokens. Given vector of pages might contains pages of arbitrary sizes. #[rr::params("MEMORY_CONFIG" : "memory_layout")] /// Precondition: We require the page allocator to be initialized. @@ -288,23 +299,25 @@ impl PageAllocator { #[rr::requires(#iris "once_initialized π \"MEMORY_LAYOUT\" (Some MEMORY_CONFIG)")] #[rr::returns("Ok tt")] |page_allocator| { - let base_address = page_allocator.base_address; - let page_size = page_allocator.page_size; - let root_node = &mut page_allocator.root; - for page_token in released_pages { - #[rr::params("γ")] - #[rr::inv_vars("root_node")] - #[rr::inv("root_node.ghost = γ")] - #[rr::inv("root_node.cur.(max_node_size) = Size128TiB")] - #[rr::inv("root_node.cur.(base_address) = 0%Z")] - #[rr::ignore] - #[allow(unused)] - || {}; - - root_node.store_page_token(base_address, page_size, page_token); - } - Ok(()) - }).unwrap(); + let base_address = page_allocator.base_address; + let page_size = page_allocator.page_size; + let root_node = &mut page_allocator.root; + for page_token in released_pages { + #[rr::params("γ")] + #[rr::inv_vars("root_node")] + #[rr::inv("root_node.ghost = γ")] + #[rr::inv("root_node.cur.(max_node_size) = Size128TiB")] + #[rr::inv("root_node.cur.(base_address) = 0%Z")] + #[rr::ignore] + #[allow(unused)] + || {}; + + root_node.store_page_token(base_address, page_size, page_token); + } + Ok(()) + }, + ) + .unwrap(); //.inspect_err(|_| debug!("Memory leak: failed to store released pages in the page allocator")); } @@ -315,7 +328,6 @@ impl PageAllocator { #[rr::ensures(#iris "{O::Post} π p op x ret")] fn try_write(op: O) -> Result where O: FnOnce(&mut RwLockWriteGuard<'static, PageAllocator>) -> Result { - //op(&mut PAGE_ALLOCATOR.get().expect(Self::NOT_INITIALIZED).write()) op(&mut PAGE_ALLOCATOR.get().unwrap().write()) } } @@ -507,7 +519,6 @@ impl PageStorageTreeNode { /// Creates children for the given node because the node gets created with an empty list of children, expecting that children will be /// created lazily with this function. - /// #[rr::params("smaller_sz")] /// Precondition: the page size argument has to match the node's logical state. #[rr::requires("this_node_page_size = self.cur.(max_node_size)")] @@ -601,7 +612,6 @@ impl PageStorageTreeNode { /// Merges page tokens owned by children. /// Safety: Requires that all children have been initialized. - /// #[rr::params("smaller_sz")] /// Precondition: The children are initialized. #[rr::requires("Hchild_init" : "self.cur.(children_initialized)")] diff --git a/security-monitor/src/core/page_allocator/page.rs b/security-monitor/src/core/page_allocator/page.rs index fd518461..6eb7c8dd 100644 --- a/security-monitor/src/core/page_allocator/page.rs +++ b/security-monitor/src/core/page_allocator/page.rs @@ -159,7 +159,7 @@ impl Page { // Precondition: the offset is within the bound #[rr::requires("Hinrange" : "{self.address}.(loc_a) + (1 + i) * (page_size_in_bytes_Z {smaller_page_size}) ≤ {page_end}.(loc_a)")] #[rr::requires("Hinrange2" : "{page_end}.(loc_a) ≤ MAX_PAGE_ADDR")] - /// Precondition: provenance + // Precondition: provenance #[rr::requires("{self.address}.(loc_p) = ProvAlloc machine_memory_prov")] // Precondition: ownership of this token's memory region #[rr::requires(#type "({self.address} +ₗ (i * page_size_in_bytes_Z {smaller_page_size}))" : "<#> v" @ "array_t (page_size_in_words_nat {smaller_page_size}) (int usize)")] @@ -201,7 +201,7 @@ impl Page { pg.(page_loc).(loc_a) = base_address.(loc_a) + (i * page_size_in_bytes_Z pg.(page_sz))" )] #[rr::returns("mk_page base_address new_size (mjoin (page_val <$> from_pages))")] - pub unsafe fn merge(mut from_pages: Vec>, new_size: PageSize) -> Self { + pub unsafe fn merge(from_pages: Vec>, new_size: PageSize) -> Self { let base_address = vec_index(&from_pages, 0).address; let smaller_sz = vec_index(&from_pages, 0).size; let pages_len = from_pages.len(); diff --git a/security-monitor/src/debug.rs b/security-monitor/src/debug.rs index 160dc909..cb7c53ff 100644 --- a/security-monitor/src/debug.rs +++ b/security-monitor/src/debug.rs @@ -88,7 +88,8 @@ macro_rules! debug { ($fmt:expr, $($args:tt)+) => {{}}; } -pub(crate) use {_debug, debug}; +pub(crate) use _debug; +pub(crate) use debug; pub struct Console {} diff --git a/security-monitor/src/lib.rs b/security-monitor/src/lib.rs index bc02078d..ea209ad5 100644 --- a/security-monitor/src/lib.rs +++ b/security-monitor/src/lib.rs @@ -63,5 +63,4 @@ mod rr_wrappers { pub fn vec_iter_mut(x: &mut Vec) -> core::slice::IterMut<'_, T> { x.iter_mut() } - } diff --git a/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs b/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs index cf307121..891208ac 100644 --- a/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs +++ b/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs @@ -14,8 +14,8 @@ use crate::core::time_controller::TimeController; use crate::error::Error; use crate::non_confidential_flow::handlers::supervisor_binary_interface::SbiResponse; use crate::non_confidential_flow::{ApplyToHypervisorHart, NonConfidentialFlow}; -use alloc::vec::Vec; use flattened_device_tree::FlattenedDeviceTree; +use heapless::Vec; use riscv_cove_tap::{AttestationPayload, AttestationPayloadParser, Secret}; /// Creates a confidential VM in a single-step. This handler implements the Promote to TVM call defined by the COVH ABI in the CoVE @@ -72,7 +72,7 @@ impl PromoteToConfidentialVm { SbiResponse::error(error) } }; - PageAllocator::release_pages(alloc::vec![large_page.deallocate()]); + PageAllocator::release_page(large_page.deallocate()); non_confidential_flow.apply_and_exit_to_hypervisor(ApplyToHypervisorHart::PromoteResponse((self, sbi_response))) } @@ -89,42 +89,54 @@ impl PromoteToConfidentialVm { let (vm_memory_layout, number_of_confidential_harts) = self.process_device_tree(large_page, &memory_protector, &fdt_address)?; debug!("Number of confidential harts: {}", number_of_confidential_harts); - // We create a fixed number of harts (all but the boot hart are in the reset state). - let confidential_harts: Vec<_> = (0..number_of_confidential_harts) - .map(|id| match id { + ensure!(number_of_confidential_harts <= ConfidentialVm::MAX_NUMBER_OF_HARTS_PER_VM, Error::InvalidNumberOfHartsInFdt())?; + let mut harts_locks = Vec::new(); + let mut remote_commands = heapless::FnvIndexMap::new(); + for id in 0..number_of_confidential_harts { + let hart = match id { Self::BOOT_HART_ID => { ConfidentialHart::from_vm_hart(id, self.program_counter, &fdt_address, self.htimedelta, shared_memory) } _ => ConfidentialHart::from_vm_hart_reset(id, self.htimedelta, shared_memory), - }) - .collect(); + }; + let hart_id = hart.confidential_hart_id(); + harts_locks.push(spin::RwLock::new(hart)).map_err(|_| Error::InvalidNumberOfHartsInFdt())?; + remote_commands.insert(hart_id, spin::Mutex::new(Vec::new())).map_err(|_| Error::InvalidNumberOfHartsInFdt())?; + } let payload = self .read_attestation_payload(large_page, &memory_protector) .inspect_err(|e| debug!("TAP reading failed: {:?}", e)) .unwrap_or(None); - let measurements = self.measure(&mut memory_protector, &vm_memory_layout, &confidential_harts)?; + let measurements = self.measure(&mut memory_protector, &vm_memory_layout, &harts_locks)?; let secrets = self .authenticate_and_authorize_vm(payload, &measurements) .inspect_err(|e| debug!("Local attestation failed: {:?}", e)) - .unwrap_or(alloc::vec![]); + .unwrap_or_default(); ControlDataStorage::try_write(|control_data| { // We have a write lock on the entire control data! Spend here as little time as possible because we are // blocking all other harts from accessing the control data. This influences all confidential VMs in the system! let id = control_data.unique_id()?; - control_data.insert_confidential_vm(ConfidentialVm::new(id, confidential_harts, measurements, secrets, memory_protector)) + control_data.insert_confidential_vm(ConfidentialVm::new( + id, + harts_locks, + remote_commands, + measurements, + secrets, + memory_protector, + )?) }) } - fn measure( + fn measure( &self, memory_protector: &mut ConfidentialVmMemoryProtector, vm_memory_layout: &ConfidentialVmMemoryLayout, - confidential_harts: &Vec, + confidential_harts: &Vec, N>, ) -> Result { let mut measurements = StaticMeasurements::default(); memory_protector.finalize(&mut measurements, vm_memory_layout)?; - confidential_harts[Self::BOOT_HART_ID].measure(measurements.pcr_boot_hart_mut()); + confidential_harts[Self::BOOT_HART_ID].read().measure(measurements.pcr_boot_hart_mut()); debug!("VM measurements: {:?}", measurements); Ok(measurements) } @@ -198,7 +210,7 @@ impl PromoteToConfidentialVm { /// for this confidential VM. fn authenticate_and_authorize_vm( &self, attestation_payload: Option, measurements: &StaticMeasurements, - ) -> Result, Error> { + ) -> Result, Error> { use crate::core::control_data::MeasurementDigest; match attestation_payload { Some(attestation_payload) => { @@ -210,9 +222,13 @@ impl PromoteToConfidentialVm { ensure!(measurements.compare(digest.pcr_id() as usize, pcr_value)?, Error::LocalAttestationFailed())?; } debug!("Attestation succeeded, fetched {} secrets", attestation_payload.secrets.len()); - Ok(attestation_payload.secrets) + let mut secrets = Vec::new(); + for secret in attestation_payload.secrets { + secrets.push(secret).map_err(|_| Error::LocalAttestationFailed())?; + } + Ok(secrets) } - None => Ok(alloc::vec![]), + None => Ok(Vec::new()), } } diff --git a/tools/cove_tap_tool/Cargo.lock b/tools/cove_tap_tool/Cargo.lock index 9fef3d02..f4e0e1a9 100644 --- a/tools/cove_tap_tool/Cargo.lock +++ b/tools/cove_tap_tool/Cargo.lock @@ -4,44 +4,44 @@ version = 4 [[package]] name = "aead" -version = "0.6.0-rc.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" +checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99" dependencies = [ - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.2", "inout", ] [[package]] name = "aes" -version = "0.9.0-rc.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e713c57c2a2b19159e7be83b9194600d7e8eb3b7c2cd67e671adf47ce189a05" +checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" dependencies = [ - "cfg-if", "cipher", - "cpufeatures", + "cpubits", + "cpufeatures 0.3.1", ] [[package]] name = "aes-gcm" -version = "0.11.0-rc.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686ba04dc80c816104c96cd7782b748f6ad58c5dd4ee619ff3258cf68e83d54" +checksum = "7f2b8006a0c83f52b62ba44a97b58bf76fe2f70a329e588f67f89691d93d498f" dependencies = [ "aead", "aes", "cipher", "ctr", + "ctutils", "ghash", - "subtle", ] [[package]] name = "anstream" -version = "0.6.18" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -54,33 +54,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.8" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", @@ -89,9 +89,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "block-buffer" @@ -104,11 +104,11 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.11.0-rc.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ - "hybrid-array 0.4.5", + "hybrid-array 0.4.15", ] [[package]] @@ -119,26 +119,26 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "cipher" -version = "0.5.0-rc.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" dependencies = [ - "block-buffer 0.11.0-rc.5", - "crypto-common 0.2.0-rc.4", + "block-buffer 0.12.1", + "crypto-common 0.2.2", "inout", ] [[package]] name = "clap" -version = "4.5.39" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", "clap_derive", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.39" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", @@ -167,27 +167,33 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.101", + "syn 3.0.6", ] [[package]] name = "clap_lex" -version = "0.7.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" + +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "cove-tap-tool" @@ -196,11 +202,18 @@ dependencies = [ "byteorder", "clap", "clap-num", + "heapless", "riscv_cove_tap", - "sha3", + "sha3 0.10.9", "thiserror", ] +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -210,11 +223,20 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array 0.14.7", "typenum", @@ -222,23 +244,32 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.0-rc.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "hybrid-array 0.4.5", - "rand_core 0.9.3", + "hybrid-array 0.4.15", + "rand_core 0.10.1", ] [[package]] name = "ctr" -version = "0.10.0-rc.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e41d01c6f73b9330177f5cf782ae5b581b5f2c7840e298e0275ceee5001434" +checksum = "baaca1c4b237092596f64d571e9db6ce4109c4ef9742e27590f1709594461f21" dependencies = [ "cipher", ] +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "digest" version = "0.10.7" @@ -246,7 +277,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "crypto-common 0.1.6", + "crypto-common 0.1.7", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "crypto-common 0.2.2", ] [[package]] @@ -261,9 +302,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "1.3.3" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42bb3faf529935fbba0684910e1a71ecd271d618549d58f430b878619b7f4cf" +checksum = "337d46834ee672ab3e48caca2cb0c78cc174fb12b3a68d0d88f99a0519a5e36e" dependencies = [ "rustversion", "typenum", @@ -271,9 +312,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", @@ -282,13 +323,32 @@ dependencies = [ [[package]] name = "ghash" -version = "0.6.0-rc.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f88107cb02ed63adcc4282942e60c4d09d80208d33b360ce7c729ce6dae1739" +checksum = "2eecf2d5dc9b66b732b97707a0210906b1d30523eb773193ab777c0c84b3e8d5" dependencies = [ "polyval", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -306,63 +366,86 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.4.5" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" dependencies = [ + "ctutils", "typenum", ] [[package]] name = "inout" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7357b6e7aa75618c7864ebd0634b115a7218b0615f4cb1df33ac3eca23943d4" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ - "hybrid-array 0.4.5", + "hybrid-array 0.4.15", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", +] + +[[package]] +name = "keccak" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f198d1db720e4940b5a493201d199d9f24f568f8f746bd13706243a2f71598" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", ] [[package]] name = "kem" -version = "0.3.0-pre.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8645470337db67b01a7f966decf7d0bafedbae74147d33e641c67a91df239f" +checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd" dependencies = [ - "rand_core 0.6.4", - "zeroize", + "crypto-common 0.2.2", + "rand_core 0.10.1", ] [[package]] name = "libc" -version = "0.2.172" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "ml-kem" -version = "0.3.0-pre" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fde1200e61dd95a2c6143baa22dbab79d8dad2644f55e955dd8a3d535f5d9f" +checksum = "5e15f3e5b957493873e396a66914e83e616b6afe335cdef7efe5c6e1216aba66" dependencies = [ - "hybrid-array 0.2.3", + "hybrid-array 0.4.15", "kem", - "rand_core 0.6.4", - "sha3", + "module-lattice", + "rand_core 0.10.1", + "sha3 0.11.0", +] + +[[package]] +name = "module-lattice" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c61b87c9683ab7cb1c6871d261ad5479b6b10ceb52c4352aaca3b5d35a8febe" +dependencies = [ + "ctutils", + "hybrid-array 0.4.15", + "num-traits", ] [[package]] @@ -376,18 +459,18 @@ dependencies = [ [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "polyval" -version = "0.7.0-rc.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffd40cc99d0fbb02b4b3771346b811df94194bc103983efa0203c8893755085" +checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd" dependencies = [ - "cfg-if", - "cpufeatures", + "cpubits", + "cpufeatures 0.3.1", "universal-hash", ] @@ -402,27 +485,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" dependencies = [ "libc", "rand_chacha", @@ -450,16 +533,17 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "riscv_cove_tap" version = "0.2.0" dependencies = [ "aes-gcm", - "generic-array 1.3.3", + "generic-array 1.4.5", + "heapless", "hybrid-array 0.2.3", "ml-kem", "rand", @@ -468,20 +552,36 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "sha3" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" +dependencies = [ + "digest 0.10.7", + "keccak 0.1.6", +] [[package]] name = "sha3" -version = "0.10.8" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" dependencies = [ - "digest", - "keccak", + "digest 0.11.3", + "keccak 0.2.2", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "strsim" version = "0.11.1" @@ -489,16 +589,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "subtle" -version = "2.6.1" +name = "syn" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] name = "syn" -version = "1.0.109" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -507,9 +612,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ "proc-macro2", "quote", @@ -518,22 +623,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 3.0.6", ] [[package]] @@ -558,24 +663,24 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" [[package]] name = "universal-hash" -version = "0.6.0-rc.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" +checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96" dependencies = [ - "crypto-common 0.2.0-rc.4", - "subtle", + "crypto-common 0.2.2", + "ctutils", ] [[package]] @@ -597,100 +702,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "windows-sys" -version = "0.59.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-targets" -version = "0.52.6" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.101", + "syn 2.0.119", ] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/tools/cove_tap_tool/Cargo.toml b/tools/cove_tap_tool/Cargo.toml index d2d81d72..dc21737d 100644 --- a/tools/cove_tap_tool/Cargo.toml +++ b/tools/cove_tap_tool/Cargo.toml @@ -6,6 +6,7 @@ description = "Tool to create TVM attestation payload for CoVE's confidential VM edition = "2021" [dependencies] +heapless = { version = "0.8", default-features = false } clap = { version="4.5", features = ["derive"] } # for command line argument parsing clap-num = "1.2.0" byteorder = "1.5" # to serialize numbers using little/big endianness diff --git a/tools/cove_tap_tool/src/generate.rs b/tools/cove_tap_tool/src/generate.rs index 26dd0c77..dde88914 100644 --- a/tools/cove_tap_tool/src/generate.rs +++ b/tools/cove_tap_tool/src/generate.rs @@ -3,13 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::ensure; use crate::error::Error; -use riscv_cove_tap::AttestationPayload; -use riscv_cove_tap::AttestationPayloadSerializer; -use riscv_cove_tap::Digest; -use riscv_cove_tap::DigestAlgorithm; -use riscv_cove_tap::Lockbox; -use riscv_cove_tap::LockboxAlgorithm; -use riscv_cove_tap::Secret; +use riscv_cove_tap::{ + AttestationPayload, AttestationPayloadSerializer, Digest, DigestAlgorithm, Lockbox, + LockboxAlgorithm, Secret, MAX_DIGEST_VALUE_SIZE, MAX_NUMBER_OF_DIGESTS, + MAX_NUMBER_OF_LOCKBOXES, MAX_NUMBER_OF_SECRETS, MAX_SECRET_VALUE_SIZE, MAX_TSK_SIZE, +}; use std::fs::OpenOptions; use std::io::Write; @@ -20,18 +18,34 @@ pub fn generate_tap( output_file: String, ) -> Result<(), Error> { ensure!( - confidential_vm_secrets.len() < 256, - Error::InvalidParameter(format!("Confidential VM can receive maximum 256 secrets")) + confidential_vm_secrets.len() <= MAX_NUMBER_OF_SECRETS, + Error::InvalidParameter(format!( + "Too many secrets: max {} allowed", + MAX_NUMBER_OF_SECRETS + )) )?; ensure!( - tee_public_keys_files.len() < 1024, - Error::InvalidParameter(format!("Confidential VM TAP supports max 1024 lockboxes")) + tee_public_keys_files.len() <= MAX_NUMBER_OF_LOCKBOXES, + Error::InvalidParameter(format!( + "Too many lockboxes: max {} allowed", + MAX_NUMBER_OF_LOCKBOXES + )) + )?; + ensure!( + pcrs.len() <= MAX_NUMBER_OF_DIGESTS, + Error::InvalidParameter(format!( + "Too many PCR digests: max {} allowed", + MAX_NUMBER_OF_DIGESTS + )) )?; - let mut symmetric_key = vec![0u8; 32]; + let mut symmetric_key: heapless::Vec = heapless::Vec::new(); + symmetric_key + .extend_from_slice(&[0u8; 32]) + .map_err(|_| Error::InvalidParameter("symmetric_key too large".into()))?; let lockbox_algorithm = LockboxAlgorithm::MlKem1024Aes256; - let test_encapsulation_key = "307A4CEA4148219B958EA0B7886659235A4D1980B192610847D86EF32739F94C3B446C4D81D89B8B422A9D079C88B11ACAF321B014294E18B296E52F3F744CF9634A4FB01DB0D99EF20A633A552E76A0585C6109F018768B763AF3678B4780089C1342B96907A29A1C11521C744C2797D0BF2B9CCDCA614672B45076773F458A31EF869BE1EB2EFEB50D0E37495DC5CA55E07528934F6293C4168027D0E53D07FACC6630CB08197E53FB193A171135DC8AD9979402A71B6926BCDCDC47B93401910A5FCC1A813B682B09BA7A72D2486D6C799516465C14729B26949B0B7CBC7C640F267FED80B162C51FD8E09227C101D505A8FAE8A2D7054E28A78BA8750DECF9057C83979F7ABB084945648006C5B28804F34E73B238111A65A1F500B1CC606A848F2859070BEBA7573179F36149CF5801BF89A1C38CC278415528D03BDB943F96280C8CC52042D9B91FAA9D6EA7BCBB7AB1897A3266966F78393426C76D8A49578B98B159EBB46EE0A883A270D8057CD0231C86906A91DBBADE6B2469581E2BCA2FEA8389F7C74BCD70961EA5B934FBCF9A6590BF86B8DB548854D9A3FB30110433BD7A1B659CA8568085639237B3BDC37B7FA716D482A25B54106B3A8F54D3AA99B5123DA96066904592F3A54EE23A7981AB608A2F4413CC658946C6D7780EA765644B3CC06C70034AB4EB351912E7715B56755D09021571BF340AB92598A24E811893195B96A1629F8041F58658431561FC0AB15292B913EC473F04479BC145CD4C563A286235646CD305A9BE1014E2C7B130C33EB77CC4A0D9786BD6BC2A954BF3005778F8917CE13789BBB962807858B67731572B6D3C9B4B5206FAC9A7C8961698D88324A915186899B29923F08442A3D386BD416BCC9A100164C930EC35EAFB6AB35851B6C8CE6377366A175F3D75298C518D44898933F53DEE617145093379C4659F68583B2B28122666BEC57838991FF16C368DD22C36E780C91A3582E25E19794C6BF2AB42458A8DD7705DE2C2AA20C054E84B3EF35032798626C248263253A71A11943571340A978CD0A602E47DEE540A8814BA06F31414797CDF6049582361BBABA387A83D89913FE4C0C112B95621A4BDA8123A14D1A842FB57B83A4FBAF33A8E552238A596AAE7A150D75DA648BC44644977BA1F87A4C68A8C4BD245B7D00721F7D64E822B085B901312EC37A8169802160CCE1160F010BE8CBCACE8E7B005D7839234A707868309D03784B4273B1C8A160133ED298184704625F29CFA086D13263EE5899123C596BA788E5C54A8E9BA829B8A9D904BC4BC0BBEA76BC53FF811214598472C9C202B73EFF035DC09703AF7BF1BABAAC73193CB46117A7C9492A43FC95789A924C5912787B2E2090EBBCFD3796221F06DEBF9CF70E056B8B9161D6347F47335F3E1776DA4BB87C15CC826146FF0249A413B45AA93A805196EA453114B524E310AEDAA46E3B99642368782566D049A726D6CCA910993AED621D0149EA588A9ABD909DBB69AA22829D9B83ADA2209A6C2659F2169D668B9314842C6E22A74958B4C25BBDCD293D99CB609D866749A485DFB56024883CF5465DBA0363206587F45597F89002FB8607232138E03B2A894525F265370054B48863614472B95D0A2303442E378B0DD1C75ACBAB971A9A8D1281C79613ACEC6933C377B3C578C2A61A1EC181B101297A37CC5197B2942F6A0E4704C0EC63540481B9F159DC255B59BB55DF496AE54217B7689BD51DBA0383A3D72D852FFCA76DF05B66EECCBD47BC53040817628C71E361D6AF889084916B408A466C96E7086C4A60A10FCF7537BB94AFBCC7D437590919C28650C4F2368259226A9BFDA3A3A0BA1B5087D9D76442FD786C6F81C68C0360D7194D7072C4533AEA86C2D1F8C0A27696066F6CFD11003F797270B32389713CFFA093D991B63844C385E72277F166F5A3934D6BB89A4788DE28321DEFC7457AB484BD30986DC1DAB3008CD7B22F69702FABB9A1045407DA4791C3590FF599D81D688CFA7CC12A68C50F51A1009411B44850F9015DC84A93B17C7A207552C661EA9838E31B95EAD546248E56BE7A5130505268771199880A141771A9E47ACFED590CB3AA7CB7C5F74911D8912C29D6233F4D53BC64139E2F55BE75507DD77868E384AEC581F3F411DB1A742972D3EBFD3315C84A5AD63A0E75C8BCA3E3041E05D9067AFF3B1244F763E7983"; - let encapsulation_key = (0..test_encapsulation_key.len()) + let test_encapsulation_key = "307A4CEA4148219B958EA0B7886659235A4D1980B192610847D86EF32739F94C3B446C4D81D89B8B422A9D079C88B11ACAF321B014294E18B296E52F3F744CF9634A4FB01DB0D99EF20A633A552E76A0585C6109F018768B763AF3678B4780089C1342B96907A29A1C11521C744C2797D0BF2B9CCDCA614672B45076773F458A31EF869BE1EB2EFEB50D0E37495DC5CA55E07528934F6293C4168027D0E53D07FACC6630CB08197E53FB193A171135DC8AD9979402A71B6926BCDCDC47B93401910A5FCC1A813B682B09BA7A72D2486D6C799516465C14729B26949B0B7CBC7C640F267FED80B162C51FD8E09227C101D505A8FAE8A2D7054E28A78BA8750DECF9057C83979F7ABB084945648006C5B28804F34E73B238111A65A1F500B1CC606A848F2859070BEBA7573179F36149CF5801BF89A1C38CC278415528D03BDB943F96280C8CC52042D9B91FAA9D6EA7BCBB7AB1897A3266966F78393426C76D8A49578B98B159EBB46EE0A883A270D8057CD0231C86906A91DBBADE6B2469581E2BCA2FEA8389F7C74BCD70961EA5B934FBCF9A6590BF86B8DB548854D9A3FB30110433BD7A1B659CA8568085639237B3BDC37B7FA716D482A25B54106B3A8F54D3AA99B5123DA96066904592F3A54EE23A7981AB608A2F4413CC658946C6D7780EA765644B3CC06C70034AB4EB351912E7715B56755D09021571BF340AB92598A24E811893195B96A1629F8041F58658431561FC0AB15292B913EC473F04479BC145CD4C563A286235646CD305A9BE1014E2C7B130C33EB77CC4A0D9786BD6BC2A954BF3005778F8917CE13789BBB962807858B67731572B6D3C9B4B5206FAC9A7C8961698D88324A915186899B29923F08442A3D386BD416BCC9A100164C930EC35EAFB6AB35851B6C8CE6377366A175F3D75298C518D44898933F53DEE617145093379C4659F68583B2B28122666BEC57838991FF16C368DD22C36E780C91A3582E25E19794C6BF2AB42458A8DD7705DE2C2AA20C054E84B3EF35032798626C248263253A71A11943571340A978CD0A602E47DEE540A8814BA06F31414797CDF6049582361BBABA387A83D89913FE4C0C112B95621A4BDA8123A14D1A842FB57B83A4FBAF33A8E552238A596AAE7A150D75DA648BC44644977BA1F87A4C68A8C4BD245B7D00721F7D64E822B085B901312EC37A8169802160CCE1160F010BE8CBCACE8E7B005D7839234A707868309D03784B4273B1C8A160133ED298184704625F29CFA086D13263EE5899123C596BA788E5C54A8E9BA829B8A9D904BC4BC0BBEA76BC53FF811214598472C9C202B73EFF035DC09703AF7BF1BABAAC73193CB46117A7C9492A43FC95789A924C5912787B2E2090EBB"; + let encapsulation_key: Vec = (0..test_encapsulation_key.len()) .step_by(2) .map(|i| { test_encapsulation_key @@ -41,32 +55,82 @@ pub fn generate_tap( }) .collect(); - let mut lockboxes = vec![]; - lockboxes.push(Lockbox::new( - lockbox_algorithm, - &encapsulation_key, - &mut symmetric_key, - )?); + let mut lockboxes: heapless::Vec = heapless::Vec::new(); + lockboxes + .push(Lockbox::new( + lockbox_algorithm, + &encapsulation_key, + &mut symmetric_key, + )?) + .map_err(|_| { + Error::InvalidParameter(format!( + "Too many lockboxes: max {} allowed", + MAX_NUMBER_OF_LOCKBOXES + )) + })?; - let mut digests = vec![]; + let mut digests: heapless::Vec = heapless::Vec::new(); for (pcr_id, pcr_value) in pcrs.into_iter() { + ensure!( + pcr_value.len() <= MAX_DIGEST_VALUE_SIZE, + Error::InvalidParameter(format!( + "PCR{} value is {} bytes, max is {}", + pcr_id, + pcr_value.len(), + MAX_DIGEST_VALUE_SIZE + )) + )?; + let mut value: heapless::Vec = heapless::Vec::new(); + value.extend_from_slice(&pcr_value).map_err(|_| { + Error::InvalidParameter(format!( + "PCR{} value exceeds {} bytes", + pcr_id, MAX_DIGEST_VALUE_SIZE + )) + })?; let tap_digest = Digest { pcr_id, algorithm: DigestAlgorithm::Sha512, - value: pcr_value, + value, }; println!("Writing PCR{}={}", pcr_id, tap_digest.value_in_hex()); - digests.push(tap_digest); + digests.push(tap_digest).map_err(|_| { + Error::InvalidParameter(format!( + "Too many digests: max {} allowed", + MAX_NUMBER_OF_DIGESTS + )) + })?; } - let mut secrets = vec![]; + let mut secrets: heapless::Vec = heapless::Vec::new(); for (secret_name, secret_value) in confidential_vm_secrets.into_iter() { - let secret = Secret { - name: secret_name, - value: secret_value, - }; + ensure!( + secret_value.len() <= MAX_SECRET_VALUE_SIZE, + Error::InvalidParameter(format!( + "Secret {} value is {} bytes, max is {}", + secret_name, + secret_value.len(), + MAX_SECRET_VALUE_SIZE + )) + )?; + let mut value: heapless::Vec = heapless::Vec::new(); + value.extend_from_slice(&secret_value).map_err(|_| { + Error::InvalidParameter(format!( + "Secret {} value exceeds {} bytes", + secret_name, MAX_SECRET_VALUE_SIZE + )) + })?; println!("Writing secret {}", secret_name); - secrets.push(secret); + secrets + .push(Secret { + name: secret_name, + value, + }) + .map_err(|_| { + Error::InvalidParameter(format!( + "Too many secrets: max {} allowed", + MAX_NUMBER_OF_SECRETS + )) + })?; } let tap = AttestationPayload { digests, secrets }; @@ -74,7 +138,6 @@ pub fn generate_tap( let serializer = AttestationPayloadSerializer::new(); let serialized = serializer.serialize(lockboxes, tap)?; - // write the entire TAP to the output file let mut output = OpenOptions::new() .create_new(true) .read(true)