diff --git a/Cargo.lock b/Cargo.lock index d281808..83d6c72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", + "heapless", +] + [[package]] name = "ahash" version = "0.8.6" @@ -131,6 +142,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" @@ -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" @@ -379,6 +434,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -424,6 +488,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" @@ -457,6 +527,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "dary_heap" version = "0.3.6" @@ -546,6 +626,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.11" @@ -575,6 +665,15 @@ 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" @@ -596,6 +695,19 @@ 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" @@ -662,6 +774,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" @@ -792,6 +913,16 @@ 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" @@ -897,6 +1028,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" @@ -967,6 +1104,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" @@ -1157,11 +1305,13 @@ name = "rosenpass-ciphers" version = "0.1.0" dependencies = [ "anyhow", + "chacha20poly1305", "rosenpass-constant-time", "rosenpass-oqs", "rosenpass-secret-memory", "rosenpass-sodium", "rosenpass-to", + "rosenpass-util", "static_assertions", "zeroize", ] @@ -1248,6 +1398,8 @@ version = "0.1.0" dependencies = [ "anyhow", "base64", + "static_assertions", + "typenum", ] [[package]] @@ -1262,6 +1414,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" @@ -1328,6 +1489,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + [[package]] name = "serde" version = "1.0.193" @@ -1379,6 +1546,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 +1581,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" @@ -1527,6 +1709,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -1548,6 +1736,16 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 6c915a7..0f7e311 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,3 +60,4 @@ 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'] } +chacha20poly1305 = { version = "0.10.1", default-features = false, features = [ "std", "heapless" ] } diff --git a/ciphers/Cargo.toml b/ciphers/Cargo.toml index a226239..3589ce4 100644 --- a/ciphers/Cargo.toml +++ b/ciphers/Cargo.toml @@ -16,5 +16,7 @@ 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 } diff --git a/ciphers/src/lib.rs b/ciphers/src/lib.rs index 994431b..252ae61 100644 --- a/ciphers/src/lib.rs +++ b/ciphers/src/lib.rs @@ -9,7 +9,7 @@ const_assert!(KEY_LEN == hash_domain::KEY_LEN); /// Authenticated encryption with associated data pub mod aead { - pub use rosenpass_sodium::aead::chacha20poly1305_ietf::{ + pub use crate::subtle::chacha20poly1305_ietf::{ decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN, }; } diff --git a/ciphers/src/subtle/chacha20poly1305_ietf.rs b/ciphers/src/subtle/chacha20poly1305_ietf.rs new file mode 100644 index 0000000..b00b23a --- /dev/null +++ b/ciphers/src/subtle/chacha20poly1305_ietf.rs @@ -0,0 +1,43 @@ +use rosenpass_to::To; +use rosenpass_to::ops::copy_slice; +use rosenpass_util::typenum2const; + +use chacha20poly1305::aead::generic_array::GenericArray; +use chacha20poly1305::{ChaCha20Poly1305 as AeadImpl}; +use chacha20poly1305::{AeadCore, KeySizeUser, KeyInit, AeadInPlace}; + +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/mod.rs b/ciphers/src/subtle/mod.rs index b4f4456..70c9425 100644 --- a/ciphers/src/subtle/mod.rs +++ b/ciphers/src/subtle/mod.rs @@ -1 +1,2 @@ pub mod incorrect_hmac_blake2b; +pub mod chacha20poly1305_ietf;