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}