diff --git a/Cargo.lock b/Cargo.lock index d281808..f53b0c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,21 +18,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "adler32" -version = "1.2.0" +name = "aead" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - -[[package]] -name = "ahash" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", + "crypto-common", + "generic-array", + "heapless", ] [[package]] @@ -131,6 +124,15 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "atty" version = "0.2.14" @@ -204,6 +206,24 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "build-deps" version = "0.1.4" @@ -256,6 +276,30 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + [[package]] name = "ciborium" version = "0.2.1" @@ -283,6 +327,17 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "clang-sys" version = "1.6.1" @@ -371,21 +426,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] -name = "core2" -version = "0.4.0" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "memchr", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", + "libc", ] [[package]] @@ -424,6 +470,12 @@ dependencies = [ "itertools", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -458,10 +510,14 @@ dependencies = [ ] [[package]] -name = "dary_heap" -version = "0.3.6" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7762d17f1241643615821a8455a0b2c3e803784b058693d990b11f2dce25a0ca" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] [[package]] name = "derive_arbitrary" @@ -474,6 +530,17 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -516,34 +583,13 @@ dependencies = [ ] [[package]] -name = "filetime" -version = "0.2.22" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "windows-sys 0.48.0", -] - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", + "typenum", + "version_check", ] [[package]] @@ -575,27 +621,40 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "spin", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -632,16 +691,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "indexmap" version = "1.9.3" @@ -662,6 +711,15 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "is-terminal" version = "0.4.9" @@ -724,30 +782,6 @@ version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" -[[package]] -name = "libflate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7d5654ae1795afc7ff76f4365c2c8791b0feb18e8996a96adad8ffd7c3b2bf" -dependencies = [ - "adler32", - "core2", - "crc32fast", - "dary_heap", - "libflate_lz77", -] - -[[package]] -name = "libflate_lz77" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5f52fb8c451576ec6b79d3f4deb327398bc05bbdbd99021a6e77a4c855d524" -dependencies = [ - "core2", - "hashbrown 0.13.2", - "rle-decode-fast", -] - [[package]] name = "libfuzzer-sys" version = "0.4.7" @@ -769,29 +803,22 @@ dependencies = [ "winapi", ] -[[package]] -name = "libsodium-sys-stable" -version = "1.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1d164bc6f9139c5f95efb4f0be931b2bd5a9edf7e4e3c945d26b95ab8fa669b" -dependencies = [ - "cc", - "libc", - "libflate", - "minisign-verify", - "pkg-config", - "tar", - "ureq", - "vcpkg", - "zip", -] - [[package]] name = "linux-raw-sys" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.20" @@ -830,12 +857,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "minisign-verify" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -897,6 +918,12 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "oqs-sys" version = "0.8.0" @@ -927,18 +954,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - [[package]] name = "plotters" version = "0.3.5" @@ -967,6 +982,17 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1060,15 +1086,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" version = "1.10.2" @@ -1098,26 +1115,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" -[[package]] -name = "ring" -version = "0.17.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.48.0", -] - -[[package]] -name = "rle-decode-fast" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" - [[package]] name = "rosenpass" version = "0.2.1" @@ -1126,7 +1123,6 @@ dependencies = [ "clap 4.4.10", "criterion", "env_logger", - "libsodium-sys-stable", "log", "memoffset", "mio", @@ -1137,7 +1133,6 @@ dependencies = [ "rosenpass-constant-time", "rosenpass-lenses", "rosenpass-secret-memory", - "rosenpass-sodium", "rosenpass-to", "rosenpass-util", "serde", @@ -1157,11 +1152,13 @@ name = "rosenpass-ciphers" version = "0.1.0" dependencies = [ "anyhow", + "blake2", + "chacha20poly1305", "rosenpass-constant-time", "rosenpass-oqs", "rosenpass-secret-memory", - "rosenpass-sodium", "rosenpass-to", + "rosenpass-util", "static_assertions", "zeroize", ] @@ -1170,6 +1167,7 @@ dependencies = [ name = "rosenpass-constant-time" version = "0.1.0" dependencies = [ + "memsec", "rosenpass-to", ] @@ -1183,7 +1181,6 @@ dependencies = [ "rosenpass-cipher-traits", "rosenpass-ciphers", "rosenpass-secret-memory", - "rosenpass-sodium", "rosenpass-to", "stacker", ] @@ -1213,28 +1210,14 @@ dependencies = [ "allocator-api2", "allocator-api2-tests", "anyhow", - "libsodium-sys-stable", "log", "memsec", "rand", - "rosenpass-sodium", "rosenpass-to", "rosenpass-util", "zeroize", ] -[[package]] -name = "rosenpass-sodium" -version = "0.1.0" -dependencies = [ - "allocator-api2", - "anyhow", - "libsodium-sys-stable", - "log", - "rosenpass-to", - "rosenpass-util", -] - [[package]] name = "rosenpass-to" version = "0.1.0" @@ -1248,6 +1231,8 @@ version = "0.1.0" dependencies = [ "anyhow", "base64", + "static_assertions", + "typenum", ] [[package]] @@ -1262,6 +1247,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.26" @@ -1275,28 +1269,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rustls" -version = "0.21.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "ryu" version = "1.0.15" @@ -1319,14 +1291,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "sct" -version = "0.7.1" +name = "semver" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" @@ -1379,6 +1347,15 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" @@ -1405,6 +1382,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "2.0.39" @@ -1416,17 +1399,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tar" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" -dependencies = [ - "filetime", - "libc", - "xattr", -] - [[package]] name = "termcolor" version = "1.4.0" @@ -1478,21 +1450,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "toml" version = "0.7.8" @@ -1528,10 +1485,10 @@ dependencies = [ ] [[package]] -name = "unicode-bidi" -version = "0.3.13" +name = "typenum" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" @@ -1540,44 +1497,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-normalization" -version = "0.1.22" +name = "universal-hash" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "tinyvec", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "ureq" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" -dependencies = [ - "base64", - "log", - "once_cell", - "rustls", - "rustls-webpki", - "url", - "webpki-roots", -] - -[[package]] -name = "url" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", + "crypto-common", + "subtle", ] [[package]] @@ -1586,12 +1512,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" @@ -1678,12 +1598,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" - [[package]] name = "which" version = "4.4.2" @@ -1934,49 +1848,8 @@ dependencies = [ "memchr", ] -[[package]] -name = "xattr" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" -dependencies = [ - "libc", -] - -[[package]] -name = "zerocopy" -version = "0.7.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "byteorder", - "crc32fast", - "crossbeam-utils", - "flate2", -] diff --git a/Cargo.toml b/Cargo.toml index 155abd3..35d7386 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ members = [ "ciphers", "util", "constant-time", - "sodium", "oqs", "to", "fuzz", @@ -27,7 +26,6 @@ tag-prefix = "" rosenpass = { path = "rosenpass" } rosenpass-util = { path = "util" } rosenpass-constant-time = { path = "constant-time" } -rosenpass-sodium = { path = "sodium" } rosenpass-cipher-traits = { path = "cipher-traits" } rosenpass-ciphers = { path = "ciphers" } rosenpass-to = { path = "to" } @@ -51,11 +49,13 @@ allocator-api2 = "0.2.14" allocator-api2-tests = "0.2.14" memsec = "0.6.3" rand = "0.8.5" +typenum = "1.17.0" log = { version = "0.4.20" } clap = { version = "4.4.10", features = ["derive"] } serde = { version = "1.0.193", features = ["derive"] } arbitrary = { version = "1.3.2", features = ["derive"] } anyhow = { version = "1.0.75", features = ["backtrace", "std"] } mio = { version = "0.8.9", features = ["net", "os-poll"] } -libsodium-sys-stable= { version = "1.20.4", features = ["use-pkg-config"] } -oqs-sys = { version = "0.8", default-features = false, features = ['classic_mceliece', 'kyber'] } \ No newline at end of file +oqs-sys = { version = "0.8", default-features = false, features = ['classic_mceliece', 'kyber'] } +blake2 = "0.10.6" +chacha20poly1305 = { version = "0.10.1", default-features = false, features = [ "std", "heapless" ] } diff --git a/ciphers/Cargo.toml b/ciphers/Cargo.toml index a226239..5475042 100644 --- a/ciphers/Cargo.toml +++ b/ciphers/Cargo.toml @@ -11,10 +11,12 @@ readme = "readme.md" [dependencies] anyhow = { workspace = true } -rosenpass-sodium = { workspace = true } rosenpass-to = { workspace = true } rosenpass-constant-time = { workspace = true } rosenpass-secret-memory = { workspace = true } rosenpass-oqs = { workspace = true } +rosenpass-util = { workspace = true } static_assertions = { workspace = true } zeroize = { workspace = true } +chacha20poly1305 = { workspace = true } +blake2 = { workspace = true } diff --git a/ciphers/src/lib.rs b/ciphers/src/lib.rs index 994431b..d57bd00 100644 --- a/ciphers/src/lib.rs +++ b/ciphers/src/lib.rs @@ -9,14 +9,12 @@ const_assert!(KEY_LEN == hash_domain::KEY_LEN); /// Authenticated encryption with associated data pub mod aead { - pub use rosenpass_sodium::aead::chacha20poly1305_ietf::{ - decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN, - }; + pub use crate::subtle::chacha20poly1305_ietf::{decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN}; } /// Authenticated encryption with associated data with a constant nonce pub mod xaead { - pub use rosenpass_sodium::aead::xchacha20poly1305_ietf::{ + pub use crate::subtle::xchacha20poly1305_ietf::{ decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN, }; } diff --git a/ciphers/src/subtle/blake2b.rs b/ciphers/src/subtle/blake2b.rs new file mode 100644 index 0000000..4f8933d --- /dev/null +++ b/ciphers/src/subtle/blake2b.rs @@ -0,0 +1,42 @@ +use zeroize::Zeroizing; + +use blake2::digest::crypto_common::generic_array::GenericArray; +use blake2::digest::crypto_common::typenum::U32; +use blake2::digest::crypto_common::KeySizeUser; +use blake2::digest::{FixedOutput, Mac, OutputSizeUser}; +use blake2::Blake2bMac; + +use rosenpass_to::{ops::copy_slice, with_destination, To}; +use rosenpass_util::typenum2const; + +type Impl = Blake2bMac; + +type KeyLen = ::KeySize; +type OutLen = ::OutputSize; + +const KEY_LEN: usize = typenum2const! { KeyLen }; +const OUT_LEN: usize = typenum2const! { OutLen }; + +pub const KEY_MIN: usize = KEY_LEN; +pub const KEY_MAX: usize = KEY_LEN; +pub const OUT_MIN: usize = OUT_LEN; +pub const OUT_MAX: usize = OUT_LEN; + +#[inline] +pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a { + with_destination(|out: &mut [u8]| { + let mut h = Impl::new_from_slice(key)?; + h.update(data); + + // Jesus christ, blake2 crate, your usage of GenericArray might be nice and fancy + // but it introduces a ton of complexity. This cost me half an hour just to figure + // out the right way to use the imports while allowing for zeroization. + // An API based on slices might actually be simpler. + let mut tmp = Zeroizing::new([0u8; OUT_LEN]); + let mut tmp = GenericArray::from_mut_slice(tmp.as_mut()); + h.finalize_into(&mut tmp); + copy_slice(tmp.as_ref()).to(out); + + Ok(()) + }) +} diff --git a/ciphers/src/subtle/chacha20poly1305_ietf.rs b/ciphers/src/subtle/chacha20poly1305_ietf.rs new file mode 100644 index 0000000..4f2db50 --- /dev/null +++ b/ciphers/src/subtle/chacha20poly1305_ietf.rs @@ -0,0 +1,43 @@ +use rosenpass_to::ops::copy_slice; +use rosenpass_to::To; +use rosenpass_util::typenum2const; + +use chacha20poly1305::aead::generic_array::GenericArray; +use chacha20poly1305::ChaCha20Poly1305 as AeadImpl; +use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser}; + +pub const KEY_LEN: usize = typenum2const! { ::KeySize }; +pub const TAG_LEN: usize = typenum2const! { ::TagSize }; +pub const NONCE_LEN: usize = typenum2const! { ::NonceSize }; + +#[inline] +pub fn encrypt( + ciphertext: &mut [u8], + key: &[u8], + nonce: &[u8], + ad: &[u8], + plaintext: &[u8], +) -> anyhow::Result<()> { + let nonce = GenericArray::from_slice(nonce); + let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN); + copy_slice(plaintext).to(ct); + let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(&nonce, ad, ct)?; + copy_slice(&mac_value[..]).to(mac); + Ok(()) +} + +#[inline] +pub fn decrypt( + plaintext: &mut [u8], + key: &[u8], + nonce: &[u8], + ad: &[u8], + ciphertext: &[u8], +) -> anyhow::Result<()> { + let nonce = GenericArray::from_slice(nonce); + let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN); + let tag = GenericArray::from_slice(mac); + copy_slice(ct).to(plaintext); + AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(&nonce, ad, plaintext, tag)?; + Ok(()) +} diff --git a/ciphers/src/subtle/incorrect_hmac_blake2b.rs b/ciphers/src/subtle/incorrect_hmac_blake2b.rs index 802859a..a558be3 100644 --- a/ciphers/src/subtle/incorrect_hmac_blake2b.rs +++ b/ciphers/src/subtle/incorrect_hmac_blake2b.rs @@ -1,9 +1,11 @@ use anyhow::ensure; -use rosenpass_constant_time::xor; -use rosenpass_sodium::hash::blake2b; -use rosenpass_to::{ops::copy_slice, with_destination, To}; use zeroize::Zeroizing; +use rosenpass_constant_time::xor; +use rosenpass_to::{ops::copy_slice, with_destination, To}; + +use crate::subtle::blake2b; + pub const KEY_LEN: usize = 32; pub const KEY_MIN: usize = KEY_LEN; pub const KEY_MAX: usize = KEY_LEN; diff --git a/ciphers/src/subtle/mod.rs b/ciphers/src/subtle/mod.rs index b4f4456..d9c9ecf 100644 --- a/ciphers/src/subtle/mod.rs +++ b/ciphers/src/subtle/mod.rs @@ -1 +1,4 @@ +pub mod blake2b; +pub mod chacha20poly1305_ietf; pub mod incorrect_hmac_blake2b; +pub mod xchacha20poly1305_ietf; diff --git a/ciphers/src/subtle/xchacha20poly1305_ietf.rs b/ciphers/src/subtle/xchacha20poly1305_ietf.rs new file mode 100644 index 0000000..3d172b3 --- /dev/null +++ b/ciphers/src/subtle/xchacha20poly1305_ietf.rs @@ -0,0 +1,45 @@ +use rosenpass_to::ops::copy_slice; +use rosenpass_to::To; +use rosenpass_util::typenum2const; + +use chacha20poly1305::aead::generic_array::GenericArray; +use chacha20poly1305::XChaCha20Poly1305 as AeadImpl; +use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser}; + +pub const KEY_LEN: usize = typenum2const! { ::KeySize }; +pub const TAG_LEN: usize = typenum2const! { ::TagSize }; +pub const NONCE_LEN: usize = typenum2const! { ::NonceSize }; + +#[inline] +pub fn encrypt( + ciphertext: &mut [u8], + key: &[u8], + nonce: &[u8], + ad: &[u8], + plaintext: &[u8], +) -> anyhow::Result<()> { + let nonce = GenericArray::from_slice(nonce); + let (n, ct_mac) = ciphertext.split_at_mut(NONCE_LEN); + let (ct, mac) = ct_mac.split_at_mut(ct_mac.len() - TAG_LEN); + copy_slice(nonce).to(n); + copy_slice(plaintext).to(ct); + let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(&nonce, ad, ct)?; + copy_slice(&mac_value[..]).to(mac); + Ok(()) +} + +#[inline] +pub fn decrypt( + plaintext: &mut [u8], + key: &[u8], + ad: &[u8], + ciphertext: &[u8], +) -> anyhow::Result<()> { + let (n, ct_mac) = ciphertext.split_at(NONCE_LEN); + let (ct, mac) = ct_mac.split_at(ct_mac.len() - TAG_LEN); + let nonce = GenericArray::from_slice(n); + let tag = GenericArray::from_slice(mac); + copy_slice(ct).to(plaintext); + AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(&nonce, ad, plaintext, tag)?; + Ok(()) +} diff --git a/constant-time/Cargo.toml b/constant-time/Cargo.toml index 46de621..497f0f4 100644 --- a/constant-time/Cargo.toml +++ b/constant-time/Cargo.toml @@ -13,3 +13,4 @@ readme = "readme.md" [dependencies] rosenpass-to = { workspace = true } +memsec = { workspace = true } diff --git a/constant-time/src/lib.rs b/constant-time/src/lib.rs index 33908ba..b5ea516 100644 --- a/constant-time/src/lib.rs +++ b/constant-time/src/lib.rs @@ -1,3 +1,5 @@ +use core::hint::black_box; + use rosenpass_to::{with_destination, To}; /// Xors the source into the destination @@ -18,9 +20,60 @@ use rosenpass_to::{with_destination, To}; #[inline] pub fn xor(src: &[u8]) -> impl To<[u8], ()> + '_ { with_destination(|dst: &mut [u8]| { - assert!(src.len() == dst.len()); + assert!(black_box(src.len()) == black_box(dst.len())); for (dv, sv) in dst.iter_mut().zip(src.iter()) { - *dv ^= *sv; + *black_box(dv) ^= black_box(*sv); } }) } + +#[inline] +pub fn memcmp(a: &[u8], b: &[u8]) -> bool { + a.len() == b.len() + && unsafe { memsec::memeq(a.as_ptr() as *const u8, b.as_ptr() as *const u8, a.len()) } +} + +#[inline] +pub fn compare(a: &[u8], b: &[u8]) -> i32 { + assert!(a.len() == b.len()); + unsafe { memsec::memcmp(a.as_ptr(), b.as_ptr(), a.len()) } +} + +/// Interpret the given slice as a little-endian unsigned integer +/// and increment that integer. +/// +/// # Examples +/// +/// ``` +/// use rosenpass_constant_time::increment as inc; +/// use rosenpass_to::To; +/// +/// fn testcase(v: &[u8], correct: &[u8]) { +/// let mut v = v.to_owned(); +/// inc(&mut v); +/// assert_eq!(&v, correct); +/// } +/// +/// testcase(b"", b""); +/// testcase(b"\x00", b"\x01"); +/// testcase(b"\x01", b"\x02"); +/// testcase(b"\xfe", b"\xff"); +/// testcase(b"\xff", b"\x00"); +/// testcase(b"\x00\x00", b"\x01\x00"); +/// testcase(b"\x01\x00", b"\x02\x00"); +/// testcase(b"\xfe\x00", b"\xff\x00"); +/// testcase(b"\xff\x00", b"\x00\x01"); +/// testcase(b"\x00\x00\x00\x00\x00\x00", b"\x01\x00\x00\x00\x00\x00"); +/// testcase(b"\x00\xa3\x00\x77\x00\x00", b"\x01\xa3\x00\x77\x00\x00"); +/// testcase(b"\xff\xa3\x00\x77\x00\x00", b"\x00\xa4\x00\x77\x00\x00"); +/// testcase(b"\xff\xff\xff\x77\x00\x00", b"\x00\x00\x00\x78\x00\x00"); +/// ``` +#[inline] +pub fn increment(v: &mut [u8]) { + let mut carry = 1u8; + for val in v.iter_mut() { + let (v, c) = black_box(*val).overflowing_add(black_box(carry)); + *black_box(val) = v; + *black_box(&mut carry) = black_box(black_box(c) as u8); + } +} diff --git a/doc/rosenpass.1 b/doc/rosenpass.1 index f9ec510..21bd0b2 100644 --- a/doc/rosenpass.1 +++ b/doc/rosenpass.1 @@ -23,7 +23,7 @@ If you are not specifically tasked with developing post-quantum secure systems, you probably do not need this tool. .Ss COMMANDS .Bl -tag -width Ds -.It Ar keygen private-key public-key +.It Ar gen-keys --secret-key --public-key Generate a keypair to use in the exchange command later. Send the public-key file to your communication partner and keep the private-key file secret! diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 0e26f23..e00d010 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -12,7 +12,6 @@ arbitrary = { workspace = true } libfuzzer-sys = { workspace = true } stacker = { workspace = true } rosenpass-secret-memory = { workspace = true } -rosenpass-sodium = { workspace = true } rosenpass-ciphers = { workspace = true } rosenpass-cipher-traits = { workspace = true } rosenpass-to = { workspace = true } diff --git a/fuzz/fuzz_targets/aead_enc_into.rs b/fuzz/fuzz_targets/aead_enc_into.rs index d90d52b..19f0bc4 100644 --- a/fuzz/fuzz_targets/aead_enc_into.rs +++ b/fuzz/fuzz_targets/aead_enc_into.rs @@ -5,7 +5,6 @@ extern crate rosenpass; use libfuzzer_sys::fuzz_target; use rosenpass_ciphers::aead; -use rosenpass_sodium::init as sodium_init; #[derive(arbitrary::Arbitrary, Debug)] pub struct Input { @@ -16,8 +15,6 @@ pub struct Input { } fuzz_target!(|input: Input| { - sodium_init().unwrap(); - let mut ciphertext: Vec = Vec::with_capacity(input.plaintext.len() + 16); ciphertext.resize(input.plaintext.len() + 16, 0); diff --git a/fuzz/fuzz_targets/blake2b.rs b/fuzz/fuzz_targets/blake2b.rs index 807c1a6..f4349b0 100644 --- a/fuzz/fuzz_targets/blake2b.rs +++ b/fuzz/fuzz_targets/blake2b.rs @@ -4,7 +4,7 @@ extern crate rosenpass; use libfuzzer_sys::fuzz_target; -use rosenpass_sodium::{hash::blake2b, init as sodium_init}; +use rosenpass_ciphers::subtle::blake2b; use rosenpass_to::To; #[derive(arbitrary::Arbitrary, Debug)] @@ -14,8 +14,6 @@ pub struct Blake2b { } fuzz_target!(|input: Blake2b| { - sodium_init().unwrap(); - let mut out = [0u8; 32]; blake2b::hash(&input.key, &input.data).to(&mut out).unwrap(); diff --git a/fuzz/fuzz_targets/handle_msg.rs b/fuzz/fuzz_targets/handle_msg.rs index 83d3533..21473ac 100644 --- a/fuzz/fuzz_targets/handle_msg.rs +++ b/fuzz/fuzz_targets/handle_msg.rs @@ -5,11 +5,8 @@ use libfuzzer_sys::fuzz_target; use rosenpass::protocol::CryptoServer; use rosenpass_secret_memory::Secret; -use rosenpass_sodium::init as sodium_init; fuzz_target!(|rx_buf: &[u8]| { - sodium_init().unwrap(); - let sk = Secret::from_slice(&[0; 13568]); let pk = Secret::from_slice(&[0; 524160]); diff --git a/rosenpass/Cargo.toml b/rosenpass/Cargo.toml index f8f4634..4523c1f 100644 --- a/rosenpass/Cargo.toml +++ b/rosenpass/Cargo.toml @@ -16,7 +16,6 @@ harness = false [dependencies] rosenpass-util = { workspace = true } rosenpass-constant-time = { workspace = true } -rosenpass-sodium = { workspace = true } rosenpass-ciphers = { workspace = true } rosenpass-cipher-traits = { workspace = true } rosenpass-to = { workspace = true } @@ -25,7 +24,6 @@ rosenpass-lenses = { workspace = true } anyhow = { workspace = true } static_assertions = { workspace = true } memoffset = { workspace = true } -libsodium-sys-stable = { workspace = true } thiserror = { workspace = true } paste = { workspace = true } log = { workspace = true } diff --git a/rosenpass/benches/handshake.rs b/rosenpass/benches/handshake.rs index e276a9d..cb01fea 100644 --- a/rosenpass/benches/handshake.rs +++ b/rosenpass/benches/handshake.rs @@ -56,7 +56,6 @@ fn make_server_pair() -> Result<(CryptoServer, CryptoServer)> { } fn criterion_benchmark(c: &mut Criterion) { - rosenpass_sodium::init().unwrap(); let (mut a, mut b) = make_server_pair().unwrap(); c.bench_function("cca_secret_alloc", |bench| { bench.iter(|| { diff --git a/rosenpass/src/main.rs b/rosenpass/src/main.rs index e4db49e..c5cd7e1 100644 --- a/rosenpass/src/main.rs +++ b/rosenpass/src/main.rs @@ -1,6 +1,5 @@ use log::error; use rosenpass::cli::Cli; -use rosenpass_util::attempt; use std::process::exit; /// Catches errors, prints them through the logger, then exits @@ -8,12 +7,7 @@ pub fn main() { // default to displaying warning and error log messages only env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); - let res = attempt!({ - rosenpass_sodium::init()?; - Cli::run() - }); - - match res { + match Cli::run() { Ok(_) => {} Err(e) => { error!("{e}"); diff --git a/rosenpass/src/protocol.rs b/rosenpass/src/protocol.rs index f9e36cf..8aa7eac 100644 --- a/rosenpass/src/protocol.rs +++ b/rosenpass/src/protocol.rs @@ -26,9 +26,6 @@ //! }; //! # fn main() -> anyhow::Result<()> { //! -//! // always initialize libsodium before anything -//! rosenpass_sodium::init()?; -//! //! // initialize secret and public key for peer a ... //! let (mut peer_a_sk, mut peer_a_pk) = (SSk::zero(), SPk::zero()); //! StaticKem::keygen(peer_a_sk.secret_mut(), peer_a_pk.secret_mut())?; @@ -68,21 +65,25 @@ //! # } //! ``` -use crate::{hash_domains, msgs::*}; -use anyhow::{bail, ensure, Context, Result}; -use rosenpass_cipher_traits::Kem; -use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace}; -use rosenpass_ciphers::kem::{EphemeralKem, StaticKem}; -use rosenpass_ciphers::{aead, xaead, KEY_LEN}; -use rosenpass_lenses::LenseView; -use rosenpass_secret_memory::{Public, Secret}; -use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase}; use std::collections::hash_map::{ Entry::{Occupied, Vacant}, HashMap, }; use std::convert::Infallible; +use anyhow::{bail, ensure, Context, Result}; + +use rosenpass_cipher_traits::Kem; +use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace}; +use rosenpass_ciphers::kem::{EphemeralKem, StaticKem}; +use rosenpass_ciphers::{aead, xaead, KEY_LEN}; +use rosenpass_constant_time as constant_time; +use rosenpass_lenses::LenseView; +use rosenpass_secret_memory::{Public, Secret}; +use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase}; + +use crate::{hash_domains, msgs::*}; + // CONSTANTS & SETTINGS ////////////////////////// /// Size required to fit any message in binary form @@ -921,7 +922,7 @@ impl CryptoServer { }; //If valid cookie is found, process message - if rosenpass_sodium::helpers::memcmp(&rx_cookie, &expected) { + if constant_time::memcmp(&rx_cookie, &expected) { let result = self.handle_msg(rx_buf, tx_buf)?; Ok(result) } @@ -1461,7 +1462,7 @@ where let expected = hash_domains::mac()? .mix(srv.spkm.secret())? .mix(self.until_mac())?; - Ok(rosenpass_sodium::helpers::memcmp( + Ok(constant_time::memcmp( self.mac(), &expected.into_value()[..16], )) @@ -1569,7 +1570,7 @@ impl HandshakeState { .into_value(); // consume biscuit no - rosenpass_sodium::helpers::increment(&mut *srv.biscuit_ctr); + constant_time::increment(&mut *srv.biscuit_ctr); // The first bit of the nonce indicates which biscuit key was used // TODO: This is premature optimization. Remove! @@ -1632,8 +1633,7 @@ impl HandshakeState { // indicates retransmission // TODO: Handle retransmissions without involving the crypto code ensure!( - rosenpass_sodium::helpers::compare(biscuit.biscuit_no(), &*peer.get(srv).biscuit_used) - >= 0, + constant_time::compare(biscuit.biscuit_no(), &*peer.get(srv).biscuit_used) >= 0, "Rejecting biscuit: Outdated biscuit number" ); @@ -1910,7 +1910,7 @@ impl CryptoServer { core.decrypt_and_mix(&mut [0u8; 0], ic.auth())?; // ICR5 - if rosenpass_sodium::helpers::compare(&*biscuit_no, &*peer.get(self).biscuit_used) > 0 { + if constant_time::compare(&*biscuit_no, &*peer.get(self).biscuit_used) > 0 { // ICR6 peer.get_mut(self).biscuit_used = biscuit_no; @@ -2096,8 +2096,6 @@ mod test { /// Through all this, the handshake should still successfully terminate; /// i.e. an exchanged key must be produced in both servers. fn handles_incorrect_size_messages() { - rosenpass_sodium::init().unwrap(); - stacker::grow(8 * 1024 * 1024, || { const OVERSIZED_MESSAGE: usize = ((MAX_MESSAGE_LEN as f32) * 1.2) as usize; type MsgBufPlus = Public; @@ -2169,8 +2167,6 @@ mod test { #[test] fn cookie_reply_mechanism_responder_under_load() { - rosenpass_sodium::init().unwrap(); - stacker::grow(8 * 1024 * 1024, || { type MsgBufPlus = Public; let (mut a, mut b) = make_server_pair().unwrap(); @@ -2257,7 +2253,6 @@ mod test { #[test] fn cookie_reply_mechanism_initiator_bails_on_message_under_load() { - rosenpass_sodium::init().unwrap(); stacker::grow(8 * 1024 * 1024, || { type MsgBufPlus = Public; let (mut a, mut b) = make_server_pair().unwrap(); diff --git a/secret-memory/Cargo.toml b/secret-memory/Cargo.toml index 3f56f3d..a89f9d1 100644 --- a/secret-memory/Cargo.toml +++ b/secret-memory/Cargo.toml @@ -12,9 +12,7 @@ readme = "readme.md" [dependencies] anyhow = { workspace = true } rosenpass-to = { workspace = true } -rosenpass-sodium = { workspace = true } rosenpass-util = { workspace = true } -libsodium-sys-stable = { workspace = true } zeroize = { workspace = true } rand = { workspace = true } memsec = { workspace = true } diff --git a/sodium/Cargo.toml b/sodium/Cargo.toml deleted file mode 100644 index 1476132..0000000 --- a/sodium/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "rosenpass-sodium" -authors = ["Karolin Varner ", "wucke13 "] -version = "0.1.0" -edition = "2021" -license = "MIT OR Apache-2.0" -description = "Rosenpass internal bindings to libsodium" -homepage = "https://rosenpass.eu/" -repository = "https://github.com/rosenpass/rosenpass" -readme = "readme.md" - -[dependencies] -rosenpass-util = { workspace = true } -rosenpass-to = { workspace = true } -anyhow = { workspace = true } -libsodium-sys-stable = { workspace = true } -log = { workspace = true } -allocator-api2 = { workspace = true } diff --git a/sodium/readme.md b/sodium/readme.md deleted file mode 100644 index 0ddad45..0000000 --- a/sodium/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -# Rosenpass internal libsodium bindings - -Rosenpass internal library providing bindings to libsodium. - -This is an internal library; not guarantee is made about its API at this point in time. diff --git a/sodium/src/aead/chacha20poly1305_ietf.rs b/sodium/src/aead/chacha20poly1305_ietf.rs deleted file mode 100644 index 7f35f6c..0000000 --- a/sodium/src/aead/chacha20poly1305_ietf.rs +++ /dev/null @@ -1,63 +0,0 @@ -use libsodium_sys as libsodium; -use std::ffi::c_ulonglong; -use std::ptr::{null, null_mut}; - -pub const KEY_LEN: usize = libsodium::crypto_aead_chacha20poly1305_IETF_KEYBYTES as usize; -pub const TAG_LEN: usize = libsodium::crypto_aead_chacha20poly1305_IETF_ABYTES as usize; -pub const NONCE_LEN: usize = libsodium::crypto_aead_chacha20poly1305_IETF_NPUBBYTES as usize; - -#[inline] -pub fn encrypt( - ciphertext: &mut [u8], - key: &[u8], - nonce: &[u8], - ad: &[u8], - plaintext: &[u8], -) -> anyhow::Result<()> { - assert!(ciphertext.len() == plaintext.len() + TAG_LEN); - assert!(key.len() == KEY_LEN); - assert!(nonce.len() == NONCE_LEN); - let mut clen: u64 = 0; - sodium_call!( - crypto_aead_chacha20poly1305_ietf_encrypt, - ciphertext.as_mut_ptr(), - &mut clen, - plaintext.as_ptr(), - plaintext.len() as c_ulonglong, - ad.as_ptr(), - ad.len() as c_ulonglong, - null(), // nsec is not used - nonce.as_ptr(), - key.as_ptr() - )?; - assert!(clen as usize == ciphertext.len()); - Ok(()) -} - -#[inline] -pub fn decrypt( - plaintext: &mut [u8], - key: &[u8], - nonce: &[u8], - ad: &[u8], - ciphertext: &[u8], -) -> anyhow::Result<()> { - assert!(ciphertext.len() == plaintext.len() + TAG_LEN); - assert!(key.len() == KEY_LEN); - assert!(nonce.len() == NONCE_LEN); - let mut mlen: u64 = 0; - sodium_call!( - crypto_aead_chacha20poly1305_ietf_decrypt, - plaintext.as_mut_ptr(), - &mut mlen as *mut c_ulonglong, - null_mut(), // nsec is not used - ciphertext.as_ptr(), - ciphertext.len() as c_ulonglong, - ad.as_ptr(), - ad.len() as c_ulonglong, - nonce.as_ptr(), - key.as_ptr() - )?; - assert!(mlen as usize == plaintext.len()); - Ok(()) -} diff --git a/sodium/src/aead/mod.rs b/sodium/src/aead/mod.rs deleted file mode 100644 index 0f10c84..0000000 --- a/sodium/src/aead/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod chacha20poly1305_ietf; -pub mod xchacha20poly1305_ietf; diff --git a/sodium/src/aead/xchacha20poly1305_ietf.rs b/sodium/src/aead/xchacha20poly1305_ietf.rs deleted file mode 100644 index a5d86c2..0000000 --- a/sodium/src/aead/xchacha20poly1305_ietf.rs +++ /dev/null @@ -1,63 +0,0 @@ -use libsodium_sys as libsodium; -use std::ffi::c_ulonglong; -use std::ptr::{null, null_mut}; - -pub const KEY_LEN: usize = libsodium::crypto_aead_xchacha20poly1305_IETF_KEYBYTES as usize; -pub const TAG_LEN: usize = libsodium::crypto_aead_xchacha20poly1305_ietf_ABYTES as usize; -pub const NONCE_LEN: usize = libsodium::crypto_aead_xchacha20poly1305_IETF_NPUBBYTES as usize; - -#[inline] -pub fn encrypt( - ciphertext: &mut [u8], - key: &[u8], - nonce: &[u8], - ad: &[u8], - plaintext: &[u8], -) -> anyhow::Result<()> { - assert!(ciphertext.len() == plaintext.len() + NONCE_LEN + TAG_LEN); - assert!(key.len() == libsodium::crypto_aead_xchacha20poly1305_IETF_KEYBYTES as usize); - let (n, ct) = ciphertext.split_at_mut(NONCE_LEN); - n.copy_from_slice(nonce); - let mut clen: u64 = 0; - sodium_call!( - crypto_aead_xchacha20poly1305_ietf_encrypt, - ct.as_mut_ptr(), - &mut clen, - plaintext.as_ptr(), - plaintext.len() as c_ulonglong, - ad.as_ptr(), - ad.len() as c_ulonglong, - null(), // nsec is not used - nonce.as_ptr(), - key.as_ptr() - )?; - assert!(clen as usize == ct.len()); - Ok(()) -} - -#[inline] -pub fn decrypt( - plaintext: &mut [u8], - key: &[u8], - ad: &[u8], - ciphertext: &[u8], -) -> anyhow::Result<()> { - assert!(ciphertext.len() == plaintext.len() + NONCE_LEN + TAG_LEN); - assert!(key.len() == KEY_LEN); - let (n, ct) = ciphertext.split_at(NONCE_LEN); - let mut mlen: u64 = 0; - sodium_call!( - crypto_aead_xchacha20poly1305_ietf_decrypt, - plaintext.as_mut_ptr(), - &mut mlen as *mut c_ulonglong, - null_mut(), // nsec is not used - ct.as_ptr(), - ct.len() as c_ulonglong, - ad.as_ptr(), - ad.len() as c_ulonglong, - n.as_ptr(), - key.as_ptr() - )?; - assert!(mlen as usize == plaintext.len()); - Ok(()) -} diff --git a/sodium/src/hash/blake2b.rs b/sodium/src/hash/blake2b.rs deleted file mode 100644 index e2f2fe3..0000000 --- a/sodium/src/hash/blake2b.rs +++ /dev/null @@ -1,31 +0,0 @@ -use libsodium_sys as libsodium; -use rosenpass_to::{with_destination, To}; -use std::ffi::c_ulonglong; -use std::ptr::null; - -pub const KEY_MIN: usize = libsodium::crypto_generichash_blake2b_KEYBYTES_MIN as usize; -pub const KEY_MAX: usize = libsodium::crypto_generichash_blake2b_KEYBYTES_MAX as usize; -pub const OUT_MIN: usize = libsodium::crypto_generichash_blake2b_BYTES_MIN as usize; -pub const OUT_MAX: usize = libsodium::crypto_generichash_blake2b_BYTES_MAX as usize; - -#[inline] -pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a { - with_destination(|out: &mut [u8]| { - assert!(key.is_empty() || (KEY_MIN <= key.len() && key.len() <= KEY_MAX)); - assert!(OUT_MIN <= out.len() && out.len() <= OUT_MAX); - let kptr = match key.len() { - // NULL key - 0 => null(), - _ => key.as_ptr(), - }; - sodium_call!( - crypto_generichash_blake2b, - out.as_mut_ptr(), - out.len(), - data.as_ptr(), - data.len() as c_ulonglong, - kptr, - key.len() - ) - }) -} diff --git a/sodium/src/hash/mod.rs b/sodium/src/hash/mod.rs deleted file mode 100644 index 52d9d26..0000000 --- a/sodium/src/hash/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod blake2b; diff --git a/sodium/src/helpers.rs b/sodium/src/helpers.rs deleted file mode 100644 index a64f95b..0000000 --- a/sodium/src/helpers.rs +++ /dev/null @@ -1,28 +0,0 @@ -use libsodium_sys as libsodium; -use std::os::raw::c_void; - -#[inline] -pub fn memcmp(a: &[u8], b: &[u8]) -> bool { - a.len() == b.len() - && unsafe { - let r = libsodium::sodium_memcmp( - a.as_ptr() as *const c_void, - b.as_ptr() as *const c_void, - a.len(), - ); - r == 0 - } -} - -#[inline] -pub fn compare(a: &[u8], b: &[u8]) -> i32 { - assert!(a.len() == b.len()); - unsafe { libsodium::sodium_compare(a.as_ptr(), b.as_ptr(), a.len()) } -} - -#[inline] -pub fn increment(v: &mut [u8]) { - unsafe { - libsodium::sodium_increment(v.as_mut_ptr(), v.len()); - } -} diff --git a/sodium/src/lib.rs b/sodium/src/lib.rs deleted file mode 100644 index 606bbd0..0000000 --- a/sodium/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -use libsodium_sys as libsodium; - -macro_rules! sodium_call { - ($name:ident, $($args:expr),*) => { ::rosenpass_util::attempt!({ - anyhow::ensure!(unsafe{libsodium::$name($($args),*)} > -1, - "Error in libsodium's {}.", stringify!($name)); - Ok(()) - })}; - ($name:ident) => { sodium_call!($name, ) }; -} - -#[inline] -pub fn init() -> anyhow::Result<()> { - log::trace!("initializing libsodium"); - sodium_call!(sodium_init) -} - -pub mod aead; -pub mod hash; -pub mod helpers; diff --git a/util/Cargo.toml b/util/Cargo.toml index d1df0f1..a75e76c 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -14,3 +14,5 @@ readme = "readme.md" [dependencies] base64 = { workspace = true } anyhow = { workspace = true } +typenum = { workspace = true } +static_assertions = { workspace = true } diff --git a/util/src/lib.rs b/util/src/lib.rs index 49ded9c..0c1f846 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -1,3 +1,5 @@ +#![recursion_limit = "256"] + pub mod b64; pub mod file; pub mod functional; @@ -5,3 +7,4 @@ pub mod mem; pub mod ord; pub mod result; pub mod time; +pub mod typenum; diff --git a/util/src/typenum.rs b/util/src/typenum.rs new file mode 100644 index 0000000..d14944a --- /dev/null +++ b/util/src/typenum.rs @@ -0,0 +1,341 @@ +use typenum::bit::{B0, B1}; +use typenum::int::{NInt, PInt, Z0}; +use typenum::marker_traits as markers; +use typenum::uint::{UInt, UTerm}; + +/// Convenience macro to convert type numbers to constant integers +#[macro_export] +macro_rules! typenum2const { + ($val:ty) => { + typenum2const!($val as _) + }; + ($val:ty as $type:ty) => { + <$val as $crate::typenum::IntoConst<$type>>::VALUE + }; +} + +/// Trait implemented by constant integers to facilitate conversion to constant integers +pub trait IntoConst { + const VALUE: T; +} + +struct ConstApplyNegSign::Type>>( + *const T, + *const Param, +); +struct ConstApplyPosSign::Type>>( + *const T, + *const Param, +); +struct ConstLshift, const SHIFT: i32>(*const T, *const Param); // impl IntoConst +struct ConstAdd, Rhs: IntoConst>(*const T, *const Lhs, *const Rhs); // impl IntoConst + +/// Assigns an unsigned type to a signed type +trait AssociatedUnsigned { + type Type; +} + +macro_rules! impl_into_const { + ( $from:ty as $to:ty := $impl:expr) => { + impl IntoConst<$to> for $from { + const VALUE: $to = $impl; + } + }; +} + +macro_rules! impl_numeric_into_const_common { + ($type:ty) => { + impl_into_const! { Z0 as $type := 0 } + impl_into_const! { B0 as $type := 0 } + impl_into_const! { B1 as $type := 1 } + impl_into_const! { UTerm as $type := 0 } + + impl, const SHIFT: i32> IntoConst<$type> + for ConstLshift<$type, Param, SHIFT> + { + const VALUE: $type = Param::VALUE << SHIFT; + } + + impl, Rhs: IntoConst<$type>> IntoConst<$type> + for ConstAdd<$type, Lhs, Rhs> + { + const VALUE: $type = + >::VALUE + >::VALUE; + } + }; +} + +macro_rules! impl_numeric_into_const_unsigned { + ($($to_list:ty),*) => { + $( impl_numeric_into_const_unsigned! { @impl $to_list } )* + }; + + (@impl $type:ty) => { + impl_numeric_into_const_common!{ $type } + + impl AssociatedUnsigned for $type { + type Type = $type; + } + + impl> IntoConst<$type> for ConstApplyPosSign<$type, Param> { + const VALUE : $type = Param::VALUE; + } + }; +} + +macro_rules! impl_numeric_into_const_signed { + ($($to_list:ty : $unsigned_list:ty),*) => { + $( impl_numeric_into_const_signed! { @impl $to_list : $unsigned_list} )* + }; + + (@impl $type:ty : $unsigned:ty) => { + impl_numeric_into_const_common!{ $type } + + impl AssociatedUnsigned for $type { + type Type = $unsigned; + } + + impl> IntoConst<$type> for ConstApplyPosSign<$type, Param> { + const VALUE : $type = Param::VALUE as $type; + } + + impl> IntoConst<$type> for ConstApplyNegSign<$type, Param> { + const VALUE : $type = + if Param::VALUE == (1 as $unsigned).rotate_right(1) { + // Handle the negative value without an associated positive value (e.g. -128 + // for i8) + < $type >::MIN + } else { + -(Param::VALUE as $type) + }; + } + }; +} + +impl_into_const! { B0 as bool := false } +impl_into_const! { B1 as bool := true } +impl_numeric_into_const_unsigned! { usize, u8, u16, u32, u64, u128 } +impl_numeric_into_const_signed! { isize : usize, i8 : u8, i16 : u16, i32 : u32, i64 : u64, i128 : u128 } + +// Unsigned type numbers to const integers +impl IntoConst for UInt +where + Rest: IntoConst, + Bit: IntoConst, + ConstLshift: IntoConst, + ConstAdd, Bit>: IntoConst, +{ + const VALUE: Ret = , Bit> as IntoConst>::VALUE; +} + +// Signed type numbers with positive sign to const integers +impl IntoConst for PInt +where + Ret: AssociatedUnsigned, + Unsigned: markers::Unsigned + markers::NonZero + IntoConst<::Type>, + ConstApplyPosSign: IntoConst, +{ + const VALUE: Ret = as IntoConst>::VALUE; +} + +// Signed type numbers with negative sign to const integers +impl IntoConst for NInt +where + Ret: AssociatedUnsigned, + Unsigned: markers::Unsigned + markers::NonZero + IntoConst<::Type>, + ConstApplyNegSign: IntoConst, +{ + const VALUE: Ret = as IntoConst>::VALUE; +} + +mod test { + use static_assertions::const_assert_eq; + use typenum::consts::*; + use typenum::op; + + macro_rules! test_const_conversion { + // Type groups + + (($($typenum:ty),*) >= u7 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as (u8, u16, u32, u64, u128) = $const } )* + $( test_const_conversion! { ($typenum) as (i8, i16, i32, i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u8 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as (u8, u16, u32, u64, u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( i16, i32, i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u15 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( u16, u32, u64, u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( i16, i32, i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u16 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( u16, u32, u64, u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( i32, i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u31 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( u32, u64, u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( i32, i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u32 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( u32, u64, u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u63 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( u64, u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u64 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( u64, u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u127 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= u128 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( u128) = $const } )* + $( test_const_conversion! { ($typenum) as ( ) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= i8 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as (i8, i16, i32, i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= i16 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( i16, i32, i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= i32 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( i32, i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= i64 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( i64, i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) >= i128 = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { ($typenum) as ( i128) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + // Basic operation + + () => {}; + + (($($typenum:ty),*) as () = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) as ($type:ty) = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { @impl ($typenum) as ($type) = $const } )* + $( test_const_conversion! { $($rest)* } )? + }; + + (($($typenum:ty),*) as ($type_head:ty, $($type_tail:ty),*) = $const:expr $(; $($rest:tt)*)?) => { + $( test_const_conversion! { @impl ($typenum) as ($type_head) = $const } )* + test_const_conversion! { ($($typenum),*) as ($($type_tail),*) = $const } + $( test_const_conversion! { $($rest)* } )? + }; + + (@impl ($typenum:ty) as ($type:ty) = $const:expr $(; $($rest:tt)*)?) => { + const_assert_eq!(typenum2const!($typenum as $type), $const); + $( test_const_conversion!($($rest)*); )? + }; + } + + test_const_conversion! { + (B0, False) as (bool, bool) = false; + + (B0, U0, Z0) >= u7 = 0; + (B1, U1, P1) >= u7 = 1; + + (U2, P2) >= u7 = 2; + (B1, True) as (bool) = true; + (U3, P3) >= u7 = 3; + (U8, P8) >= u7 = 8; + (U127, P127) >= u7 = 127; + (U220, P220) >= u8 = 220; + (U255, P255) >= u8 = 255; + (U1000, P1000) >= u15 = 1000; + (U10000, P10000) >= u15 = 10000; + (U16384, P16384) >= u15 = 16384; + (U32768, P32768) >= u16 = 32768; + (U65536, P65536) >= u31 = 65536; + (U100000, P100000) >= u31 = 100000; + (U1000000000, P1000000000) >= u31 = 1000000000; + (U2147483648, P2147483648) >= u32 = 2147483648; + (U1000000000000000000, P1000000000000000000) >= u63 = 1000000000000000000; + (U1000000000000000000, P1000000000000000000) >= u63 = 1000000000000000000; + + (U9223372036854775808) >= u64 = 9223372036854775808; + (U10000000000000000000) >= u64 = 10000000000000000000; + + (N10000) >= i16 = -10000; + (N1000000) >= i32 = -1000000; + (N1000000000) >= i32 = -1000000000; + (N1000000000000) >= i64 = -1000000000000; + } + + const_assert_eq!(127, (!(1u8.rotate_right(1)) - 0) as _); + const_assert_eq!(126, (!(1u8.rotate_right(1)) - 1) as _); + const_assert_eq!(255, (!(0u8.rotate_right(1)) - 0) as _); + const_assert_eq!(254, (!(0u8.rotate_right(1)) - 1) as _); + + test_const_conversion! { + (op!(pow(U2, U7) - U1)) >= u7 = (!(1u8.rotate_right(1)) - 0) as _; + (op!(pow(U2, U7) - U2)) >= u7 = (!(1u8.rotate_right(1)) - 1) as _; + (op!(pow(U2, U15) - U1)) >= u15 = (!(1u16.rotate_right(1)) - 0) as _; + (op!(pow(U2, U15) - U2)) >= u15 = (!(1u16.rotate_right(1)) - 1) as _; + (op!(pow(U2, U31) - U1)) >= u31 = (!(1u32.rotate_right(1)) - 0) as _; + (op!(pow(U2, U31) - U2)) >= u31 = (!(1u32.rotate_right(1)) - 1) as _; + (op!(pow(U2, U63) - U1)) >= u63 = (!(1u64.rotate_right(1)) - 0) as _; + (op!(pow(U2, U63) - U2)) >= u63 = (!(1u64.rotate_right(1)) - 1) as _; + (op!(pow(U2, U127) - U1)) >= u127 = (!(1u128.rotate_right(1)) - 0) as _; + (op!(pow(U2, U127) - U2)) >= u127 = (!(1u128.rotate_right(1)) - 1) as _; + + (op!(pow(U2, U8) - U1)) >= u8 = (u8::MAX - 0) as _; + (op!(pow(U2, U8) - U2)) >= u8 = (u8::MAX - 1) as _; + (op!(pow(U2, U16) - U1)) >= u16 = (u16::MAX - 0) as _; + (op!(pow(U2, U16) - U2)) >= u16 = (u16::MAX - 1) as _; + (op!(pow(U2, U32) - U1)) >= u32 = (u32::MAX - 0) as _; + (op!(pow(U2, U32) - U2)) >= u32 = (u32::MAX - 1) as _; + (op!(pow(U2, U64) - U1)) >= u64 = (u64::MAX - 0) as _; + (op!(pow(U2, U64) - U2)) >= u64 = (u64::MAX - 1) as _; + (op!(pow(U2, U128) - U1)) >= u128 = (u128::MAX - 0) as _; + (op!(pow(U2, U128) - U2)) >= u128 = (u128::MAX - 1) as _; + + (op!(Z0 - pow(P2, P7) + Z0)) >= i8 = (i8::MIN + 0) as _; + (op!(Z0 - pow(P2, P7) + P1)) >= i8 = (i8::MIN + 1) as _; + (op!(Z0 - pow(P2, P15) + Z0)) >= i16 = (i16::MIN + 0) as _; + (op!(Z0 - pow(P2, P15) + P1)) >= i16 = (i16::MIN + 1) as _; + (op!(Z0 - pow(P2, P31) + Z0)) >= i32 = (i32::MIN + 0) as _; + (op!(Z0 - pow(P2, P31) + P1)) >= i32 = (i32::MIN + 1) as _; + (op!(Z0 - pow(P2, P63) + Z0)) >= i64 = (i64::MIN + 0) as _; + (op!(Z0 - pow(P2, P63) + P1)) >= i64 = (i64::MIN + 1) as _; + (op!(Z0 - pow(P2, P127) + Z0)) >= i128 = (i128::MIN + 0) as _; + (op!(Z0 - pow(P2, P127) + P1)) >= i128 = (i128::MIN + 1) as _; + } +}