copernica_packets/
narrow_waist_packet.rs

1use {
2    crate::{
3        hbfi::HBFI,
4        ResponseData, Nonce,
5        PrivateIdentityInterface,
6        PublicIdentityInterface,
7        Signature,
8    },
9    copernica_common::constants::*,
10    core::hash::{Hash},
11    std::{
12        fmt,
13    },
14    anyhow::{anyhow, Result},
15    log::{error},
16};
17#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
18pub enum NarrowWaistPacket {
19    Request {
20        hbfi: HBFI,
21        nonce: Nonce,
22    },
23    Response {
24        hbfi: HBFI,
25        nonce: Nonce,
26        signature: Signature,
27        data: ResponseData,
28    },
29}
30impl NarrowWaistPacket {
31    pub fn request(hbfi: HBFI) -> Result<Self> {
32        let nonce: Nonce = Nonce::new();
33        Ok(NarrowWaistPacket::Request { hbfi, nonce })
34    }
35    pub fn response(response_sid: PrivateIdentityInterface, hbfi: HBFI, data: Vec<u8>) -> Result<Self> {
36        if hbfi.response_pid != response_sid.public_id() {
37            let msg = "The Request's Response Public Identity doesn't match the Public Identity used to sign or encypt the Response";
38            error!("{}", msg);
39            return Err(anyhow!(msg));
40        }
41        let hbfi = hbfi.clone();
42        let nonce: Nonce = Nonce::new();
43        let data = ResponseData::insert(response_sid.clone(), hbfi.request_pid.clone(), data, nonce.clone())?;
44        let manifest = manifest(&data, &hbfi, &nonce);
45        let response_signkey = response_sid.signing_key();
46        let signature = response_signkey.sign(manifest);
47        Ok(NarrowWaistPacket::Response { hbfi, nonce, data, signature })
48    }
49    pub fn verify(&self) -> Result<bool> {
50        match self {
51            NarrowWaistPacket::Request {..} => {
52                return Ok(true)
53            },
54            NarrowWaistPacket::Response { data, hbfi, signature, nonce} => {
55                let manifest = manifest(&data, &hbfi, &nonce);
56                let verify_key = hbfi.response_pid.verify_key()?;
57                let verified = verify_key.verify(&signature, manifest);
58                return Ok(verified);
59            },
60        }
61    }
62    pub fn data(&self, request_sid: PrivateIdentityInterface) -> Result<Vec<u8>> {
63        match self {
64            NarrowWaistPacket::Request {..} => {
65                let err_msg = "No data in a NarrowWaistPacket::Request";
66                error!("{}", err_msg);
67                return Err(anyhow!(err_msg))
68            },
69            NarrowWaistPacket::Response { data, hbfi, nonce, ..}=> {
70                return Ok(data.extract(request_sid, hbfi.request_pid.clone(), hbfi.response_pid.clone(), nonce.clone())?)
71
72            },
73        }
74    }
75    pub fn as_bytes(&self) -> Vec<u8> {
76        let mut buf: Vec<u8> = vec![];
77        match self {
78            NarrowWaistPacket::Request { hbfi, nonce } => {
79                match hbfi.request_pid {
80                    PublicIdentityInterface::Absent => {
81                        buf.extend_from_slice(&[CLEARTEXT_NARROW_WAIST_PACKET_REQUEST_INDEX]);
82                    },
83                    PublicIdentityInterface::Present { .. } => {
84                        buf.extend_from_slice(&[CYPHERTEXT_NARROW_WAIST_PACKET_REQUEST_INDEX]);
85                    }
86                }
87                buf.extend_from_slice(&nonce.as_bytes());
88                buf.extend_from_slice(&hbfi.as_bytes());
89            },
90            NarrowWaistPacket::Response { hbfi, signature, nonce, data } => {
91                match hbfi.request_pid {
92                    PublicIdentityInterface::Absent => {
93                        buf.extend_from_slice(&[CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_INDEX]);
94                    },
95                    PublicIdentityInterface::Present { .. } => {
96                        buf.extend_from_slice(&[CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_INDEX]);
97                    }
98                }
99                buf.extend_from_slice(signature.as_ref());
100                buf.extend_from_slice(&nonce.as_bytes());
101                buf.extend_from_slice(&hbfi.as_bytes());
102                buf.extend_from_slice(&data.as_bytes());
103            },
104        }
105        buf
106    }
107    pub fn from_bytes(data: &[u8]) -> Result<Self> {
108        let nw_index = data[0];
109        let nw: NarrowWaistPacket = match nw_index {
110            CLEARTEXT_NARROW_WAIST_PACKET_REQUEST_INDEX => {
111                let nonce = Nonce::from_bytes(&data[CLEARTEXT_NARROW_WAIST_PACKET_REQUEST_NONCE_START..CLEARTEXT_NARROW_WAIST_PACKET_REQUEST_NONCE_END]);
112                let hbfi: HBFI = HBFI::from_bytes(&data[CLEARTEXT_NARROW_WAIST_PACKET_REQUEST_HBFI_START..CLEARTEXT_NARROW_WAIST_PACKET_REQUEST_HBFI_END])?;
113                NarrowWaistPacket::Request { hbfi, nonce }
114            },
115            CYPHERTEXT_NARROW_WAIST_PACKET_REQUEST_INDEX => {
116                let nonce = Nonce::from_bytes(&data[CYPHERTEXT_NARROW_WAIST_PACKET_REQUEST_NONCE_START..CYPHERTEXT_NARROW_WAIST_PACKET_REQUEST_NONCE_END]);
117                let hbfi: HBFI = HBFI::from_bytes(&data[CYPHERTEXT_NARROW_WAIST_PACKET_REQUEST_HBFI_START..CYPHERTEXT_NARROW_WAIST_PACKET_REQUEST_HBFI_END])?;
118                NarrowWaistPacket::Request { hbfi, nonce }
119            },
120            CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_INDEX => {
121                let mut signature = [0u8; Signature::SIZE];
122                signature.clone_from_slice(&data[CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_SIG_START..CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_SIG_END]);
123                let signature: Signature = Signature::from(signature);
124                let nonce = Nonce::from_bytes(&data[CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_NONCE_START..CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_NONCE_END]);
125                let hbfi: HBFI = HBFI::from_bytes(&data[CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_HBFI_START..CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_HBFI_END])?;
126                let data: ResponseData = ResponseData::from_bytes(&data[CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_DATA_START..CLEARTEXT_NARROW_WAIST_PACKET_RESPONSE_DATA_END])?;
127                NarrowWaistPacket::Response { hbfi, signature, nonce, data }
128            },
129            CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_INDEX => {
130                let mut signature = [0u8; Signature::SIZE];
131                signature.clone_from_slice(&data[CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_SIG_START..CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_SIG_END]);
132                let signature: Signature = Signature::from(signature);
133                let nonce = Nonce::from_bytes(&data[CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_NONCE_START..CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_NONCE_END]);
134                let hbfi: HBFI = HBFI::from_bytes(&data[CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_HBFI_START..CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_HBFI_END])?;
135                let data: ResponseData = ResponseData::from_bytes(&data[CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_DATA_START..CYPHERTEXT_NARROW_WAIST_PACKET_RESPONSE_DATA_END])?;
136                NarrowWaistPacket::Response { hbfi, signature, nonce, data }
137            },
138            _ => {
139                let msg = format!("Index used in the NarrowWaistPacket is unrecognized");
140                error!("{}", msg);
141                return Err(anyhow!(msg));
142            },
143        };
144        if !nw.verify()? {
145            let err_msg = "NarrowWaistPacket::from_cleartext_bytes signature check failed";
146            error!("{}", err_msg);
147            return Err(anyhow!(err_msg))
148        }
149        Ok(nw)
150    }
151}
152fn manifest(data: &ResponseData, hbfi: &HBFI, nonce: &Nonce) ->  Vec<u8> {
153    [data.as_bytes(), hbfi.as_bytes(), nonce.as_bytes()].concat()
154}
155impl fmt::Debug for NarrowWaistPacket {
156    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157        match &*self {
158            NarrowWaistPacket::Request { hbfi, .. } => write!(f, "NW REQ {:?}", hbfi),
159            NarrowWaistPacket::Response {
160                hbfi,
161                signature,
162                nonce,
163                ..
164            } => write!(f, "NW RES {:?} {} {:?}", hbfi, signature, nonce),
165        }
166    }
167}