diff --git a/userspace/Cargo.lock b/userspace/Cargo.lock index ccc12eeb..181fea9c 100644 --- a/userspace/Cargo.lock +++ b/userspace/Cargo.lock @@ -208,6 +208,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64ct" version = "1.6.0" @@ -631,7 +637,7 @@ version = "0.1.0" dependencies = [ "clap", "ed25519-dalek", - "rand 0.8.5 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand", "rsa", "thiserror 1.0.69", ] @@ -646,9 +652,13 @@ dependencies = [ "chacha20poly1305", "cross", "der", + "ecdsa", + "elliptic-curve", "hmac", - "rand 0.8.5 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", - "rand_core 0.6.4 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "p256", + "p384", + "rand", + "rand_core", "rsa", "rustls", "sha2", @@ -656,6 +666,18 @@ dependencies = [ "x25519-dalek", ] +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -690,7 +712,8 @@ checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" [[package]] name = "curve25519-dalek" version = "4.1.3" -source = "git+https://git.alnyan.me/yggdrasil/curve25519-dalek.git?branch=alnyan%2Fyggdrasil#5f4dbb09259347077d3a5024ba60c77efde93a3a" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", @@ -705,7 +728,8 @@ dependencies = [ [[package]] name = "curve25519-dalek-derive" version = "0.1.1" -source = "git+https://git.alnyan.me/yggdrasil/curve25519-dalek.git?branch=alnyan%2Fyggdrasil#5f4dbb09259347077d3a5024ba60c77efde93a3a" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", @@ -838,6 +862,20 @@ dependencies = [ "yggdrasil-rt", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "ed25519" version = "2.2.3" @@ -845,17 +883,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", - "signature 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "signature", ] [[package]] name = "ed25519-dalek" -version = "2.1.1" -source = "git+https://git.alnyan.me/yggdrasil/curve25519-dalek.git?branch=alnyan%2Fyggdrasil#5f4dbb09259347077d3a5024ba60c77efde93a3a" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ "curve25519-dalek", "ed25519", - "rand_core 0.6.4 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand_core", "serde", "sha2", "subtle", @@ -868,6 +907,27 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "embedded-io" version = "0.4.0" @@ -943,6 +1003,16 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -1036,6 +1106,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1091,6 +1162,17 @@ dependencies = [ "polyval", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "hash32" version = "0.2.1" @@ -1144,6 +1226,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1627,7 +1718,7 @@ dependencies = [ "http", "log", "logsink", - "rand 0.8.5 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand", "runtime", "serde", "serde_json", @@ -1661,8 +1752,9 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.2" -source = "git+https://git.alnyan.me/yggdrasil/num-bigint-dig.git?branch=alnyan%2Fyggdrasil-0.8.2#e0ff3fcf8e9f5612be8ede9df7458bd762ac525f" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" dependencies = [ "byteorder", "lazy_static", @@ -1670,7 +1762,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand", "smallvec", "zeroize", ] @@ -1990,6 +2082,30 @@ dependencies = [ "ttf-parser 0.25.1", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "parking_lot" version = "0.12.4" @@ -2067,7 +2183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand", ] [[package]] @@ -2238,6 +2354,15 @@ dependencies = [ "syn", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-crate" version = "3.3.0" @@ -2291,15 +2416,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.8.5" @@ -2307,7 +2423,7 @@ source = "git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand_core", ] [[package]] @@ -2316,16 +2432,7 @@ version = "0.3.1" source = "git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4#27d8b41f68e239bf5b2e5079554f1b861966672f" dependencies = [ "ppv-lite86", - "rand_core 0.6.4 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", + "rand_core", ] [[package]] @@ -2437,6 +2544,16 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.14" @@ -2454,7 +2571,8 @@ dependencies = [ [[package]] name = "rsa" version = "0.9.8" -source = "git+https://git.alnyan.me/yggdrasil/rsa.git?branch=alnyan%2Fyggdrasil-0.9.8#6c5b186b9025d5e4f28882a5ac7202357c392874" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ "const-oid", "digest", @@ -2463,8 +2581,8 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8", - "rand_core 0.6.4 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", - "signature 2.2.0 (git+https://git.alnyan.me/yggdrasil/rustcrypto-traits.git?branch=alnyan%2Fyggdrasil-2.2.0)", + "rand_core", + "signature", "spki", "subtle", "zeroize", @@ -2482,7 +2600,7 @@ dependencies = [ "libterm", "log", "logsink", - "rand 0.8.5 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand", "sha2", "thiserror 1.0.69", "x25519-dalek", @@ -2541,8 +2659,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.16" -source = "git+https://git.alnyan.me/yggdrasil/rustls.git?branch=alnyan%2Fyggdrasil#07a6b26eec16e54ba50d3854813b89cd7f703279" +version = "0.23.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" dependencies = [ "log", "once_cell", @@ -2563,9 +2682,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring", "rustls-pki-types", @@ -2628,6 +2747,20 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "semver" version = "1.0.26" @@ -2656,9 +2789,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" dependencies = [ "itoa", "memchr", @@ -2741,17 +2874,9 @@ name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "rand_core 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "git+https://git.alnyan.me/yggdrasil/rustcrypto-traits.git?branch=alnyan%2Fyggdrasil-2.2.0#ac3771039858e20b812450ff7b6bf67e29436208" dependencies = [ "digest", - "rand_core 0.6.4 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand_core", ] [[package]] @@ -2943,7 +3068,7 @@ dependencies = [ "log", "logsink", "pci-ids", - "rand 0.8.5 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand", "regex", "runtime", "serde", @@ -3504,9 +3629,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ "rustls-pki-types", ] @@ -3940,10 +4065,11 @@ checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "x25519-dalek" version = "2.0.1" -source = "git+https://git.alnyan.me/yggdrasil/curve25519-dalek.git?branch=alnyan%2Fyggdrasil#5f4dbb09259347077d3a5024ba60c77efde93a3a" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", - "rand_core 0.6.4 (git+https://git.alnyan.me/yggdrasil/rand.git?branch=alnyan%2Fyggdrasil-rng_core-0.6.4)", + "rand_core", "serde", "zeroize", ] diff --git a/userspace/Cargo.toml b/userspace/Cargo.toml index 63e41e40..a43abc00 100644 --- a/userspace/Cargo.toml +++ b/userspace/Cargo.toml @@ -42,28 +42,33 @@ chrono = { version = "0.4.31", default-features = false } postcard = { version = "1.1.1", features = ["alloc"] } tui = { version = "0.19.0", default-features = false } toml = "0.8.20" -sha2 = { version = "0.10.9" } +url = "2.5.0" +http = "1.1.0" + +# Cryptography +rustls = { version = "0.23.29", default-features = false, features = ["std", "logging", "tls12", "custom-provider"] } +ed25519-dalek = "2.2.0" +x25519-dalek = "2.0.1" +curve25519-dalek = "4.1.3" +elliptic-curve = "0.13.8" +rsa = "0.9.8" +ecdsa = "0.16.9" +p256 = "0.13.2" +p384 = "0.13.1" hmac = { version = "0.12.1" } aes = { version = "0.8.4" } der = { version = "0.7.10" } chacha20poly1305 = { version = "0.10.1", default-features = false, features = ["alloc"] } aes-gcm = { version = "0.10.1", default-features = false, features = ["alloc"] } aead = { version = "0.5.2", default-features = false, features = ["alloc"] } +sha2 = { version = "0.10.9" } webpki-roots = "1.0.1" -url = "2.5.0" -http = "1.1.0" raqote = { version = "0.8.3", default-features = false } # Vendored/patched dependencies rand = { git = "https://git.alnyan.me/yggdrasil/rand.git", branch = "alnyan/yggdrasil-rng_core-0.6.4" } rand_core = { git = "https://git.alnyan.me/yggdrasil/rand.git", branch = "alnyan/yggdrasil-rng_core-0.6.4" } -ring = { git = "https://git.alnyan.me/yggdrasil/ring.git", branch = "alnyan/yggdrasil" } -rsa = { git = "https://git.alnyan.me/yggdrasil/rsa.git", branch = "alnyan/yggdrasil-0.9.8" } -rustls = { git = "https://git.alnyan.me/yggdrasil/rustls.git", branch = "alnyan/yggdrasil", default-features = false, features = ["std", "logging", "tls12", "custom-provider"] } -curve25519-dalek = { git = "https://git.alnyan.me/yggdrasil/curve25519-dalek.git", branch = "alnyan/yggdrasil" } -x25519-dalek = { git = "https://git.alnyan.me/yggdrasil/curve25519-dalek.git", branch = "alnyan/yggdrasil" } -ed25519-dalek = { git = "https://git.alnyan.me/yggdrasil/curve25519-dalek.git", branch = "alnyan/yggdrasil" } # Internal crates libterm.path = "lib/libterm" @@ -83,3 +88,7 @@ hclient.path = "lib/hclient" [workspace.lints.rust] unexpected_cfgs = { level = "allow", check-cfg = ['cfg(rust_analyzer)'] } + +[patch.crates-io] +rand_core = { git = "https://git.alnyan.me/yggdrasil/rand.git", branch = "alnyan/yggdrasil-rng_core-0.6.4", package = "rand_core" } +rand = { git = "https://git.alnyan.me/yggdrasil/rand.git", branch = "alnyan/yggdrasil-rng_core-0.6.4" } diff --git a/userspace/lib/cryptic/Cargo.toml b/userspace/lib/cryptic/Cargo.toml index ea224558..251c3bc9 100644 --- a/userspace/lib/cryptic/Cargo.toml +++ b/userspace/lib/cryptic/Cargo.toml @@ -19,6 +19,10 @@ chacha20poly1305.workspace = true aes-gcm.workspace = true aead.workspace = true webpki-roots.workspace = true +ecdsa.workspace = true +elliptic-curve.workspace = true +p256.workspace = true +p384.workspace = true [lints] workspace = true diff --git a/userspace/lib/cryptic/src/cipher/aes_gcm.rs b/userspace/lib/cryptic/src/cipher/aes_gcm.rs index ab61a07c..8a91886a 100644 --- a/userspace/lib/cryptic/src/cipher/aes_gcm.rs +++ b/userspace/lib/cryptic/src/cipher/aes_gcm.rs @@ -11,7 +11,7 @@ use rustls::{ OutboundPlainMessage, PrefixedPayload, Tls12AeadAlgorithm, Tls13AeadAlgorithm, UnsupportedOperationError, }, - ConnectionTrafficSecrets, + ConnectionTrafficSecrets, ContentType, ProtocolVersion, }; use crate::cipher::{DecryptBufferAdapter, EncryptBufferAdapter}; @@ -161,7 +161,13 @@ where self.0 .encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload)) .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new(msg.typ, msg.version, payload)) + .map(|_| { + OutboundOpaqueMessage::new( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + payload, + ) + }) } fn encrypted_payload_len(&self, payload_len: usize) -> usize { diff --git a/userspace/lib/cryptic/src/cipher/chacha20poly1305.rs b/userspace/lib/cryptic/src/cipher/chacha20poly1305.rs index 3125403b..11f0d2b1 100644 --- a/userspace/lib/cryptic/src/cipher/chacha20poly1305.rs +++ b/userspace/lib/cryptic/src/cipher/chacha20poly1305.rs @@ -7,7 +7,7 @@ use rustls::{ OutboundPlainMessage, PrefixedPayload, Tls12AeadAlgorithm, Tls13AeadAlgorithm, UnsupportedOperationError, }, - ConnectionTrafficSecrets, + ConnectionTrafficSecrets, ContentType, ProtocolVersion, }; use crate::cipher::{DecryptBufferAdapter, EncryptBufferAdapter}; @@ -102,7 +102,13 @@ impl MessageEncrypter for Tls13Cipher { self.0 .encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload)) .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new(msg.typ, msg.version, payload)) + .map(|_| { + OutboundOpaqueMessage::new( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + payload, + ) + }) } fn encrypted_payload_len(&self, payload_len: usize) -> usize { diff --git a/userspace/lib/cryptic/src/lib.rs b/userspace/lib/cryptic/src/lib.rs index 3c5b11a1..2f314dd1 100644 --- a/userspace/lib/cryptic/src/lib.rs +++ b/userspace/lib/cryptic/src/lib.rs @@ -14,10 +14,7 @@ pub mod rustls; pub mod verify; pub fn rustls_client() -> ConfigBuilder { - ClientConfig::builder_with_details( - rustls::provider().into(), - Arc::new(rustls::TimeProviderImpl), - ) + ClientConfig::builder_with_provider(rustls::provider().into()) } pub fn rustls_default_client() -> ConfigBuilder { diff --git a/userspace/lib/cryptic/src/rustls.rs b/userspace/lib/cryptic/src/rustls.rs index 6fe70bfb..18603adf 100644 --- a/userspace/lib/cryptic/src/rustls.rs +++ b/userspace/lib/cryptic/src/rustls.rs @@ -9,16 +9,12 @@ use rustls::{ }, pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime}, sign::SigningKey, - time_provider::TimeProvider, CipherSuite, CipherSuiteCommon, DigitallySignedStruct, SignatureScheme, SupportedCipherSuite, Tls12CipherSuite, Tls13CipherSuite, }; use crate::{cipher, hash, hmac, kx, verify}; -#[derive(Debug)] -pub struct TimeProviderImpl; - #[derive(Debug)] struct Provider; @@ -67,12 +63,6 @@ impl ServerCertVerifier for InsecureServerCertificateVerifier { } } -impl TimeProvider for TimeProviderImpl { - fn current_time(&self) -> Option { - Some(UnixTime::now()) - } -} - pub fn provider() -> CryptoProvider { CryptoProvider { cipher_suites: CIPHER_SUITES.to_vec(), @@ -113,18 +103,33 @@ static CIPHER_SUITES: &[SupportedCipherSuite] = &[ ]; static KX_GROUPS: &[&dyn SupportedKxGroup] = &[&kx::X25519]; static SIGNATURE_VERIFICATION_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { - all: &[verify::RSA_PSS_SHA256, verify::RSA_PKCS1_SHA256], + all: &[ + verify::RSA_PSS_SHA256, + verify::RSA_PKCS1_SHA256, + verify::ECDSA_NISTP256_SHA256, + verify::ECDSA_NISTP384_SHA384, + ], mapping: &[ (SignatureScheme::RSA_PSS_SHA256, &[verify::RSA_PSS_SHA256]), ( SignatureScheme::RSA_PKCS1_SHA256, &[verify::RSA_PKCS1_SHA256], ), + ( + SignatureScheme::ECDSA_NISTP256_SHA256, + &[verify::ECDSA_NISTP256_SHA256], + ), + ( + SignatureScheme::ECDSA_NISTP384_SHA384, + &[verify::ECDSA_NISTP384_SHA384], + ), ], }; static SUPPORTED_SIGNATURE_SCHEMES: &[SignatureScheme] = &[ SignatureScheme::RSA_PSS_SHA256, SignatureScheme::RSA_PKCS1_SHA256, + SignatureScheme::ECDSA_NISTP256_SHA256, + SignatureScheme::ECDSA_NISTP384_SHA384, ]; // TLSv1.3 diff --git a/userspace/lib/cryptic/src/verify/ecdsa.rs b/userspace/lib/cryptic/src/verify/ecdsa.rs new file mode 100644 index 00000000..e81731c2 --- /dev/null +++ b/userspace/lib/cryptic/src/verify/ecdsa.rs @@ -0,0 +1,35 @@ +use std::marker::PhantomData; + +use ecdsa::PrimeCurve; +use elliptic_curve::PrimeCurveArithmetic; +use rustls::pki_types::{ + alg_id, AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm, +}; + +#[derive(Debug)] +struct EcdsaVerify(PhantomData); + +pub(crate) static ECDSA_NISTP256_SHA256: &dyn SignatureVerificationAlgorithm = + &EcdsaVerify::(PhantomData); +pub(crate) static ECDSA_NISTP384_SHA384: &dyn SignatureVerificationAlgorithm = + &EcdsaVerify::(PhantomData); + +impl SignatureVerificationAlgorithm for EcdsaVerify { + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + alg_id::ECDSA_P384 + } + + fn signature_alg_id(&self) -> AlgorithmIdentifier { + alg_id::ECDSA_SHA384 + } + + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + let _ = (public_key, message, signature); + todo!("Implement signature verification for ECDSA, curves NISTP256, NISTP384") + } +} diff --git a/userspace/lib/cryptic/src/verify/mod.rs b/userspace/lib/cryptic/src/verify/mod.rs index 0dcb8369..ae9eedaa 100644 --- a/userspace/lib/cryptic/src/verify/mod.rs +++ b/userspace/lib/cryptic/src/verify/mod.rs @@ -1,72 +1,5 @@ -use der::Reader; -use rsa::{pkcs1v15, pss, signature::Verifier, BigUint, RsaPublicKey}; -use rustls::pki_types::{ - alg_id, AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm, -}; +pub mod ecdsa; +pub mod rsa; -#[derive(Debug)] -struct RsaPssSha256Verify; -#[derive(Debug)] -struct RsaPkcs1Sha256Verify; - -pub(crate) static RSA_PSS_SHA256: &dyn SignatureVerificationAlgorithm = &RsaPssSha256Verify; -pub(crate) static RSA_PKCS1_SHA256: &dyn SignatureVerificationAlgorithm = &RsaPkcs1Sha256Verify; - -impl SignatureVerificationAlgorithm for RsaPssSha256Verify { - fn public_key_alg_id(&self) -> AlgorithmIdentifier { - alg_id::RSA_ENCRYPTION - } - - fn signature_alg_id(&self) -> AlgorithmIdentifier { - alg_id::RSA_PSS_SHA256 - } - - fn verify_signature( - &self, - public_key: &[u8], - message: &[u8], - signature: &[u8], - ) -> Result<(), InvalidSignature> { - let public_key = decode_spki_spk(public_key)?; - let signature = pss::Signature::try_from(signature).map_err(|_| InvalidSignature)?; - pss::VerifyingKey::::new(public_key) - .verify(message, &signature) - .map_err(|_| InvalidSignature) - } -} - -impl SignatureVerificationAlgorithm for RsaPkcs1Sha256Verify { - fn public_key_alg_id(&self) -> AlgorithmIdentifier { - alg_id::RSA_ENCRYPTION - } - - fn signature_alg_id(&self) -> AlgorithmIdentifier { - alg_id::RSA_PKCS1_SHA256 - } - - fn verify_signature( - &self, - public_key: &[u8], - message: &[u8], - signature: &[u8], - ) -> Result<(), InvalidSignature> { - let public_key = decode_spki_spk(public_key)?; - let signature = pkcs1v15::Signature::try_from(signature).map_err(|_| InvalidSignature)?; - pkcs1v15::VerifyingKey::::new_unprefixed(public_key) - .verify(message, &signature) - .map_err(|_| InvalidSignature) - } -} - -fn decode_spki_spk(spki_spk: &[u8]) -> Result { - // public_key: unfortunately this is not a whole SPKI, but just the key material. - // decode the two integers manually. - let mut reader = der::SliceReader::new(spki_spk).map_err(|_| InvalidSignature)?; - let ne: [der::asn1::UintRef<'_>; 2] = reader.decode().map_err(|_| InvalidSignature)?; - - RsaPublicKey::new( - BigUint::from_bytes_be(ne[0].as_bytes()), - BigUint::from_bytes_be(ne[1].as_bytes()), - ) - .map_err(|_| InvalidSignature) -} +pub(crate) use ecdsa::{ECDSA_NISTP256_SHA256, ECDSA_NISTP384_SHA384}; +pub(crate) use rsa::{RSA_PKCS1_SHA256, RSA_PSS_SHA256}; diff --git a/userspace/lib/cryptic/src/verify/rsa.rs b/userspace/lib/cryptic/src/verify/rsa.rs new file mode 100644 index 00000000..0dcb8369 --- /dev/null +++ b/userspace/lib/cryptic/src/verify/rsa.rs @@ -0,0 +1,72 @@ +use der::Reader; +use rsa::{pkcs1v15, pss, signature::Verifier, BigUint, RsaPublicKey}; +use rustls::pki_types::{ + alg_id, AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm, +}; + +#[derive(Debug)] +struct RsaPssSha256Verify; +#[derive(Debug)] +struct RsaPkcs1Sha256Verify; + +pub(crate) static RSA_PSS_SHA256: &dyn SignatureVerificationAlgorithm = &RsaPssSha256Verify; +pub(crate) static RSA_PKCS1_SHA256: &dyn SignatureVerificationAlgorithm = &RsaPkcs1Sha256Verify; + +impl SignatureVerificationAlgorithm for RsaPssSha256Verify { + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + alg_id::RSA_ENCRYPTION + } + + fn signature_alg_id(&self) -> AlgorithmIdentifier { + alg_id::RSA_PSS_SHA256 + } + + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + let public_key = decode_spki_spk(public_key)?; + let signature = pss::Signature::try_from(signature).map_err(|_| InvalidSignature)?; + pss::VerifyingKey::::new(public_key) + .verify(message, &signature) + .map_err(|_| InvalidSignature) + } +} + +impl SignatureVerificationAlgorithm for RsaPkcs1Sha256Verify { + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + alg_id::RSA_ENCRYPTION + } + + fn signature_alg_id(&self) -> AlgorithmIdentifier { + alg_id::RSA_PKCS1_SHA256 + } + + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + let public_key = decode_spki_spk(public_key)?; + let signature = pkcs1v15::Signature::try_from(signature).map_err(|_| InvalidSignature)?; + pkcs1v15::VerifyingKey::::new_unprefixed(public_key) + .verify(message, &signature) + .map_err(|_| InvalidSignature) + } +} + +fn decode_spki_spk(spki_spk: &[u8]) -> Result { + // public_key: unfortunately this is not a whole SPKI, but just the key material. + // decode the two integers manually. + let mut reader = der::SliceReader::new(spki_spk).map_err(|_| InvalidSignature)?; + let ne: [der::asn1::UintRef<'_>; 2] = reader.decode().map_err(|_| InvalidSignature)?; + + RsaPublicKey::new( + BigUint::from_bytes_be(ne[0].as_bytes()), + BigUint::from_bytes_be(ne[1].as_bytes()), + ) + .map_err(|_| InvalidSignature) +} diff --git a/userspace/lib/hclient/src/client.rs b/userspace/lib/hclient/src/client.rs index 643f2bf2..aa2f747e 100644 --- a/userspace/lib/hclient/src/client.rs +++ b/userspace/lib/hclient/src/client.rs @@ -160,7 +160,7 @@ fn recv_http1_line( fn recv_response_http1( mut connection: C, ) -> Result, HttpError> { - let mut buffer = [0; 256]; + let mut buffer = [0; 512]; let len = recv_http1_line(&mut connection, &mut buffer)?; let mut content_length = None; diff --git a/userspace/lib/hclient/src/connection/auto.rs b/userspace/lib/hclient/src/connection/auto.rs index 88b96599..7acba3ed 100644 --- a/userspace/lib/hclient/src/connection/auto.rs +++ b/userspace/lib/hclient/src/connection/auto.rs @@ -54,15 +54,17 @@ impl HttpConnector for AutoConnector { } fn default_port(&self, scheme: &str) -> u16 { - match scheme { - "http" => 80, - "https" => 443, - _ => unreachable!(), + if scheme.eq_ignore_ascii_case("http") { + 80 + } else if scheme.eq_ignore_ascii_case("https") { + 443 + } else { + unreachable!() } } fn supports_scheme(&self, scheme: &str) -> bool { - scheme == "http" || scheme == "https" + scheme.eq_ignore_ascii_case("http") || scheme.eq_ignore_ascii_case("https") } } diff --git a/userspace/lib/hclient/src/connection/tcp.rs b/userspace/lib/hclient/src/connection/tcp.rs index 7676cac1..bdc0f3bc 100644 --- a/userspace/lib/hclient/src/connection/tcp.rs +++ b/userspace/lib/hclient/src/connection/tcp.rs @@ -36,7 +36,7 @@ impl HttpConnector for TcpConnector { } fn supports_scheme(&self, scheme: &str) -> bool { - scheme == "http" + scheme.eq_ignore_ascii_case("http") } } diff --git a/userspace/lib/hclient/src/connection/tls.rs b/userspace/lib/hclient/src/connection/tls.rs index 986fb1a9..7227dd5e 100644 --- a/userspace/lib/hclient/src/connection/tls.rs +++ b/userspace/lib/hclient/src/connection/tls.rs @@ -13,8 +13,10 @@ pub struct TlsConnector { config: Arc, } +struct TcpStreamWrapper(TcpStream); + pub struct TlsConnection { - stream: StreamOwned, + stream: StreamOwned, } #[derive(Debug, thiserror::Error)] @@ -58,7 +60,7 @@ impl HttpConnector for TlsConnector { let tls_server_name = ServerName::try_from(server_name.to_owned())?; let connection = ClientConnection::new(self.config.clone(), tls_server_name)?; let socket = TcpConnector.connect(remote, scheme, server_name, timeout, options)?; - let stream = StreamOwned::new(connection, socket); + let stream = StreamOwned::new(connection, TcpStreamWrapper(socket)); Ok(TlsConnection { stream }) } @@ -68,7 +70,43 @@ impl HttpConnector for TlsConnector { } fn supports_scheme(&self, scheme: &str) -> bool { - scheme == "https" + scheme.eq_ignore_ascii_case("https") + } +} + +impl io::Write for TcpStreamWrapper { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + // FIXME: this is a dumb implementation of write_vectored + fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { + let mut count = 0; + for buf in bufs { + let len = self.0.write(&buf[..])?; + count += len; + if len < buf.len() { + break; + } + } + Ok(count) + } + + fn flush(&mut self) -> io::Result<()> { + self.0.flush() + } +} + +impl io::Read for TcpStreamWrapper { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.0.read(buf) + } + + fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { + if bufs.len() > 1 { + todo!("This is a notification for myself to implement read_vectored on sockets"); + } + self.read(&mut bufs[0][..]) } } diff --git a/userspace/netutils/src/http.rs b/userspace/netutils/src/http.rs index ac848b01..ce03cf3d 100644 --- a/userspace/netutils/src/http.rs +++ b/userspace/netutils/src/http.rs @@ -66,6 +66,7 @@ impl Write for Output { fn get(url: Uri, output: Option) -> Result<(), Error> { let mut output = Output::open(output)?; + // TODO proper root certificate store let mut client = HttpClient::from(AutoConnector::with_insecure_tls()); let mut buffer = [0; 4096]; @@ -86,6 +87,7 @@ fn get(url: Uri, output: Option) -> Result<(), Error> { } fn main() -> ExitCode { + logsink::setup_logging(false); let args = Arguments::parse(); let result = match args.method {