disco_rs/channel.rs
1/*
2 Copyright David Huseby, All Rights Reserved.
3 SPDX-License-Identifier: Apache-2.0
4*/
5use crate::{
6 error::ProtocolError,
7 nonce::NonceGenerator,
8 tag::{Tag, TaggedData},
9 transport::{Transport, TransportOrder, TransportState},
10 Result,
11};
12use core::marker::PhantomData;
13use serde::{Deserialize, Serialize};
14use strobe_rs::Strobe;
15
16use std::println as debug;
17
18/// The fixed size of MAC values in the protocol
19const MSG_MAC_LEN: usize = 16;
20
21/// Specifies if the channel is full duplex, or if it is a half-duplex channel for either inbound
22/// or outbout
23#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
24pub enum ChannelDuplex {
25 /// Inbound half-duplex channel
26 InboundHalf,
27 /// Outbound half-duplex channel
28 OutboundHalf,
29 /// In/Out full duplex channel
30 Full,
31}
32
33/// Specifies if the channel is for an initiator or a responder. This is really only useful for
34/// handshaking channel state machines
35#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
36pub enum ChannelRole {
37 /// Session initiator
38 Initiator,
39 /// Session responder
40 Responder,
41}
42
43/// Channels have an internal channel state that handles stateful message exchanges such as
44/// handshakes and encrypted transports
45pub trait ChannelState: Iterator + Clone {
46 /// get the channel role
47 fn role(&self) -> &ChannelRole;
48 /// get the channel duplex
49 fn duplex(&self) -> &ChannelDuplex;
50 /// reset the channel state
51 fn reset(&mut self) -> Result<()>;
52}
53
54/// Channel manages all the channel states and nonces and sending/receiving messages
55#[derive(Clone, Serialize, Deserialize)]
56pub struct Channel<T, CS, N, NG>
57where
58 T: Tag,
59 CS: ChannelState,
60 N: TaggedData<T>,
61 NG: NonceGenerator<T, N>,
62{
63 current_strobe: Strobe,
64 previous_strobe: Strobe,
65 msg_strobe: Option<Strobe>,
66 state: CS,
67 nonce_generator: NG,
68 msg_order: TransportOrder,
69 is_keyed: bool,
70 _t: PhantomData<T>,
71 _n: PhantomData<N>,
72}
73
74/// Make it easy walk through the steps of the state machine
75impl<T, CS, N, NG> Iterator for Channel<T, CS, N, NG>
76where
77 T: Tag,
78 CS: ChannelState,
79 N: TaggedData<T>,
80 NG: NonceGenerator<T, N>,
81{
82 type Item = CS::Item;
83 fn next(&mut self) -> Option<Self::Item> {
84 self.state.next()
85 }
86}
87
88impl<T, CS, N, NG> Channel<T, CS, N, NG>
89where
90 T: Tag,
91 CS: ChannelState,
92 N: TaggedData<T>,
93 NG: NonceGenerator<T, N>,
94{
95 /// Create a new Channel from the strobe, channel state and transport order
96 pub fn new(
97 strobe: &Strobe,
98 state: &CS,
99 nonce_generator: &NG,
100 msg_order: TransportOrder,
101 is_keyed: bool,
102 ) -> Self {
103 Self {
104 current_strobe: strobe.clone(),
105 previous_strobe: strobe.clone(),
106 msg_strobe: None,
107 state: state.clone(),
108 nonce_generator: nonce_generator.clone(),
109 msg_order,
110 is_keyed,
111 _t: PhantomData,
112 _n: PhantomData,
113 }
114 }
115
116 /// Start a new message
117 pub fn start(&mut self) {
118 // at the start of each message we clone the current strobe state, preserving the current
119 // state so we can support both in-order and out-of-order message delivery
120 self.msg_strobe = Some(self.current_strobe.clone());
121 }
122
123 /// Stop a new message
124 pub fn stop(&mut self) {
125 match self.msg_order {
126 TransportOrder::InOrder => {
127 // when we are delivering messages in-order, the message state must be moved back
128 // to the current state so that the next message is based on the accumulated state
129 self.current_strobe = self.msg_strobe.take().unwrap();
130 }
131 TransportOrder::OutOfOrder => {
132 // when we are delivering messages out-of-order, we throw away the message state
133 self.msg_strobe = None;
134 }
135 }
136 }
137
138 /// Returns whether this channel has had a KEY operation done on it
139 pub fn is_keyed(&self) -> bool {
140 self.is_keyed
141 }
142
143 /// Return the channel role
144 pub fn role(&self) -> &ChannelRole {
145 self.state.role()
146 }
147
148 /// Return the channel duplex mode
149 pub fn duplex(&self) -> &ChannelDuplex {
150 self.state.duplex()
151 }
152
153 /// Return the channel ordering
154 pub fn ordering(&self) -> TransportOrder {
155 self.msg_order
156 }
157
158 /// Return the next nonce
159 pub fn nonce(&mut self) -> N {
160 self.nonce_generator.generate()
161 }
162
163 /// Check the nonce to see if it is valid
164 pub fn check_nonce(&mut self, nonce: &N) -> bool {
165 self.nonce_generator.check(nonce)
166 }
167
168 /// Return a default nonce for receiving
169 pub fn default_nonce(&mut self) -> N {
170 self.nonce_generator.default_nonce()
171 }
172
173 /// Do a prf function on the strobe state to get pseudo-random data derived from all data mixed
174 /// into the strobe state until now.
175 pub fn prf(&mut self, data: &mut [u8]) {
176 if let Some(s) = self.msg_strobe.as_mut() {
177 (*s).prf(data, false);
178 debug!("PRF({:02x?})", data);
179 }
180 }
181
182 /// this uses the KEY operation to rekey with the data bytes
183 pub fn key(&mut self, data: &[u8]) {
184 // update the strobe state with the data bytes
185 if data.len() > 0 {
186 if let Some(s) = self.msg_strobe.as_mut() {
187 // mix in the key data
188 (*s).key(data, false);
189 // mark the channel as keyed
190 self.is_keyed = true;
191 debug!("MIX KEY({:02x?})", data);
192 }
193 }
194 }
195
196 /// Split this full-duplex channel into two half-duplex channels so that sending and receiving
197 /// does not have to proceed in an alternating fashion. This is the split() operation detailed
198 /// in the Disco Noise Extension specification (https://discocrypto.com/disco.html).
199 pub fn split(
200 &mut self,
201 handshake_hash: &[u8; 32],
202 ) -> (
203 Channel<T, TransportState, N, NG>,
204 Channel<T, TransportState, N, NG>,
205 ) {
206 // This function follows the steps in §5 and §7.3.1 of the Disco extension spec
207 // (https://www.discocrypto.com/disco.html) to support both regular and out-of-order
208 // message delivery
209
210 // Both message delivery modes follow the steps in §5
211
212 // 0. store the current state before proceeding
213 self.current_strobe = self.msg_strobe.take().unwrap();
214
215 // 1. clone the strobe state into one for outbound and one for inbound
216 let mut s_out = self.current_strobe.clone();
217 let mut s_in = self.current_strobe.clone();
218
219 // 2. for the initiator, call meta_AD("initiator") on outbount and meta_AD("responder") on
220 // the inbound. for the responder, call meta_AD("responder") on outbound and
221 // meta_AD("initiator") on inbound.
222 match self.state.role() {
223 ChannelRole::Initiator => {
224 // initiator's outbound state is tagged as "initiator" and
225 // inbound state is tagged as "responder"
226 s_out.meta_ad(b"initiator", false);
227 s_in.meta_ad(b"responder", false);
228 }
229 ChannelRole::Responder => {
230 // responder's output state is tagged as "responder" and
231 // inbound state is tagged as "initiator"
232 s_out.meta_ad(b"responder", false);
233 s_in.meta_ad(b"initiator", false);
234 }
235 }
236
237 // 3. call RATCHET(16) on both inbound and outbount for both initiator and responder
238 s_out.ratchet(16, false);
239 s_in.ratchet(16, false);
240
241 // 4. create the correct transport state objects based on the message delivery mode
242 //
243 // Out-of-order delivery follows the steps in §7.3.1
244 if self.msg_order == TransportOrder::OutOfOrder {
245 // 4.1 call meta_RATCHET(0) on both inbound and outbound
246 s_out.meta_ratchet(0, false);
247 s_in.meta_ratchet(0, false);
248 }
249
250 // create transport states for inbound and outbound
251 let t_out = TransportState::new(
252 Transport {},
253 self.state.role(),
254 &ChannelDuplex::OutboundHalf,
255 );
256 let t_in =
257 TransportState::new(Transport {}, self.state.role(), &ChannelDuplex::InboundHalf);
258
259 // reset the nonce generator to the handshake hash
260 self.nonce_generator.reset(handshake_hash);
261
262 // create and return two new Channels with the new ChannelState, strobe, role, duplex, and
263 // ordering
264 (
265 // outbound half-duplex
266 Channel::<T, TransportState, N, NG>::new(
267 &s_out,
268 &t_out,
269 &self.nonce_generator,
270 self.msg_order,
271 self.is_keyed,
272 ),
273 // inbound half-duplex
274 Channel::<T, TransportState, N, NG>::new(
275 &s_in,
276 &t_in,
277 &self.nonce_generator,
278 self.msg_order,
279 self.is_keyed,
280 ),
281 )
282 }
283
284 /// Write a tag and associated data to the message. The boolean 'force_clear' forces the data
285 /// to be written as cleartext even if the channel is keyed. The boolen 'meta_tag' prevents any
286 /// tag data from being sent and instead it is just mixed into the strobe state using
287 /// meta_AD/AD operations. This is only useful when the data being sent is a known fixed type
288 /// and known fixed length because the recipient must manually create a tag with the correct
289 /// type and length information to pass into the recv function when receiving the data.
290 pub fn send(
291 &mut self,
292 send_tag: bool,
293 send_data: bool,
294 send_clear: bool,
295 tag: &T,
296 data: &[u8],
297 msg: &mut [u8],
298 ) -> Result<usize> {
299 // make sure we're not sending a tag without any data
300 if send_tag && !send_data {
301 return Err(ProtocolError::InvalidSend.into());
302 }
303
304 // get the number of bytes the tag will write
305 let tlen = if send_tag {
306 tag.as_ref().len() + MSG_MAC_LEN
307 } else {
308 0 // meta tag means we're not actually sending the tag
309 };
310
311 // get the number of bytes the data will write
312 let dlen = if send_data {
313 tag.get_data_length()
314 + if self.is_keyed && !send_clear {
315 MSG_MAC_LEN
316 } else {
317 0
318 }
319 } else {
320 0
321 };
322
323 // make sure we're not writing beyond the end of the output buffer
324 if tlen + dlen > msg.len() {
325 return Err(ProtocolError::InvalidBufferLen.into());
326 }
327
328 // make sure the data length in the tag matches the number of data bytes
329 if tag.get_data_length() != data.len() {
330 return Err(ProtocolError::InvalidBufferLen.into());
331 }
332
333 // output the tag and mac
334 let tag_len = self.send_tag(send_tag, send_clear, tag, msg)?;
335
336 // output the data and mac
337 let data_len = self.send_data(
338 send_data,
339 send_clear,
340 &data[..tag.get_data_length()],
341 &mut msg[tag_len..],
342 )?;
343
344 // return the number of bytes sent
345 Ok(tag_len + data_len)
346 }
347
348 /// Read a tag and associated data from the message. The boolean 'force_clear' forces the data
349 /// to be read as cleartext even if the channel is keyed.
350 pub fn recv(
351 &mut self,
352 recv_tag: bool,
353 recv_data: bool,
354 recv_clear: bool,
355 msg: &[u8],
356 tag: &mut T,
357 data: &mut [u8],
358 ) -> Result<usize> {
359 // make sure we're not receiving a tag and no data
360 if recv_tag && !recv_data {
361 return Err(ProtocolError::InvalidRecv.into());
362 }
363
364 // if the tag data was sent, reset the tag before reading the tag
365 if recv_tag {
366 *tag = T::default();
367 }
368
369 // recv the tag
370 let actual_tag_len = self.recv_tag(recv_tag, recv_clear, msg, tag)?;
371
372 // make sure we didn't read any bytes if we aren't supposed to receive a tag
373 if !recv_tag && actual_tag_len != 0 {
374 return Err(ProtocolError::InvalidTag.into());
375 }
376
377 // calculate the expected data length
378 let expected_data_len = if recv_data {
379 tag.get_data_length()
380 + if self.is_keyed && !recv_clear {
381 MSG_MAC_LEN
382 } else {
383 0
384 }
385 } else {
386 actual_tag_len + 0
387 };
388
389 // make sure we're not going to read past the end of the message buffer
390 if expected_data_len > msg.len() {
391 return Err(ProtocolError::InvalidBufferLen.into());
392 }
393
394 // recv the data
395 let actual_data_len = self.recv_data(
396 recv_data,
397 recv_clear,
398 &msg[actual_tag_len..],
399 &mut data[..tag.get_data_length()],
400 )?;
401
402 if actual_data_len != expected_data_len {
403 return Err(ProtocolError::InvalidData.into());
404 }
405
406 // return just the number of bytes we read from the msg buffer
407 Ok(actual_tag_len + actual_data_len)
408 }
409
410 ///////////////// PRIVATE HELPERS
411
412 // write a MAC to the message, if framing is true, then we use the meta operation
413 fn send_mac(&mut self, framing: bool, msg: &mut [u8]) -> Result<usize> {
414 // make sure we're not going to write beyond the end of the buffer
415 if MSG_MAC_LEN > msg.len() {
416 return Err(ProtocolError::InvalidBufferLen.into());
417 }
418
419 if let Some(s) = self.msg_strobe.as_mut() {
420 // do a meta_AD of the MAC length in network byte order
421 (*s).meta_ad(&MSG_MAC_LEN.to_be_bytes(), false);
422 debug!("META_AD({:02x?})", &MSG_MAC_LEN.to_be_bytes());
423
424 // now add the MAC payload using the meta operation if it is for framing data
425 if framing {
426 (*s).meta_send_mac(&mut msg[..MSG_MAC_LEN], false);
427 debug!("META_SEND_MAC({:02x?})", &msg[..MSG_MAC_LEN]);
428 } else {
429 (*s).send_mac(&mut msg[..MSG_MAC_LEN], false);
430 debug!("SEND_MAC({:02x?})", &msg[..MSG_MAC_LEN]);
431 }
432
433 // return the number of bytes sent
434 Ok(MSG_MAC_LEN)
435 } else {
436 Err(ProtocolError::InvalidState.into())
437 }
438 }
439
440 // write a Tag to the message
441 fn send_tag(
442 &mut self,
443 send_tag: bool,
444 send_clear: bool,
445 tag: &T,
446 msg: &mut [u8],
447 ) -> Result<usize> {
448 // get the length of tag data to be written
449 let expected_len = if send_tag {
450 tag.as_ref().len()
451 + if self.is_keyed && !send_clear {
452 MSG_MAC_LEN
453 } else {
454 0
455 }
456 } else {
457 0
458 };
459
460 // make sure we're not going to write beyond the end of the output buffer
461 if expected_len > msg.len() {
462 return Err(ProtocolError::InvalidBufferLen.into());
463 }
464
465 if let Some(s) = self.msg_strobe.as_mut() {
466 let actual_len = if send_tag {
467 // get the length of the tag bytes
468 let mut tag_len = tag.as_ref().len();
469
470 // copy the tag bytes to the message
471 msg[..tag_len].copy_from_slice(tag.as_ref());
472
473 // if keyed then meta_send_enc otherwise meta_send_clr
474 tag_len += if self.is_keyed && !send_clear {
475 // send the tag bytes encrypted
476 debug!("META_SEND_ENC:\n\tPT: {:02x?}", &msg[..tag_len]);
477 (*s).meta_send_enc(&mut msg[..tag_len], false);
478 debug!("\tCT: {:02x?})", &msg[..tag_len]);
479
480 // write a framing data MAC to the message
481 self.send_mac(true, &mut msg[tag_len..])?
482 } else {
483 // mix the tag bytes into the strobe state
484 debug!("META_AD({:02x?})", &msg[..tag_len]);
485 (*s).meta_ad(&msg[..tag_len], false);
486
487 // send the tag bytes in the clear
488 debug!("META_SEND_CLR({:02x?})", &msg[..tag_len]);
489 (*s).meta_send_clr(&msg[..tag_len], false);
490
491 // no extra bytes other than the tag itself
492 0
493 };
494
495 // return the number of bytes written
496 tag_len
497 } else {
498 // we're not sending the tag, just mixing it into the strobe state
499 (*s).meta_ad(tag.as_ref(), false);
500 debug!("META_AD({:02x?})", tag.as_ref());
501
502 // no bytes written
503 0
504 };
505
506 // make sure we wrote what we expected
507 if expected_len != actual_len {
508 return Err(ProtocolError::InvalidTag.into());
509 }
510
511 Ok(actual_len)
512 } else {
513 Err(ProtocolError::InvalidState.into())
514 }
515 }
516
517 // write the data to the message
518 fn send_data(
519 &mut self,
520 send_data: bool,
521 send_clear: bool,
522 data: &[u8],
523 msg: &mut [u8],
524 ) -> Result<usize> {
525 // get the length of the data
526 let expected_len = if send_data {
527 data.len()
528 + if self.is_keyed && !send_clear {
529 MSG_MAC_LEN
530 } else {
531 0
532 }
533 } else {
534 0
535 };
536
537 // make sure we're not going to write beyond the end of the buffer
538 if expected_len > msg.len() {
539 return Err(ProtocolError::InvalidBufferLen.into());
540 }
541
542 if let Some(s) = self.msg_strobe.as_mut() {
543 let actual_len = if send_data {
544 let mut data_len = data.len();
545
546 // copy the data to the message
547 msg[..data_len].copy_from_slice(data);
548
549 // make this a composite operation by first doing a meta_AD of the data length in
550 // network byte order
551 (*s).meta_ad(&data_len.to_be_bytes(), false);
552 debug!("META_AD({:02x?})", &data_len.to_be_bytes());
553
554 // if we're keyed, then we encrypt the message, otherwise send it in the clear
555 data_len += if self.is_keyed && !send_clear {
556 // send the data encrypted
557 debug!("SEND_ENC:\n\tPT: {:02x?}", &msg[..data_len]);
558 (*s).send_enc(&mut msg[..data_len], false);
559 debug!("\tCT: {:02x?}", &msg[..data_len]);
560
561 // write the payload data MAC to the message
562 self.send_mac(false, &mut msg[data_len..])?
563 } else {
564 // mix the data bytes into the strobe state
565 debug!("AD({:02x?})", &msg[..data_len]);
566 (*s).ad(&msg[..data_len], false);
567
568 // send the data in the clear
569 debug!("SEND_CLR({:02x?})", &msg[..data_len]);
570 (*s).send_clr(&msg[..data_len], false);
571
572 // no extra bytes other than the data that was written
573 0
574 };
575
576 // return the number of bytes sent
577 data_len
578 } else {
579 // we're not actually sending the data, just going to mix it into the strobe state
580 debug!("AD({:02x?})", data);
581 (*s).ad(data, false);
582
583 // didn't write any bytes
584 0
585 };
586
587 // make sure we wrote what we expected
588 if expected_len != actual_len {
589 return Err(ProtocolError::InvalidTag.into());
590 }
591
592 Ok(actual_len)
593 } else {
594 Err(ProtocolError::InvalidState.into())
595 }
596 }
597
598 // read a MAC to the message, if framing is true, then we use the meta operation
599 fn recv_mac(&mut self, framing: bool, msg: &[u8]) -> Result<usize> {
600 // make sure we're not going to read beyond the end of the buffer
601 if MSG_MAC_LEN > msg.len() {
602 return Err(ProtocolError::InvalidBufferLen.into());
603 }
604
605 // copy the mac locally
606 let mut mac = [0u8; MSG_MAC_LEN];
607 mac.copy_from_slice(&msg[..MSG_MAC_LEN]);
608
609 if let Some(s) = self.msg_strobe.as_mut() {
610 // do a meta_AD of the MAC length in network byte order
611 (*s).meta_ad(&MSG_MAC_LEN.to_be_bytes(), false);
612 debug!("META_AD({:02x?})", &MSG_MAC_LEN.to_be_bytes());
613
614 // now check the MAC payload using the meta operation if it is for framing data
615 if framing {
616 debug!("META_RECV_MAC({:02x?})", &mac);
617 (*s).meta_recv_mac(&mut mac)
618 .map_err(|_| ProtocolError::InvalidMac)?;
619 } else {
620 debug!("RECV_MAC({:02x?})", &mac);
621 (*s).recv_mac(&mut mac)
622 .map_err(|_| ProtocolError::InvalidMac)?;
623 }
624
625 // return the number of bytes received
626 Ok(MSG_MAC_LEN)
627 } else {
628 Err(ProtocolError::InvalidState.into())
629 }
630 }
631
632 // read a tag from the message, this assumes the tag is in the default state
633 fn recv_tag(
634 &mut self,
635 recv_tag: bool,
636 recv_clear: bool,
637 msg: &[u8],
638 tag: &mut T,
639 ) -> Result<usize> {
640 if let Some(s) = self.msg_strobe.as_mut() {
641 if recv_tag {
642 let mut idx = 0;
643 if self.is_keyed && !recv_clear {
644 // this loop copies one byte at a time to the tag until it parses
645 let tag_len = loop {
646 // the first strobe calls will have more set to false, the remaining calls it will be
647 // true for the streaming interface of strobe-rs
648 let more = idx > 0;
649
650 // make sure we're not going to read beyond the end of the buffer
651 if idx > msg.len() {
652 return Err(ProtocolError::InvalidBufferLen.into());
653 }
654
655 // make sure that we're not going to write beyond the end of the tag buffer
656 if idx >= tag.as_mut().len() {
657 return Err(ProtocolError::InvalidBufferLen.into());
658 }
659
660 // copy the next byte over to the tag buffer
661 tag.as_mut()[idx] = msg[idx];
662
663 // recv and decrypt the next byte
664 (*s).meta_recv_enc(&mut tag.as_mut()[idx..idx + 1], more);
665
666 // increment the index
667 idx += 1;
668
669 // check to see if we've read enough bytes to get a valid tag
670 if tag.try_parse(idx) {
671 break idx;
672 }
673 };
674
675 debug!("META_RECV_ENC:\n\tCT: {:02x?}", &msg[..tag_len]);
676 debug!("\tPT: {:02x?}", &tag.as_ref());
677
678 // read and check the framing MAC
679 let mac_len = self.recv_mac(true, &msg[tag_len..])?;
680
681 // return the number of bytes received
682 Ok(tag_len + mac_len)
683 } else {
684 // this loop copies one byte at a time to the tag until it parses
685 let tag_len = loop {
686 // make sure we're not going to read beyond the end of the buffer
687 if idx > msg.len() {
688 return Err(ProtocolError::InvalidBufferLen.into());
689 }
690
691 // make sure that we're not going to write beyond the end of the tag buffer
692 if idx >= tag.as_mut().len() {
693 return Err(ProtocolError::InvalidBufferLen.into());
694 }
695
696 // copy the next byte over to the tag buffer
697 tag.as_mut()[idx] = msg[idx];
698
699 // increment the index
700 idx += 1;
701
702 // check to see if we've read enough bytes to get a valid tag
703 if tag.try_parse(idx) {
704 break idx;
705 }
706 };
707
708 // mix the tag bytes into the strobe state
709 debug!("META_AD({:02x?})", tag.as_ref());
710 (*s).meta_ad(tag.as_ref(), false);
711
712 // recv the tag bytes in the clear
713 debug!("META_RECV_CLR({:02x?})", tag.as_ref());
714 (*s).meta_recv_clr(tag.as_ref(), false);
715
716 // return the number of bytes received
717 Ok(tag_len)
718 }
719 } else {
720 // no tag data was sent so we're just mixing the provided tag bytes into the strobe
721 // state. the recipient must create a tag with the correct tag type and data length
722 // to avoid corrupting the strobe state.
723 debug!("META_AD({:02x?})", tag.as_ref());
724 (*s).meta_ad(tag.as_ref(), false);
725 Ok(0)
726 }
727 } else {
728 Err(ProtocolError::InvalidState.into())
729 }
730 }
731
732 // read data from the mesasge
733 fn recv_data(
734 &mut self,
735 recv_data: bool,
736 recv_clear: bool,
737 msg: &[u8],
738 data: &mut [u8],
739 ) -> Result<usize> {
740 if let Some(s) = self.msg_strobe.as_mut() {
741 if recv_data {
742 // get the length of data to read
743 let mut data_len = data.len();
744
745 // copy the message data over
746 data[..data_len].copy_from_slice(&msg[..data_len]);
747
748 // make this a composite operation by meta_AD the data length in network byte order
749 (*s).meta_ad(&data_len.to_be_bytes(), false);
750 debug!("META_AD({:02x?})", &data_len.to_be_bytes());
751
752 data_len += if self.is_keyed && !recv_clear {
753 // recv and decrypt the data
754 debug!("RECV_ENC:\n\tCT: {:02x?}", &data[..data_len]);
755 (*s).recv_enc(&mut data[..data_len], false);
756 debug!("\tPT: {:02x?}", &data[..data_len]);
757
758 // read and check the payload MAC
759 self.recv_mac(false, &msg[data_len..])?
760 } else {
761 // mix the data bytes into the strobe state
762 debug!("AD({:02x?})", &data[..data_len]);
763 (*s).ad(&data[..data_len], false);
764
765 // recv the data in the clear
766 debug!("RECV_CLR({:02x?})", &data[..data_len]);
767 (*s).recv_clr(&data[..data_len], false);
768
769 // no extra bytes other than the data that was received
770 0
771 };
772
773 // return the number of bytes received
774 Ok(data_len)
775 } else {
776 // we're not actually receiving any data so we're just mixing the provided data
777 // bytes into the strobe state. the recipient must pass in the correct bytes to
778 // avoid corrupting the strobe state.
779 debug!("AD({:02x?})", data);
780 (*s).ad(data, false);
781
782 // didn't receive any bytes
783 Ok(0)
784 }
785 } else {
786 Err(ProtocolError::InvalidState.into())
787 }
788 }
789}