aboutsummaryrefslogtreecommitdiffstats
path: root/src/message.rs
blob: 4dd2fa808e3cd0ae45bbbafc8c6a79a75d4cac69 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#![allow(unused)]

use failure::Error;
use std::convert::{TryFrom, TryInto};
use byteorder::{ByteOrder, LittleEndian};

#[derive(Deref)] pub struct Initiation(Vec<u8>);
#[derive(Deref)] pub struct Response(Vec<u8>);
#[derive(Deref)] pub struct CookieReply(Vec<u8>);
#[derive(Deref)] pub struct Transport(Vec<u8>);

pub enum Message {
    Initiation(Initiation),
    Response(Response),
    CookieReply(CookieReply),
    Transport(Transport),
}

impl TryFrom<Vec<u8>> for Message {
    type Error = Error;

    fn try_from(packet: Vec<u8>) -> Result<Self, Self::Error> {
        Ok(match packet[0] {
            1 => Message::Initiation(packet.try_into()?),
            2 => Message::Response(packet.try_into()?),
            3 => Message::CookieReply(packet.try_into()?),
            4 => Message::Transport(packet.try_into()?),
            _ => bail!("unknown wireguard message type")
        })
    }
}

impl Initiation {
    pub fn their_index(&self) -> u32 {
        LittleEndian::read_u32(&self[4..])
    }

    pub fn noise_bytes(&self) -> &[u8] {
        &self[8..116]
    }

    pub fn as_bytes(&self) -> &[u8] {
        self
    }
}

impl TryFrom<Vec<u8>> for Initiation {
    type Error = Error;

    fn try_from(packet: Vec<u8>) -> Result<Self, Self::Error> {
        ensure!(packet.len() == 148, "incorrect handshake initiation packet length.");
        Ok(Initiation(packet))
    }
}

impl Response {
    pub fn their_index(&self) -> u32 {
        LittleEndian::read_u32(&self[4..])
    }

    pub fn our_index(&self) -> u32 {
        LittleEndian::read_u32(&self[8..])
    }

    pub fn noise_bytes(&self) -> &[u8] {
        &self[12..60]
    }

    pub fn mac1(&self) -> &[u8] {
        &self[60..76]
    }

    pub fn mac2(&self) -> &[u8] {
        &self[76..92]
    }

    pub fn as_bytes(&self) -> &[u8] {
        self
    }
}

impl TryFrom<Vec<u8>> for Response {
    type Error = Error;

    fn try_from(packet: Vec<u8>) -> Result<Self, Self::Error> {
        ensure!(packet.len() == 92, "incorrect handshake response packet length.");
        Ok(Response(packet))
    }
}

impl CookieReply {
    pub fn our_index(&self) -> u32 {
        LittleEndian::read_u32(&self[4..])
    }

    pub fn nonce(&self) -> &[u8] {
        &self[8..32]
    }

    pub fn cookie(&self) -> &[u8] {
        &self[32..48]
    }

    pub fn aead_tag(&self) -> &[u8] {
        &self[48..64]
    }

    pub fn as_bytes(&self) -> &[u8] {
        self
    }
}

impl TryFrom<Vec<u8>> for CookieReply {
    type Error = Error;

    fn try_from(packet: Vec<u8>) -> Result<Self, Self::Error> {
        ensure!(packet.len() == 64, "incorrect cookie reply packet length.");
        Ok(CookieReply(packet))
    }
}

impl Transport {
    pub fn our_index(&self) -> u32 {
        LittleEndian::read_u32(&self[4..])
    }

    pub fn nonce(&self) -> u64 {
        LittleEndian::read_u64(&self[8..16])
    }

    pub fn payload(&self) -> &[u8] {
        &self[16..]
    }

    pub fn as_bytes(&self) -> &[u8] {
        self
    }
}

impl TryFrom<Vec<u8>> for Transport {
    type Error = Error;

    fn try_from(packet: Vec<u8>) -> Result<Self, Self::Error> {
        ensure!(packet.len() >= 32, "transport message smaller than minimum length.");
        Ok(Transport(packet))
    }
}