aboutsummaryrefslogtreecommitdiffstats
path: root/src/machine.rs
blob: a8d4d07c0202db33503890ca456b3600e822a8f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use x25519_dalek::PublicKey;
use x25519_dalek::StaticSecret;
use x25519_dalek::SharedSecret;

use std::sync::Mutex;
use std::sync::mpsc::channel;
use std::collections::HashMap;

pub struct Peer {
    m   : StateMutable,
    sk  : StaticSecret,
    pk  : PublicKey,
    ss  : SharedSecret,
    psk : [u8; 32]
}

/* Mutable part of handshake state */
enum StateMutable {
    Reset,
    InitiationSent,
    InitiationProcessed,
    ReponseSent
}

/* Immutable part of the handshake state */
struct StateFixed {
}

struct StateMachine {
    peers : Vec<Mutex<Peer>>,          // peer index  -> state
    pkmap : HashMap<[u8; 32], usize>,  // public key  -> peer index
    ids   : Mutex<HashMap<u32, usize>> // receive ids -> peer index
}

struct Key {
    key : [u8; 32],
    id  : u32
}

struct KeyPair {
    confimed : bool, // has the key-pair been confirmed
    send     : Key,  // key for outbound messages
    recv     : Key   // key for inbound messages
}

struct Output (
    Option<KeyPair>, // resulting key-pair of successful handshake
    Option<u32>      // id to be released
);

impl StateMachine {
    /// Initialize a new handshake state machine
    ///
    /// # Arguments
    ///
    /// * `sk` - x25519 scalar representing the local private key
    pub fn new(sk : StaticSecret) -> StateMachine {
        StateMachine {
            peers : vec![],
            pkmap : HashMap::new(),
            ids   : Mutex::new(HashMap::new())
        }
    }

    /// Add a new public key to the state machine
    /// To remove public keys, you must create a new machine instance
    ///
    /// # Arguments
    ///
    /// * `pk` - The public key to add
    ///
    /// # Returns
    ///
    /// The call might fail if the public key corresponds to the secret key of the machine
    pub fn add(&mut self, pk : PublicKey) -> Result<(), ()> {
        // let ss = sk.diffie_hellman(&pk);
        Err(())
    }

    /// Release an id back to the pool
    ///
    /// # Arguments
    ///
    /// * `id` - The (sender) id to release
    pub fn release(&self, id : u32) {
        self.ids.lock().unwrap().remove(&id);
    }

    /// Begin a new handshake
    ///
    /// # Arguments
    ///
    /// * `pk` - Public key of peer to initiate handshake for
    pub fn begin(&self, pk : PublicKey) -> Result<Output, ()> {
        match self.pkmap.get(pk.as_bytes()) {
            None => Err(()),
            Some(&idx) => {
                let mut peer = self.peers.get(idx).unwrap().lock().unwrap();
                Err(())
            }
        }
    }

    /// Process a handshake message.
    ///
    /// # Arguments
    ///
    /// * `msg` - Byte slice containing the message (untrusted input)
    fn process(&self, msg : &[u8]) -> Result<Output, ()> {
        // inspect type field
        match msg.get(0) {
            _ => Err(())
        }
    }
}