|
@@ -29,12 +29,16 @@ pub struct SymmetricKey {
|
|
nonce: [u8; 16],
|
|
nonce: [u8; 16],
|
|
}
|
|
}
|
|
|
|
|
|
-#[derive(Default)]
|
|
|
|
-pub(crate) struct VerifyPacketSignature {}
|
|
|
|
|
|
+pub(crate) struct VerifyPacketSignature {
|
|
|
|
+ api: std::rc::Rc<crate::API>,
|
|
|
|
+}
|
|
|
|
|
|
-impl DefaultService for VerifyPacketSignature {
|
|
|
|
- fn setup(self: &std::rc::Rc<Self>, api: std::rc::Rc<crate::API>) {
|
|
|
|
- api.channel::<fleck_core::ReceivePacketChannel>().sub_opt(
|
|
|
|
|
|
+impl Service for VerifyPacketSignature {
|
|
|
|
+ fn new(api: std::rc::Rc<crate::API>) -> Self {
|
|
|
|
+ Self { api }
|
|
|
|
+ }
|
|
|
|
+ fn setup(self: &std::rc::Rc<Self>) {
|
|
|
|
+ self.api.channel::<fleck_core::ReceivePacketChannel>().sub_opt(
|
|
fleck_core::ReceiveOrder::Verify,
|
|
fleck_core::ReceiveOrder::Verify,
|
|
self,
|
|
self,
|
|
Self::check,
|
|
Self::check,
|
|
@@ -49,17 +53,19 @@ impl VerifyPacketSignature {
|
|
) -> Option<fleck_core::msg::Message> {
|
|
) -> Option<fleck_core::msg::Message> {
|
|
match message.crypto_header {
|
|
match message.crypto_header {
|
|
PacketHeader::Signed(signature) => {
|
|
PacketHeader::Signed(signature) => {
|
|
|
|
+ // check that we have a pubkey for the node, reject if not
|
|
|
|
+ let pubkey = message.node.as_ref().and_then(|n| Some(n.pubkey()));
|
|
|
|
+ if pubkey.is_none() {
|
|
|
|
+ return None
|
|
|
|
+ }
|
|
|
|
+ let pubkey = pubkey.unwrap();
|
|
|
|
+
|
|
message.crypto_header = PacketHeader::NoCrypto;
|
|
message.crypto_header = PacketHeader::NoCrypto;
|
|
let to_verify = bincode::serialize(&message)
|
|
let to_verify = bincode::serialize(&message)
|
|
.expect("assume that we can re-serialize the message");
|
|
.expect("assume that we can re-serialize the message");
|
|
|
|
|
|
- // signature.verify(to_verify, signature);
|
|
|
|
-
|
|
|
|
- // let pubkey = api.services().with_service(|ns: &fleck_core::Nodes| { ns.self_node().pubkey() });
|
|
|
|
-
|
|
|
|
- // match pubkey {
|
|
|
|
- // msg.crypto_header = PacketHeader::Signed(keypair.sign(&sign_data));
|
|
|
|
- // }
|
|
|
|
|
|
+ use ed25519_dalek::Verifier;
|
|
|
|
+ pubkey.verify(&to_verify, &signature).ok()?;
|
|
}
|
|
}
|
|
_ => {}
|
|
_ => {}
|
|
}
|
|
}
|
|
@@ -97,14 +103,15 @@ impl SignPacket {
|
|
}
|
|
}
|
|
|
|
|
|
self.api.with_service(|ns: &fleck_core::NodeService| {
|
|
self.api.with_service(|ns: &fleck_core::NodeService| {
|
|
- let keypair = ns.self_node().keypair().unwrap();
|
|
|
|
|
|
+ let ns = ns.self_node();
|
|
|
|
+ let keypair = ns.keypair().unwrap();
|
|
let sign_data = bincode::serialize(&message.content).unwrap();
|
|
let sign_data = bincode::serialize(&message.content).unwrap();
|
|
message.crypto_header = PacketHeader::Signed(keypair.sign(&sign_data));
|
|
message.crypto_header = PacketHeader::Signed(keypair.sign(&sign_data));
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-#[derive(serde::Serialize, serde::Deserialize)]
|
|
|
|
|
|
+#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
|
pub struct KeyExchange {
|
|
pub struct KeyExchange {
|
|
key: x25519_dalek::PublicKey,
|
|
key: x25519_dalek::PublicKey,
|
|
}
|
|
}
|
|
@@ -122,6 +129,25 @@ pub enum KeyExchangeState {
|
|
Completed(x25519_dalek::PublicKey, SymmetricKey),
|
|
Completed(x25519_dalek::PublicKey, SymmetricKey),
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+impl std::fmt::Debug for KeyExchangeState {
|
|
|
|
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
+ match self {
|
|
|
|
+ Self::NoState => {
|
|
|
|
+ f.write_str("KeyExchangeState::NoState")
|
|
|
|
+ },
|
|
|
|
+ Self::Given(pkey) => {
|
|
|
|
+ f.write_fmt(format_args!("KeyExchangeState::Given {{ pkey: {:?} }}", pkey))
|
|
|
|
+ },
|
|
|
|
+ Self::WaitForResponse(_) => {
|
|
|
|
+ f.write_str("KeyExchangeState::WaitForResponse { redacted }")
|
|
|
|
+ },
|
|
|
|
+ Self::Completed(pkey, _) => {
|
|
|
|
+ f.write_fmt(format_args!("KeyExchangeState::Completed {{ pkey: {:?}, redacted }}", pkey))
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
pub struct EncryptionService {
|
|
pub struct EncryptionService {
|
|
api: std::rc::Rc<crate::API>,
|
|
api: std::rc::Rc<crate::API>,
|
|
state: RefCell<HashMap<fleck_core::peer::Peer, KeyExchangeState>>,
|
|
state: RefCell<HashMap<fleck_core::peer::Peer, KeyExchangeState>>,
|
|
@@ -133,6 +159,9 @@ impl Service for EncryptionService {
|
|
}
|
|
}
|
|
|
|
|
|
fn setup(self: &std::rc::Rc<Self>) {
|
|
fn setup(self: &std::rc::Rc<Self>) {
|
|
|
|
+ self.api.with_service(|msg: &fleck_core::MessageService| {
|
|
|
|
+ msg.add_message_type::<KeyExchange>();
|
|
|
|
+ });
|
|
self.api.channel::<fleck_core::node::NodeRegistrationChannel>().sub_ref(self, Self::new_node);
|
|
self.api.channel::<fleck_core::node::NodeRegistrationChannel>().sub_ref(self, Self::new_node);
|
|
self.api.channel::<fleck_core::msg::MessageChannel<KeyExchange>>().sub_eat(self, Self::incoming);
|
|
self.api.channel::<fleck_core::msg::MessageChannel<KeyExchange>>().sub_eat(self, Self::incoming);
|
|
}
|
|
}
|
|
@@ -152,19 +181,24 @@ impl EncryptionService {
|
|
let secret = x25519_dalek::EphemeralSecret::new(&mut csprng);
|
|
let secret = x25519_dalek::EphemeralSecret::new(&mut csprng);
|
|
|
|
|
|
// send notification with new secret
|
|
// send notification with new secret
|
|
- self.api.queue::<fleck_core::SendPacketChannel>(fleck_core::msg::Message::build(
|
|
|
|
- KeyExchange {
|
|
|
|
- key: x25519_dalek::PublicKey::from(&secret)
|
|
|
|
- }
|
|
|
|
- ));
|
|
|
|
|
|
+ let send = || {
|
|
|
|
+ log::trace!("sending KeyExchange message");
|
|
|
|
+ self.api.queue::<fleck_core::SendPacketChannel>(fleck_core::msg::Message::build(
|
|
|
|
+ KeyExchange {
|
|
|
|
+ key: x25519_dalek::PublicKey::from(&secret)
|
|
|
|
+ }
|
|
|
|
+ ).with_peer(with.clone()));
|
|
|
|
+ };
|
|
|
|
|
|
let mut states = self.state.borrow_mut();
|
|
let mut states = self.state.borrow_mut();
|
|
let state = states.remove(&with).unwrap_or(KeyExchangeState::NoState);
|
|
let state = states.remove(&with).unwrap_or(KeyExchangeState::NoState);
|
|
match state {
|
|
match state {
|
|
KeyExchangeState::NoState => {
|
|
KeyExchangeState::NoState => {
|
|
|
|
+ send();
|
|
states.insert(with.clone(), KeyExchangeState::WaitForResponse(secret));
|
|
states.insert(with.clone(), KeyExchangeState::WaitForResponse(secret));
|
|
},
|
|
},
|
|
KeyExchangeState::Given(pubkey) => {
|
|
KeyExchangeState::Given(pubkey) => {
|
|
|
|
+ send();
|
|
let result = secret.diffie_hellman(&pubkey);
|
|
let result = secret.diffie_hellman(&pubkey);
|
|
|
|
|
|
let sk = SymmetricKey {
|
|
let sk = SymmetricKey {
|
|
@@ -172,13 +206,16 @@ impl EncryptionService {
|
|
nonce: result.as_bytes()[16..32].try_into().unwrap(),
|
|
nonce: result.as_bytes()[16..32].try_into().unwrap(),
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ log::trace!("Completed key negotiation with peer!");
|
|
states.insert(with.clone(), KeyExchangeState::Completed(pubkey, sk));
|
|
states.insert(with.clone(), KeyExchangeState::Completed(pubkey, sk));
|
|
},
|
|
},
|
|
KeyExchangeState::WaitForResponse(secret) => {
|
|
KeyExchangeState::WaitForResponse(secret) => {
|
|
|
|
+ send();
|
|
states.insert(with.clone(), KeyExchangeState::WaitForResponse(secret));
|
|
states.insert(with.clone(), KeyExchangeState::WaitForResponse(secret));
|
|
},
|
|
},
|
|
KeyExchangeState::Completed(_pubkey, _symmetric_key) => {
|
|
KeyExchangeState::Completed(_pubkey, _symmetric_key) => {
|
|
log::error!("asked to begin handshake when already have a good encryption key?");
|
|
log::error!("asked to begin handshake when already have a good encryption key?");
|
|
|
|
+ return
|
|
},
|
|
},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -186,8 +223,9 @@ impl EncryptionService {
|
|
fn incoming(&self, msg: (fleck_core::msg::Metadata, KeyExchange)) {
|
|
fn incoming(&self, msg: (fleck_core::msg::Metadata, KeyExchange)) {
|
|
let mut states = self.state.borrow_mut();
|
|
let mut states = self.state.borrow_mut();
|
|
let peer = msg.0.peer.expect("incoming KeyExchange should have a peer?");
|
|
let peer = msg.0.peer.expect("incoming KeyExchange should have a peer?");
|
|
- // let state = states.entry(peer.clone()).or_insert(KeyExchangeState::NoState);
|
|
|
|
|
|
+
|
|
let state = states.remove(&peer).unwrap_or(KeyExchangeState::NoState);
|
|
let state = states.remove(&peer).unwrap_or(KeyExchangeState::NoState);
|
|
|
|
+ log::trace!("incoming key exchange message: {:?}, state: {:?}", msg.1, &state);
|
|
match state {
|
|
match state {
|
|
KeyExchangeState::NoState => {
|
|
KeyExchangeState::NoState => {
|
|
states.insert(peer.clone(), KeyExchangeState::Given(msg.1.key));
|
|
states.insert(peer.clone(), KeyExchangeState::Given(msg.1.key));
|
|
@@ -214,6 +252,7 @@ impl EncryptionService {
|
|
};
|
|
};
|
|
|
|
|
|
states.insert(peer.clone(), KeyExchangeState::Completed(msg.1.key, sk));
|
|
states.insert(peer.clone(), KeyExchangeState::Completed(msg.1.key, sk));
|
|
|
|
+ drop(states);
|
|
},
|
|
},
|
|
KeyExchangeState::Completed(peer_pubkey, _symmetric_key) => {
|
|
KeyExchangeState::Completed(peer_pubkey, _symmetric_key) => {
|
|
if peer_pubkey == msg.1.key {
|
|
if peer_pubkey == msg.1.key {
|
|
@@ -226,5 +265,7 @@ impl EncryptionService {
|
|
self.begin_handshake(&peer);
|
|
self.begin_handshake(&peer);
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
+ log::trace!("after processing incoming key exchange message, state: {:?}", self.state.borrow().get(&peer));
|
|
|
|
+
|
|
}
|
|
}
|
|
}
|
|
}
|