mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
Add key_info() to get key information.
This commit is contained in:
parent
8b6088f335
commit
652f7360f0
2 changed files with 47 additions and 5 deletions
|
@ -14,6 +14,13 @@ struct TestApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl zssp::ApplicationLayer for TestApplication {
|
impl zssp::ApplicationLayer for TestApplication {
|
||||||
|
const REKEY_AFTER_USES: u64 = 131072;
|
||||||
|
const EXPIRE_AFTER_USES: u64 = 2147483648;
|
||||||
|
const REKEY_AFTER_TIME_MS: i64 = 1000 * 60 * 60 * 2;
|
||||||
|
const REKEY_AFTER_TIME_MS_MAX_JITTER: u32 = 1000 * 60 * 10;
|
||||||
|
const INCOMING_SESSION_NEGOTIATION_TIMEOUT_MS: i64 = 2000;
|
||||||
|
const RETRY_INTERVAL: i64 = 500;
|
||||||
|
|
||||||
type Data = ();
|
type Data = ();
|
||||||
|
|
||||||
type IncomingPacketBuffer = Vec<u8>;
|
type IncomingPacketBuffer = Vec<u8>;
|
||||||
|
|
|
@ -133,6 +133,7 @@ struct SessionKey {
|
||||||
created_at_counter: u64, // Counter at which session was created
|
created_at_counter: u64, // Counter at which session was created
|
||||||
rekey_at_counter: u64, // Rekey at or after this counter
|
rekey_at_counter: u64, // Rekey at or after this counter
|
||||||
expire_at_counter: u64, // Hard error when this counter value is reached or exceeded
|
expire_at_counter: u64, // Hard error when this counter value is reached or exceeded
|
||||||
|
ratchet_count: u64, // Number of rekey events
|
||||||
bob: bool, // Was this side "Bob" in this exchange?
|
bob: bool, // Was this side "Bob" in this exchange?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,8 +927,13 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
{
|
{
|
||||||
let mut state = session.state.write().unwrap();
|
let mut state = session.state.write().unwrap();
|
||||||
let _ = state.remote_session_id.insert(bob_session_id);
|
let _ = state.remote_session_id.insert(bob_session_id);
|
||||||
let _ =
|
let _ = state.keys[0].insert(SessionKey::new::<Application>(
|
||||||
state.keys[0].insert(SessionKey::new::<Application>(noise_es_ee_se_hk_psk, current_time, 2, false));
|
noise_es_ee_se_hk_psk,
|
||||||
|
1,
|
||||||
|
current_time,
|
||||||
|
2,
|
||||||
|
false,
|
||||||
|
));
|
||||||
state.current_key = 0;
|
state.current_key = 0;
|
||||||
state.current_offer = Offer::None;
|
state.current_offer = Offer::None;
|
||||||
}
|
}
|
||||||
|
@ -1078,7 +1084,7 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
state: RwLock::new(State {
|
state: RwLock::new(State {
|
||||||
remote_session_id: Some(incoming.alice_session_id),
|
remote_session_id: Some(incoming.alice_session_id),
|
||||||
keys: [
|
keys: [
|
||||||
Some(SessionKey::new::<Application>(noise_es_ee_se_hk_psk, current_time, 2, true)),
|
Some(SessionKey::new::<Application>(noise_es_ee_se_hk_psk, 1, current_time, 2, true)),
|
||||||
None,
|
None,
|
||||||
],
|
],
|
||||||
current_key: 0,
|
current_key: 0,
|
||||||
|
@ -1111,7 +1117,8 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
if let Some(session) = session {
|
if let Some(session) = session {
|
||||||
let state = session.state.read().unwrap();
|
let state = session.state.read().unwrap();
|
||||||
if let Some(key) = state.keys[key_index].as_ref() {
|
if let Some(key) = state.keys[key_index].as_ref() {
|
||||||
// Only the current "Alice" accepts rekeys initiated by the current "Bob."
|
// Only the current "Alice" accepts rekeys initiated by the current "Bob." These roles
|
||||||
|
// flip with each rekey event.
|
||||||
if !key.bob {
|
if !key.bob {
|
||||||
let mut c = key.get_receive_cipher();
|
let mut c = key.get_receive_cipher();
|
||||||
c.reset_init_gcm(&incoming_message_nonce);
|
c.reset_init_gcm(&incoming_message_nonce);
|
||||||
|
@ -1142,10 +1149,16 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
|
|
||||||
send(Some(&session), &mut reply_buf);
|
send(Some(&session), &mut reply_buf);
|
||||||
|
|
||||||
|
// The new "Bob" doesn't know yet if Alice has received the new key, so the
|
||||||
|
// new key is recorded as the "alt" (key_index ^ 1) but the current key is
|
||||||
|
// not advanced yet. This happens automatically the first time we receive a
|
||||||
|
// valid packet with the new key.
|
||||||
|
let next_ratchet_count = key.ratchet_count + 1;
|
||||||
drop(state);
|
drop(state);
|
||||||
let mut state = session.state.write().unwrap();
|
let mut state = session.state.write().unwrap();
|
||||||
let _ = state.keys[key_index ^ 1].replace(SessionKey::new::<Application>(
|
let _ = state.keys[key_index ^ 1].replace(SessionKey::new::<Application>(
|
||||||
next_session_key,
|
next_session_key,
|
||||||
|
next_ratchet_count,
|
||||||
current_time,
|
current_time,
|
||||||
counter.get(),
|
counter.get(),
|
||||||
false,
|
false,
|
||||||
|
@ -1192,11 +1205,16 @@ impl<Application: ApplicationLayer> Context<Application> {
|
||||||
));
|
));
|
||||||
|
|
||||||
if secure_eq(&pkt.next_key_fingerprint, &SHA384::hash(next_session_key.as_bytes())) {
|
if secure_eq(&pkt.next_key_fingerprint, &SHA384::hash(next_session_key.as_bytes())) {
|
||||||
|
// The new "Alice" knows Bob has the key since this is an ACK, so she can go
|
||||||
|
// ahead and set current_key to the new key. Then when she sends something
|
||||||
|
// to Bob the other side will automatically advance to the new key as well.
|
||||||
|
let next_ratchet_count = key.ratchet_count + 1;
|
||||||
drop(state);
|
drop(state);
|
||||||
let next_key_index = key_index ^ 1;
|
let next_key_index = key_index ^ 1;
|
||||||
let mut state = session.state.write().unwrap();
|
let mut state = session.state.write().unwrap();
|
||||||
let _ = state.keys[next_key_index].replace(SessionKey::new::<Application>(
|
let _ = state.keys[next_key_index].replace(SessionKey::new::<Application>(
|
||||||
next_session_key,
|
next_session_key,
|
||||||
|
next_ratchet_count,
|
||||||
current_time,
|
current_time,
|
||||||
session.send_counter.load(Ordering::Acquire),
|
session.send_counter.load(Ordering::Acquire),
|
||||||
true,
|
true,
|
||||||
|
@ -1297,6 +1315,16 @@ impl<Application: ApplicationLayer> Session<Application> {
|
||||||
state.keys[state.current_key].is_some()
|
state.keys[state.current_key].is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the ratchet count and a hash fingerprint of the current active key.
|
||||||
|
pub fn key_info(&self) -> Option<(u64, [u8; 48])> {
|
||||||
|
let state = self.state.read().unwrap();
|
||||||
|
if let Some(key) = state.keys[state.current_key].as_ref() {
|
||||||
|
Some((key.ratchet_count, SHA384::hash(key.ratchet_key.as_bytes())))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Send a rekey init message.
|
/// Send a rekey init message.
|
||||||
///
|
///
|
||||||
/// This is called from the session context's service() method when it's time to rekey.
|
/// This is called from the session context's service() method when it's time to rekey.
|
||||||
|
@ -1473,7 +1501,13 @@ fn assemble_fragments_into<A: ApplicationLayer>(fragments: &[A::IncomingPacketBu
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionKey {
|
impl SessionKey {
|
||||||
fn new<Application: ApplicationLayer>(key: Secret<BASE_KEY_SIZE>, current_time: i64, current_counter: u64, role_is_bob: bool) -> Self {
|
fn new<Application: ApplicationLayer>(
|
||||||
|
key: Secret<BASE_KEY_SIZE>,
|
||||||
|
ratchet_count: u64,
|
||||||
|
current_time: i64,
|
||||||
|
current_counter: u64,
|
||||||
|
role_is_bob: bool,
|
||||||
|
) -> Self {
|
||||||
let a2b = kbkdf::<AES_256_KEY_SIZE, KBKDF_KEY_USAGE_LABEL_AES_GCM_ALICE_TO_BOB>(key.as_bytes());
|
let a2b = kbkdf::<AES_256_KEY_SIZE, KBKDF_KEY_USAGE_LABEL_AES_GCM_ALICE_TO_BOB>(key.as_bytes());
|
||||||
let b2a = kbkdf::<AES_256_KEY_SIZE, KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE>(key.as_bytes());
|
let b2a = kbkdf::<AES_256_KEY_SIZE, KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE>(key.as_bytes());
|
||||||
let (receive_key, send_key) = if role_is_bob {
|
let (receive_key, send_key) = if role_is_bob {
|
||||||
|
@ -1496,6 +1530,7 @@ impl SessionKey {
|
||||||
created_at_counter: current_counter,
|
created_at_counter: current_counter,
|
||||||
rekey_at_counter: current_counter.checked_add(Application::REKEY_AFTER_USES).unwrap(),
|
rekey_at_counter: current_counter.checked_add(Application::REKEY_AFTER_USES).unwrap(),
|
||||||
expire_at_counter: current_counter.checked_add(Application::EXPIRE_AFTER_USES).unwrap(),
|
expire_at_counter: current_counter.checked_add(Application::EXPIRE_AFTER_USES).unwrap(),
|
||||||
|
ratchet_count,
|
||||||
bob: role_is_bob,
|
bob: role_is_bob,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue