diff --git a/Cargo.lock b/Cargo.lock index 541d762..54ec4ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,6 +64,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "atty" version = "0.2.14" @@ -457,14 +463,13 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.0.0-pre.5" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67bc65846be335cb20f4e52d49a437b773a2c1fdb42b19fc84e79e6f6771536f" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" dependencies = [ - "cfg-if 1.0.0", - "fiat-crypto", - "packed_simd_2", - "platforms", + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", "subtle", "zeroize", ] @@ -575,12 +580,6 @@ dependencies = [ "instant", ] -[[package]] -name = "fiat-crypto" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a214f5bb88731d436478f3ae1f8a277b62124089ba9fb67f4f93fb100ef73c90" - [[package]] name = "filetime" version = "0.2.19" @@ -757,6 +756,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -1011,12 +1021,6 @@ version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" -[[package]] -name = "libm" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" - [[package]] name = "link-cplusplus" version = "1.0.8" @@ -1159,6 +1163,31 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "noise-protocol" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb474d36dfe51bb4d7e733fee2b0dfd92ee1b95c716030a70e92737dea1a52b" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "noise-rust-crypto" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e7cfeb8e6a63b4a5ccef34ed7a22d084a129b1e53a000c080bbc54c0da6f8c" +dependencies = [ + "aes-gcm", + "blake2", + "chacha20poly1305", + "getrandom 0.2.8", + "noise-protocol", + "sha2 0.10.6", + "x25519-dalek", + "zeroize", +] + [[package]] name = "notify" version = "4.0.17" @@ -1342,16 +1371,6 @@ version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" -[[package]] -name = "packed_simd_2" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" -dependencies = [ - "cfg-if 1.0.0", - "libm", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -1421,12 +1440,6 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" -[[package]] -name = "platforms" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" - [[package]] name = "plotters" version = "0.3.4" @@ -1564,7 +1577,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -1574,7 +1587,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -1583,7 +1605,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.8", ] [[package]] @@ -1652,15 +1674,6 @@ dependencies = [ "winapi 0.3.9", ] -[[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.36.7" @@ -1734,12 +1747,6 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" - [[package]] name = "serde" version = "1.0.152" @@ -1860,22 +1867,6 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" -[[package]] -name = "snow" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d" -dependencies = [ - "aes-gcm", - "blake2", - "chacha20poly1305", - "curve25519-dalek", - "rand_core", - "rustc_version", - "sha2 0.10.6", - "subtle", -] - [[package]] name = "socket2" version = "0.4.7" @@ -1946,7 +1937,7 @@ dependencies = [ "bytes", "criterion", "futures", - "getrandom", + "getrandom 0.2.8", "hmac", "lazy_static", "openssl", @@ -1980,9 +1971,10 @@ dependencies = [ "chrono", "futures", "lazy_static", + "noise-protocol", + "noise-rust-crypto", "notify", "preserves-schema", - "snow", "structopt", "syndicate", "syndicate-macros", @@ -2005,6 +1997,18 @@ dependencies = [ "syndicate", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -2305,6 +2309,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "universal-hash" version = "0.4.1" @@ -2367,6 +2377,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -2554,7 +2570,33 @@ dependencies = [ ] [[package]] -name = "zeroize" -version = "1.5.7" +name = "x25519-dalek" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" +dependencies = [ + "curve25519-dalek", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/syndicate-server/Cargo.toml b/syndicate-server/Cargo.toml index eaca2bb..8ecc8a8 100644 --- a/syndicate-server/Cargo.toml +++ b/syndicate-server/Cargo.toml @@ -21,8 +21,9 @@ syndicate-macros = { path = "../syndicate-macros", version = "0.20.0"} chrono = "0.4" futures = "0.3" lazy_static = "1.4" +noise-protocol = "0.1" +noise-rust-crypto = "0.5" notify = "4.0" -snow = "0.9" structopt = "0.3" tungstenite = "0.13" diff --git a/syndicate-server/protocols/schema-bundle.bin b/syndicate-server/protocols/schema-bundle.bin index 6b21b35..604b4d7 100644 --- a/syndicate-server/protocols/schema-bundle.bin +++ b/syndicate-server/protocols/schema-bundle.bin @@ -1,6 +1,7 @@ ´³bundle·µ³ documentation„´³schema·³version‘³ definitions·³Url´³orµµ±present´³dict·³url´³named³url´³atom³String„„„„„µ±invalid´³dict·³url´³named³url³any„„„„µ±absent´³dict·„„„„„³IOList´³orµµ±bytes´³atom³ ByteString„„µ±string´³atom³String„„µ±nested´³seqof´³refµ„³IOList„„„„„³Metadata´³rec´³lit³metadata„´³tupleµ´³named³object³any„´³named³info´³dictof´³atom³Symbol„³any„„„„„³ Description´³orµµ±present´³dict·³ description´³named³ description´³refµ„³IOList„„„„„µ±invalid´³dict·³ description´³named³ description³any„„„„µ±absent´³dict·„„„„„„³ embeddedType€„„µ³ gatekeeperMux„´³schema·³version‘³ definitions·³API´³orµµ±Resolve´³refµ³ -gatekeeper„³Resolve„„µ±Connect´³refµ³noise„³Connect„„„„³ NoiseService´³rec´³lit³noise„´³tupleµ´³named³serviceSelector³any„´³named³responderListener´³embedded´³refµ³noise„³Connect„„„„„„„³ embeddedType€„„µ³externalServices„´³schema·³version‘³ definitions·³Process´³orµµ±simple´³refµ„³ CommandLine„„µ±full´³refµ„³ FullProcess„„„„³Service´³refµ„³ DaemonService„³ClearEnv´³orµµ±present´³dict·³clearEnv´³named³clearEnv´³atom³Boolean„„„„„µ±invalid´³dict·³clearEnv´³named³clearEnv³any„„„„µ±absent´³dict·„„„„„³EnvValue´³orµµ±set´³atom³String„„µ±remove´³lit€„„µ±invalid³any„„„³Protocol´³orµµ±none´³lit³none„„µ±binarySyndicate´³lit³application/syndicate„„µ± textSyndicate´³lit³text/syndicate„„„„³ +gatekeeper„³Resolve„„µ±Connect´³refµ³noise„³Connect„„„„³ NoiseService´³rec´³lit³noise„´³tupleµ´³named³spec´³refµ³noise„³ NoiseSpec„„´³named³service´³embedded³any„„„„„³SecretKeyField´³orµµ±present´³dict·³ secretKey´³named³ secretKey´³atom³ +ByteString„„„„„µ±invalid´³dict·³ secretKey´³named³ secretKey³any„„„„µ±absent´³dict·„„„„„³NoiseServiceSpec´³andµ´³named³base´³refµ³noise„³ NoiseSpec„„´³named³ secretKey´³refµ„³SecretKeyField„„„„„³ embeddedType€„„µ³externalServices„´³schema·³version‘³ definitions·³Process´³orµµ±simple´³refµ„³ CommandLine„„µ±full´³refµ„³ FullProcess„„„„³Service´³refµ„³ DaemonService„³ClearEnv´³orµµ±present´³dict·³clearEnv´³named³clearEnv´³atom³Boolean„„„„„µ±invalid´³dict·³clearEnv´³named³clearEnv³any„„„„µ±absent´³dict·„„„„„³EnvValue´³orµµ±set´³atom³String„„µ±remove´³lit€„„µ±invalid³any„„„³Protocol´³orµµ±none´³lit³none„„µ±binarySyndicate´³lit³application/syndicate„„µ± textSyndicate´³lit³text/syndicate„„„„³ ProcessDir´³orµµ±present´³dict·³dir´³named³dir´³atom³String„„„„„µ±invalid´³dict·³dir´³named³dir³any„„„„µ±absent´³dict·„„„„„³ ProcessEnv´³orµµ±present´³dict·³env´³named³env´³dictof´³refµ„³ EnvVariable„´³refµ„³EnvValue„„„„„„µ±invalid´³dict·³env´³named³env³any„„„„µ±absent´³dict·„„„„„³ CommandLine´³orµµ±shell´³atom³String„„µ±full´³refµ„³FullCommandLine„„„„³ EnvVariable´³orµµ±string´³atom³String„„µ±symbol´³atom³Symbol„„µ±invalid³any„„„³ FullProcess´³andµ´³dict·³argv´³named³argv´³refµ„³ CommandLine„„„„´³named³env´³refµ„³ ProcessEnv„„´³named³dir´³refµ„³ diff --git a/syndicate-server/protocols/schemas/gatekeeperMux.prs b/syndicate-server/protocols/schemas/gatekeeperMux.prs index 1f81e89..6310b5e 100644 --- a/syndicate-server/protocols/schemas/gatekeeperMux.prs +++ b/syndicate-server/protocols/schemas/gatekeeperMux.prs @@ -2,4 +2,6 @@ version 1 . API = gatekeeper.Resolve / noise.Connect . -NoiseService = . +NoiseService = . +NoiseServiceSpec = @base noise.NoiseSpec & @secretKey SecretKeyField . +SecretKeyField = @present { secretKey: bytes } / @invalid { secretKey: any } / @absent {} . diff --git a/syndicate-server/src/gatekeeper.rs b/syndicate-server/src/gatekeeper.rs index 9ca0564..a387a29 100644 --- a/syndicate-server/src/gatekeeper.rs +++ b/syndicate-server/src/gatekeeper.rs @@ -1,14 +1,30 @@ +use noise_protocol::CipherState; +use noise_protocol::U8Array; +use noise_protocol::patterns::HandshakePattern; +use noise_rust_crypto::Blake2s; +use noise_rust_crypto::ChaCha20Poly1305; +use noise_rust_crypto::X25519; use preserves_schema::Codec; +use syndicate::relay::Mutex; +use syndicate::relay::TunnelRelay; +use syndicate::trace::TurnCause; +use syndicate::value::NoEmbeddedDomainCodec; +use syndicate::value::packed::PackedWriter; +use std::convert::TryInto; use std::sync::Arc; use syndicate::actor::*; use syndicate::during::DuringResult; use syndicate::value::NestedValue; +use syndicate::schemas::dataspace; use syndicate::schemas::gatekeeper; +use syndicate::schemas::noise; use crate::language::language; -use crate::schemas::gatekeeper_mux::{Api, NoiseService}; +use crate::schemas::gatekeeper_mux::Api; +use crate::schemas::gatekeeper_mux::NoiseServiceSpec; +use crate::schemas::gatekeeper_mux::SecretKeyField; // pub fn bind( // t: &mut Activation, @@ -29,7 +45,7 @@ pub fn handle_assertion( ) -> DuringResult> { match a { Api::Resolve(resolve_box) => handle_resolve(ds, t, *resolve_box), - Api::Connect(_) => todo!(), + Api::Connect(connect_box) => handle_connect(ds, t, *connect_box), } } @@ -38,8 +54,6 @@ fn handle_resolve( t: &mut Activation, a: gatekeeper::Resolve, ) -> DuringResult> { - use syndicate::schemas::dataspace; - let gatekeeper::Resolve { sturdyref, observer } = a; let queried_oid = sturdyref.oid.clone(); let handler = syndicate::entity(observer) @@ -76,3 +90,263 @@ fn handle_resolve( Ok(None) } } + +fn handle_connect( + ds: &mut Arc, + t: &mut Activation, + a: noise::Connect, +) -> DuringResult> { + let noise::Connect { service_selector, initiator_session } = a; + let handler = syndicate::entity(()) + .on_asserted_facet(move |_state, t, a: AnyValue| { + let initiator_session = Arc::clone(&initiator_session); + t.spawn_link(None, move |t| { + let bindings = a.value().to_sequence()?; + let spec: NoiseServiceSpec = language().parse(&bindings[0])?; + let protocol = match spec.base.protocol { + noise::NoiseProtocol::Present { protocol } => + protocol, + noise::NoiseProtocol::Invalid { protocol } => + Err(format!("Invalid noise protocol {:?}", protocol))?, + noise::NoiseProtocol::Absent => + language().unparse(&noise::DefaultProtocol).value().to_string()?.clone(), + }; + let psks = match spec.base.pre_shared_keys { + noise::NoisePreSharedKeys::Present { pre_shared_keys } => + pre_shared_keys, + noise::NoisePreSharedKeys::Invalid { pre_shared_keys } => + Err(format!("Invalid pre-shared-keys {:?}", pre_shared_keys))?, + noise::NoisePreSharedKeys::Absent => + vec![], + }; + let secret_key = match spec.secret_key { + SecretKeyField::Present { secret_key } => + Some(secret_key), + SecretKeyField::Invalid { secret_key } => + Err(format!("Invalid secret key {:?}", secret_key))?, + SecretKeyField::Absent => + None, + }; + let service = bindings[1].value().to_embedded()?; + run_noise_responder(t, + spec.base.service, + protocol, + psks, + secret_key, + initiator_session, + Arc::clone(service)) + }); + Ok(()) + }) + .create_cap(t); + if let Some(oh) = ds.assert(t, language(), &dataspace::Observe { + // TODO: codegen plugin to generate pattern constructors + pattern: syndicate_macros::pattern!{ + + }, + observer: handler, + }) { + Ok(Some(Box::new(move |_ds, t| Ok(t.retract(oh))))) + } else { + Ok(None) + } +} + +struct ResponderDetails { + initiator_session: Arc, + service: Arc, +} + +struct ResponderTransport { + relay_input: Arc>>, + c_recv: CipherState +} + +enum ResponderState { + Handshake(ResponderDetails, noise_protocol::HandshakeState), + Transport(ResponderTransport), +} + +impl Entity for ResponderState { + fn message(&mut self, t: &mut Activation, p: noise::Packet) -> ActorResult { + match self { + ResponderState::Handshake(details, hs) => match p { + noise::Packet::Complete(bs) => { + if bs.len() < hs.get_next_message_overhead() { + Err("Invalid handshake message for pattern")?; + } + if bs.len() > hs.get_next_message_overhead() { + Err("Cannot accept payload during handshake")?; + } + hs.read_message(&bs, &mut [])?; + let mut reply = vec![0u8; hs.get_next_message_overhead()]; + hs.write_message(&[], &mut reply[..])?; + details.initiator_session.message(t, language(), &noise::Packet::Complete(reply.into())); + if hs.completed() { + let (c_recv, mut c_send) = hs.get_ciphers(); + let (_, relay_input, mut relay_output) = + TunnelRelay::_run(t, Some(Arc::clone(&details.service)), None, false); + let trace_collector = t.trace_collector(); + let transport = ResponderTransport { relay_input, c_recv }; + let initiator_session = Arc::clone(&details.initiator_session); + let relay_output_name = Some(AnyValue::symbol("relay_output")); + let transport_facet = t.facet.clone(); + t.linked_task(relay_output_name.clone(), async move { + let account = Account::new(relay_output_name, trace_collector); + let cause = TurnCause::external("relay_output"); + loop { + match relay_output.recv().await { + None => return Ok(LinkedTaskTermination::KeepFacet), + Some(loaned_item) => { + const MAXSIZE: usize = 65535 - 16; /* Noise tag length is 16 */ + let p = if loaned_item.item.len() > MAXSIZE { + noise::Packet::Fragmented( + loaned_item.item + .chunks(MAXSIZE) + .map(|c| c_send.encrypt_vec(c)) + .collect()) + } else { + noise::Packet::Complete(c_send.encrypt_vec(&loaned_item.item)) + }; + if !transport_facet.activate(&account, Some(cause.clone()), |t| { + initiator_session.message(t, language(), &p); + Ok(()) + }) { + break; + } + } + } + } + Ok(LinkedTaskTermination::Normal) + }); + *self = ResponderState::Transport(transport); + } + } + _ => Err("Fragmented handshake is not allowed")?, + }, + ResponderState::Transport(transport) => { + let bs = match p { + noise::Packet::Complete(bs) => + transport.c_recv.decrypt_vec(&bs[..]).map_err(|_| "Cannot decrypt packet")?, + noise::Packet::Fragmented(pieces) => { + let mut result = Vec::with_capacity(1024); + for piece in pieces { + result.extend(transport.c_recv.decrypt_vec(&piece[..]) + .map_err(|_| "Cannot decrypt packet fragment")?); + } + result + } + }; + let mut g = transport.relay_input.lock(); + let tr = g.as_mut().expect("initialized"); + tr.handle_inbound_datagram(t, &bs[..])?; + } + } + Ok(()) + } +} + +fn lookup_pattern(name: &str) -> Option { + use noise_protocol::patterns::*; + Some(match name { + "N" => noise_n(), + "K" => noise_k(), + "X" => noise_x(), + "NN" => noise_nn(), + "NK" => noise_nk(), + "NX" => noise_nx(), + "XN" => noise_xn(), + "XK" => noise_xk(), + "XX" => noise_xx(), + "KN" => noise_kn(), + "KK" => noise_kk(), + "KX" => noise_kx(), + "IN" => noise_in(), + "IK" => noise_ik(), + "IX" => noise_ix(), + "Npsk0" => noise_n_psk0(), + "Kpsk0" => noise_k_psk0(), + "Xpsk1" => noise_x_psk1(), + "NNpsk0" => noise_nn_psk0(), + "NNpsk2" => noise_nn_psk2(), + "NKpsk0" => noise_nk_psk0(), + "NKpsk2" => noise_nk_psk2(), + "NXpsk2" => noise_nx_psk2(), + "XNpsk3" => noise_xn_psk3(), + "XKpsk3" => noise_xk_psk3(), + "XXpsk3" => noise_xx_psk3(), + "KNpsk0" => noise_kn_psk0(), + "KNpsk2" => noise_kn_psk2(), + "KKpsk0" => noise_kk_psk0(), + "KKpsk2" => noise_kk_psk2(), + "KXpsk2" => noise_kx_psk2(), + "INpsk1" => noise_in_psk1(), + "INpsk2" => noise_in_psk2(), + "IKpsk1" => noise_ik_psk1(), + "IKpsk2" => noise_ik_psk2(), + "IXpsk2" => noise_ix_psk2(), + "NNpsk0+psk2" => noise_nn_psk0_psk2(), + "NXpsk0+psk1+psk2" => noise_nx_psk0_psk1_psk2(), + "XNpsk1+psk3" => noise_xn_psk1_psk3(), + "XKpsk0+psk3" => noise_xk_psk0_psk3(), + "KNpsk1+psk2" => noise_kn_psk1_psk2(), + "KKpsk0+psk2" => noise_kk_psk0_psk2(), + "INpsk1+psk2" => noise_in_psk1_psk2(), + "IKpsk0+psk2" => noise_ik_psk0_psk2(), + "IXpsk0+psk2" => noise_ix_psk0_psk2(), + "XXpsk0+psk1" => noise_xx_psk0_psk1(), + "XXpsk0+psk2" => noise_xx_psk0_psk2(), + "XXpsk0+psk3" => noise_xx_psk0_psk3(), + "XXpsk0+psk1+psk2+psk3" => noise_xx_psk0_psk1_psk2_psk3(), + _ => return None, + }) +} + +fn run_noise_responder( + t: &mut Activation, + service_selector: AnyValue, + protocol: String, + psks: Vec>, + secret_key: Option>, + initiator_session: Arc, + service: Arc, +) -> ActorResult { + const PREFIX: &'static str = "Noise_"; + const SUFFIX: &'static str = "_25519_ChaChaPoly_BLAKE2s"; + if !protocol.starts_with(PREFIX) || !protocol.ends_with(SUFFIX) { + Err(format!("Unsupported protocol {:?}", protocol))?; + } + let pattern_name = &protocol[PREFIX.len()..(protocol.len()-SUFFIX.len())]; + let pattern = lookup_pattern(pattern_name).ok_or_else::( + || format!("Unsupported handshake pattern {:?}", pattern_name).into())?; + + let hs = { + let mut builder = noise_protocol::HandshakeStateBuilder::new(); + builder.set_pattern(pattern); + builder.set_is_initiator(false); + let prologue = PackedWriter::encode(&mut NoEmbeddedDomainCodec, &service_selector)?; + builder.set_prologue(&prologue); + match secret_key { + None => (), + Some(sk) => { + let sk: [u8; 32] = sk.try_into().map_err(|_| "Bad secret key length")?; + builder.set_s(U8Array::from_slice(&sk)); + }, + } + let mut hs = builder.build_handshake_state(); + for psk in psks.into_iter() { + hs.push_psk(&psk); + } + hs + }; + + let details = ResponderDetails { + initiator_session: initiator_session.clone(), + service, + }; + + let responder_session = + Cap::guard(crate::Language::arc(), t.create(ResponderState::Handshake(details, hs))); + initiator_session.assert(t, language(), &noise::Accept { responder_session }); + Ok(()) +}