1#![cfg_attr(not(feature = "python-bindings"), no_std)]
13
14pub use cbor_decoder::*;
15pub use edhoc_parser::*;
16pub use helpers::*;
17
18use core::num::NonZeroI16;
19use defmt_or_log::trace;
20
21mod crypto;
22pub use crypto::*;
23
24mod cred;
25pub use cred::*;
26
27mod buffer;
28pub use buffer::*;
29
30#[cfg(feature = "python-bindings")]
31use pyo3::prelude::*;
32#[cfg(feature = "python-bindings")]
33mod python_bindings;
34
35pub const MAX_MESSAGE_SIZE_LEN: usize = if cfg!(feature = "max_message_size_len_1024") {
37 1024
38} else if cfg!(feature = "max_message_size_len_512") {
39 512
40} else if cfg!(feature = "max_message_size_len_448") {
41 448
42} else if cfg!(feature = "max_message_size_len_384") {
43 384
44} else if cfg!(feature = "max_message_size_len_320") {
45 320
46} else if cfg!(feature = "max_message_size_len_256") {
47 256
48} else {
49 128 + 64
51};
52
53pub const ID_CRED_LEN: usize = 4;
54pub const SUITES_LEN: usize = 9;
55pub const SUPPORTED_SUITES_LEN: usize = 1;
56pub const EDHOC_METHOD: u8 = 3u8; pub const P256_ELEM_LEN: usize = 32;
58pub const SHA256_DIGEST_LEN: usize = 32;
59pub const AES_CCM_KEY_LEN: usize = 16;
60pub const AES_CCM_IV_LEN: usize = 13;
61pub const AES_CCM_TAG_LEN: usize = 8;
62pub const MAC_LENGTH: usize = 8; pub const MAC_LENGTH_2: usize = MAC_LENGTH;
64pub const MAC_LENGTH_3: usize = MAC_LENGTH_2;
65pub const ENCODED_VOUCHER_LEN: usize = 1 + MAC_LENGTH; pub const MAX_KDF_CONTEXT_LEN: usize = if cfg!(feature = "max_kdf_content_len_1024") {
71 1024
72} else if cfg!(feature = "max_kdf_content_len_512") {
73 512
74} else if cfg!(feature = "max_kdf_content_len_448") {
75 448
76} else if cfg!(feature = "max_kdf_content_len_384") {
77 384
78} else if cfg!(feature = "max_kdf_content_len_320") {
79 320
80} else {
81 256
82};
83pub const MAX_KDF_LABEL_LEN: usize = 15; pub const MAX_BUFFER_LEN: usize = if cfg!(feature = "max_buffer_len_1024") {
87 1024
88} else if cfg!(feature = "max_buffer_len_512") {
89 512
90} else if cfg!(feature = "max_buffer_len_448") {
91 448
92} else if cfg!(feature = "max_buffer_len_384") {
93 384
94} else {
95 256 + 64
96};
97pub const CBOR_BYTE_STRING: u8 = 0x58u8;
98pub const CBOR_TEXT_STRING: u8 = 0x78u8;
99pub const CBOR_UINT_1BYTE: u8 = 0x18u8;
100pub const CBOR_NEG_INT_1BYTE_START: u8 = 0x20u8;
101pub const CBOR_NEG_INT_1BYTE_END: u8 = 0x37u8;
102pub const CBOR_UINT_1BYTE_START: u8 = 0x0u8;
103pub const CBOR_UINT_1BYTE_END: u8 = 0x17u8;
104pub const CBOR_MAJOR_TEXT_STRING: u8 = 0x60u8;
105pub const CBOR_MAJOR_BYTE_STRING: u8 = 0x40u8;
106pub const CBOR_MAJOR_BYTE_STRING_MAX: u8 = 0x57u8;
107pub const CBOR_MAJOR_ARRAY: u8 = 0x80u8;
108pub const CBOR_MAJOR_ARRAY_MAX: u8 = 0x97u8;
109pub const CBOR_MAJOR_MAP: u8 = 0xA0;
110pub const MAX_INFO_LEN: usize = 2 + SHA256_DIGEST_LEN + 1 + MAX_KDF_LABEL_LEN + 1 + MAX_KDF_CONTEXT_LEN + 1; pub const KCCS_LABEL: u8 = 14;
116#[deprecated(note = "Typo for KCCS_LABEL")]
117pub const KCSS_LABEL: u8 = KCCS_LABEL;
118pub const KID_LABEL: u8 = 4;
119
120pub const ENC_STRUCTURE_LEN: usize = 8 + 5 + SHA256_DIGEST_LEN; pub const MAX_EAD_SIZE_LEN: usize = 64;
123
124const MAX_CONNID_ENCODED_LEN: usize = if cfg!(feature = "max_connid_encoded_len_24") {
132 24
133} else {
134 8
135};
136
137pub type BytesSuites = [u8; SUITES_LEN];
138pub type BytesSupportedSuites = [u8; SUPPORTED_SUITES_LEN];
139pub const EDHOC_SUITES: BytesSuites = [0, 1, 2, 3, 4, 5, 6, 24, 25]; pub const EDHOC_SUPPORTED_SUITES: BytesSupportedSuites = [0x2u8];
141
142pub type BytesEad2 = [u8; 0];
143pub type BytesIdCred = [u8; ID_CRED_LEN];
144pub type Bytes8 = [u8; 8];
145pub type BytesCcmKeyLen = [u8; AES_CCM_KEY_LEN];
146pub type BytesCcmIvLen = [u8; AES_CCM_IV_LEN];
147pub type BufferPlaintext2 = EdhocMessageBuffer;
148pub type BufferPlaintext3 = EdhocMessageBuffer;
149pub type BufferPlaintext4 = EdhocMessageBuffer;
150pub type BytesMac2 = [u8; MAC_LENGTH_2];
151pub type BytesMac3 = [u8; MAC_LENGTH_3];
152pub type BufferMessage1 = EdhocMessageBuffer;
153pub type BufferMessage3 = EdhocMessageBuffer;
154pub type BufferMessage4 = EdhocMessageBuffer;
155pub type BufferCiphertext2 = EdhocMessageBuffer;
156pub type BufferCiphertext3 = EdhocMessageBuffer;
157pub type BufferCiphertext4 = EdhocMessageBuffer;
158pub type BytesHashLen = [u8; SHA256_DIGEST_LEN];
159pub type BytesP256ElemLen = [u8; P256_ELEM_LEN];
160pub type BufferMessage2 = EdhocMessageBuffer;
161pub type BytesMaxBuffer = [u8; MAX_BUFFER_LEN];
162pub type BytesMaxContextBuffer = [u8; MAX_KDF_CONTEXT_LEN];
163pub type BytesMaxInfoBuffer = [u8; MAX_INFO_LEN];
164pub type BytesMaxLabelBuffeer = [u8; MAX_KDF_LABEL_LEN];
165pub type BytesEncStructureLen = [u8; ENC_STRUCTURE_LEN];
166
167pub type BytesMac = [u8; MAC_LENGTH];
168pub type BytesEncodedVoucher = [u8; ENCODED_VOUCHER_LEN];
169pub type EADMessageBuffer = EdhocMessageBuffer; #[derive(Debug, PartialEq, Eq, Copy, Clone)]
178#[derive(Default)]
180pub struct ConnId([u8; MAX_CONNID_ENCODED_LEN]);
181
182enum ConnIdType {
184 SingleByte,
186 ByteString(u8),
191}
192
193impl ConnIdType {
194 const _IMPL_CONSTRAINTS: () = assert!(
195 MAX_CONNID_ENCODED_LEN <= 1 + 23,
196 "Longer connection IDs require more elaborate decoding here"
197 );
198
199 fn classify(byte: u8) -> Option<Self> {
203 if byte >> 5 <= 1 && byte & 0x1f < 24 {
204 return Some(ConnIdType::SingleByte);
205 } else if byte >> 5 == 2 && byte & 0x1f < 24 {
206 return Some(ConnIdType::ByteString(byte & 0x1f));
207 }
208 None
209 }
210
211 fn length(&self) -> usize {
213 match self {
214 ConnIdType::SingleByte => 1,
215 ConnIdType::ByteString(n) => (1 + n).into(),
216 }
217 }
218}
219
220impl ConnId {
221 #[deprecated(
227 note = "This API is only capable of generating a limited sub-set of the supported identifiers."
228 )]
229 pub const fn from_int_raw(raw: u8) -> Self {
230 debug_assert!(raw >> 5 <= 1, "Major type is not an integer");
231 debug_assert!(raw & 0x1f < 24, "Value is not immediate");
232 let mut s = [0; MAX_CONNID_ENCODED_LEN];
235 s[0] = raw;
236 Self(s)
237 }
238
239 fn classify(&self) -> ConnIdType {
243 let Some(t) = ConnIdType::classify(self.0[0]) else {
244 unreachable!("Type invariant requires valid classification")
245 };
246 t
247 }
248
249 pub fn from_decoder(decoder: &mut CBORDecoder<'_>) -> Result<Self, CBORError> {
255 let mut s = [0; MAX_CONNID_ENCODED_LEN];
256 let len = ConnIdType::classify(decoder.current()?)
257 .ok_or(CBORError::DecodingError)?
258 .length();
259 s[..len].copy_from_slice(decoder.read_slice(len)?);
260 Ok(Self(s))
261 }
262
263 pub fn as_slice(&self) -> &[u8] {
265 match self.classify() {
266 ConnIdType::SingleByte => &self.0[..1],
267 ConnIdType::ByteString(n) => &self.0[1..1 + usize::from(n)],
268 }
269 }
270
271 pub fn as_cbor(&self) -> &[u8] {
290 &self.0[..self.classify().length()]
291 }
292
293 pub fn from_slice(input: &[u8]) -> Option<Self> {
308 if input.len() > MAX_CONNID_ENCODED_LEN - 1 {
309 None
310 } else {
311 let mut s = [0; MAX_CONNID_ENCODED_LEN];
312 if input.len() == 1
313 && matches!(ConnIdType::classify(input[0]), Some(ConnIdType::SingleByte))
314 {
315 s[0] = input[0];
316 } else {
317 s[0] = input.len() as u8 | 0x40;
318 s[1..1 + input.len()].copy_from_slice(input);
319 }
320 Some(Self(s))
321 }
322 }
323}
324
325#[derive(PartialEq, Debug)]
326pub enum EDHOCMethod {
327 StatStat = 3,
328 }
332
333impl From<EDHOCMethod> for u8 {
334 fn from(method: EDHOCMethod) -> u8 {
335 method as u8
336 }
337}
338
339#[derive(PartialEq, Debug)]
340pub enum EDHOCSuite {
341 CipherSuite2 = 2,
342 }
345
346impl From<EDHOCSuite> for u8 {
347 fn from(suite: EDHOCSuite) -> u8 {
348 suite as u8
349 }
350}
351
352#[derive(PartialEq, Debug)]
353#[non_exhaustive]
354pub enum EDHOCError {
355 UnexpectedCredential,
360 MissingIdentity,
361 IdentityAlreadySet,
362 MacVerificationFailed,
363 UnsupportedMethod,
364 UnsupportedCipherSuite,
365 ParsingError,
366 EncodingError,
367 CredentialTooLongError,
368 EadLabelTooLongError,
369 EadTooLongError,
370 EADUnprocessable,
373 AccessDenied,
379}
380
381impl EDHOCError {
382 pub fn err_code(&self) -> ErrCode {
396 use EDHOCError::*;
397 match self {
398 UnexpectedCredential => ErrCode::UNSPECIFIED,
399 MissingIdentity => ErrCode::UNSPECIFIED,
400 IdentityAlreadySet => ErrCode::UNSPECIFIED,
401 MacVerificationFailed => ErrCode::UNSPECIFIED,
402 UnsupportedMethod => ErrCode::UNSPECIFIED,
403 UnsupportedCipherSuite => ErrCode::WRONG_SELECTED_CIPHER_SUITE,
404 ParsingError => ErrCode::UNSPECIFIED,
405 EncodingError => ErrCode::UNSPECIFIED,
406 CredentialTooLongError => ErrCode::UNSPECIFIED,
407 EadLabelTooLongError => ErrCode::UNSPECIFIED,
408 EadTooLongError => ErrCode::UNSPECIFIED,
409 EADUnprocessable => ErrCode::UNSPECIFIED,
410 AccessDenied => ErrCode::ACCESS_DENIED,
411 }
412 }
413}
414
415#[repr(C)]
417pub struct ErrCode(pub NonZeroI16);
418
419impl ErrCode {
420 pub const UNSPECIFIED: Self = ErrCode(match NonZeroI16::new(1) {
423 Some(v) => v,
424 _ => unreachable!(),
425 });
426 pub const WRONG_SELECTED_CIPHER_SUITE: Self = ErrCode(match NonZeroI16::new(2) {
427 Some(v) => v,
428 _ => unreachable!(),
429 });
430 pub const UNKNOWN_CREDENTIAL: Self = ErrCode(match NonZeroI16::new(3) {
431 Some(v) => v,
432 _ => unreachable!(),
433 });
434 pub const ACCESS_DENIED: Self = ErrCode(match NonZeroI16::new(3333) {
436 Some(v) => v,
437 _ => unreachable!(),
438 });
439}
440
441#[derive(Debug)]
442#[repr(C)]
443pub struct InitiatorStart {
444 pub suites_i: EdhocBuffer<MAX_SUITES_LEN>,
445 pub method: u8,
446 pub x: BytesP256ElemLen, pub g_x: BytesP256ElemLen, }
449
450#[derive(Debug)]
451pub struct ResponderStart {
452 pub method: u8,
453 pub y: BytesP256ElemLen, pub g_y: BytesP256ElemLen, }
456
457#[derive(Default, Debug)]
458pub struct ProcessingM1 {
459 pub y: BytesP256ElemLen,
460 pub g_y: BytesP256ElemLen,
461 pub c_i: ConnId,
462 pub g_x: BytesP256ElemLen, pub h_message_1: BytesHashLen,
464}
465
466#[derive(Default, Clone, Debug)]
467#[repr(C)]
468pub struct WaitM2 {
469 pub x: BytesP256ElemLen, pub h_message_1: BytesHashLen,
471}
472
473#[derive(Default, Debug)]
474pub struct WaitM3 {
475 pub y: BytesP256ElemLen, pub prk_3e2m: BytesHashLen,
477 pub th_3: BytesHashLen,
478}
479
480#[derive(Debug, Default)]
481#[repr(C)]
482pub struct ProcessingM2 {
483 pub mac_2: BytesMac2,
484 pub prk_2e: BytesHashLen,
485 pub th_2: BytesHashLen,
486 pub x: BytesP256ElemLen,
487 pub g_y: BytesP256ElemLen,
488 pub plaintext_2: EdhocMessageBuffer,
489 pub c_r: ConnId,
490 pub id_cred_r: IdCred,
491 pub ead_2: Option<EADItem>,
492}
493
494#[derive(Default, Debug)]
495#[repr(C)]
496pub struct ProcessedM2 {
497 pub prk_3e2m: BytesHashLen,
498 pub prk_4e3m: BytesHashLen,
499 pub th_3: BytesHashLen,
500}
501
502#[derive(Default, Debug)]
503pub struct ProcessingM3 {
504 pub mac_3: BytesMac3,
505 pub y: BytesP256ElemLen, pub prk_3e2m: BytesHashLen,
507 pub th_3: BytesHashLen,
508 pub id_cred_i: IdCred,
509 pub plaintext_3: EdhocMessageBuffer,
510 pub ead_3: Option<EADItem>,
511}
512
513#[derive(Default, Debug)]
514pub struct PreparingM3 {
515 pub prk_3e2m: BytesHashLen,
516 pub prk_4e3m: BytesHashLen,
517 pub th_3: BytesHashLen,
518 pub mac_3: BytesMac3,
519}
520
521#[derive(Default, Debug)]
522pub struct ProcessedM3 {
523 pub prk_4e3m: BytesHashLen,
524 pub th_4: BytesHashLen,
525 pub prk_out: BytesHashLen,
526 pub prk_exporter: BytesHashLen,
527}
528
529#[derive(Default, Debug)]
530#[repr(C)]
531pub struct WaitM4 {
532 pub prk_4e3m: BytesHashLen,
533 pub th_4: BytesHashLen,
534 pub prk_out: BytesHashLen,
535 pub prk_exporter: BytesHashLen,
536}
537
538#[derive(Default, Debug)]
539#[repr(C)]
540pub struct Completed {
541 pub prk_out: BytesHashLen,
542 pub prk_exporter: BytesHashLen,
543}
544
545#[cfg_attr(feature = "python-bindings", pyclass(eq, eq_int))]
546#[derive(Copy, Clone, Debug, PartialEq)]
547#[repr(C)]
548pub enum CredentialTransfer {
549 ByReference,
550 ByValue,
551}
552
553#[derive(PartialEq, Debug)]
554#[repr(C)]
555pub enum MessageBufferError {
556 BufferAlreadyFull,
557 SliceTooLong,
558}
559
560#[repr(C)]
565#[derive(PartialEq, Debug, Copy, Clone)]
566pub struct EdhocMessageBuffer {
567 pub content: [u8; MAX_MESSAGE_SIZE_LEN],
568 pub len: usize,
569}
570
571impl Default for EdhocMessageBuffer {
572 fn default() -> Self {
573 EdhocMessageBuffer {
574 content: [0; MAX_MESSAGE_SIZE_LEN],
575 len: 0,
576 }
577 }
578}
579
580impl EdhocMessageBuffer {
581 pub fn new() -> Self {
582 EdhocMessageBuffer {
583 content: [0u8; MAX_MESSAGE_SIZE_LEN],
584 len: 0,
585 }
586 }
587
588 pub fn new_from_slice(slice: &[u8]) -> Result<Self, MessageBufferError> {
589 let mut buffer = Self::new();
590 if buffer.fill_with_slice(slice).is_ok() {
591 Ok(buffer)
592 } else {
593 Err(MessageBufferError::SliceTooLong)
594 }
595 }
596
597 pub fn get(self, index: usize) -> Option<u8> {
598 self.content.get(index).copied()
599 }
600
601 pub fn push(&mut self, item: u8) -> Result<(), MessageBufferError> {
602 if self.len < self.content.len() {
603 self.content[self.len] = item;
604 self.len += 1;
605 Ok(())
606 } else {
607 Err(MessageBufferError::BufferAlreadyFull)
608 }
609 }
610
611 pub fn get_slice(&self, start: usize, len: usize) -> Option<&[u8]> {
612 self.content.get(start..start + len)
613 }
614
615 pub fn as_slice(&self) -> &[u8] {
616 &self.content[0..self.len]
617 }
618
619 pub fn fill_with_slice(&mut self, slice: &[u8]) -> Result<(), MessageBufferError> {
620 if slice.len() <= self.content.len() {
621 self.len = slice.len();
622 self.content[..self.len].copy_from_slice(slice);
623 Ok(())
624 } else {
625 Err(MessageBufferError::SliceTooLong)
626 }
627 }
628
629 pub fn extend_from_slice(&mut self, slice: &[u8]) -> Result<(), MessageBufferError> {
630 if self.len + slice.len() <= self.content.len() {
631 self.content[self.len..self.len + slice.len()].copy_from_slice(slice);
632 self.len += slice.len();
633 Ok(())
634 } else {
635 Err(MessageBufferError::SliceTooLong)
636 }
637 }
638
639 pub fn from_hex(hex: &str) -> Self {
640 let mut buffer = EdhocMessageBuffer::new();
641 buffer.len = hex.len() / 2;
642 for (i, chunk) in hex.as_bytes().chunks(2).enumerate() {
643 let chunk_str = core::str::from_utf8(chunk).unwrap();
644 buffer.content[i] = u8::from_str_radix(chunk_str, 16).unwrap();
645 }
646 buffer
647 }
648}
649
650impl TryInto<EdhocMessageBuffer> for &[u8] {
651 type Error = ();
652
653 fn try_into(self) -> Result<EdhocMessageBuffer, Self::Error> {
654 let mut buffer = [0u8; MAX_MESSAGE_SIZE_LEN];
655 if self.len() <= buffer.len() {
656 buffer[..self.len()].copy_from_slice(self);
657
658 Ok(EdhocMessageBuffer {
659 content: buffer,
660 len: self.len(),
661 })
662 } else {
663 Err(())
664 }
665 }
666}
667
668#[cfg_attr(feature = "python-bindings", pyclass)]
669#[derive(Clone, Debug)]
670pub struct EADItem {
671 pub label: u16,
677 pub is_critical: bool,
678 pub value: Option<EdhocMessageBuffer>,
680}
681
682impl EADItem {
683 pub fn new() -> Self {
684 EADItem {
685 label: 0,
686 is_critical: false,
687 value: None,
688 }
689 }
690}
691
692mod helpers {
693 use super::*;
694
695 pub fn encode_info(
696 label: u8,
697 context: &BytesMaxContextBuffer,
698 context_len: usize,
699 length: usize,
700 ) -> (BytesMaxInfoBuffer, usize) {
701 let mut info: BytesMaxInfoBuffer = [0x00; MAX_INFO_LEN];
702
703 info[0] = label;
705 let mut info_len = if context_len < 24 {
706 info[1] = context_len as u8 | CBOR_MAJOR_BYTE_STRING;
707 info[2..2 + context_len].copy_from_slice(&context[..context_len]);
708 2 + context_len
709 } else {
710 info[1] = CBOR_BYTE_STRING;
711 info[2] = context_len as u8;
712 info[3..3 + context_len].copy_from_slice(&context[..context_len]);
713 3 + context_len
714 };
715
716 info_len = if length < 24 {
717 info[info_len] = length as u8;
718 info_len + 1
719 } else {
720 info[info_len] = CBOR_UINT_1BYTE;
721 info[info_len + 1] = length as u8;
722 info_len + 2
723 };
724
725 (info, info_len)
726 }
727}
728
729mod edhoc_parser {
731 use super::*;
732
733 pub fn parse_ead(buffer: &[u8]) -> Result<Option<EADItem>, EDHOCError> {
734 trace!("Enter parse_ead");
735 if let Some((&label, tail)) = buffer.split_first() {
737 let label_res = if CBORDecoder::is_u8(label) {
738 Ok((label, false))
740 } else if CBORDecoder::is_i8(label) {
741 Ok((label - (CBOR_NEG_INT_1BYTE_START - 1), true))
743 } else {
744 Err(EDHOCError::ParsingError)
745 };
746
747 if let Ok((label, is_critical)) = label_res {
748 let ead_value = if tail.len() > 0 {
749 let mut buffer = EdhocMessageBuffer::new();
751 buffer.fill_with_slice(tail).unwrap(); buffer.len = tail.len();
753 Some(buffer)
754 } else {
755 None
756 };
757 let ead_item = Some(EADItem {
758 label: label.into(),
759 is_critical,
760 value: ead_value,
761 });
762 Ok(ead_item)
763 } else {
764 Err(EDHOCError::ParsingError)
765 }
766 } else {
767 Err(EDHOCError::ParsingError)
768 }
769 }
770
771 pub fn parse_suites_i(
772 mut decoder: CBORDecoder,
773 ) -> Result<(EdhocBuffer<MAX_SUITES_LEN>, CBORDecoder), EDHOCError> {
774 trace!("Enter parse_suites_i");
775 let mut suites_i: EdhocBuffer<MAX_SUITES_LEN> = Default::default();
776 if let Ok(curr) = decoder.current() {
777 if CBOR_UINT_1BYTE_START == CBORDecoder::type_of(curr) {
778 let Ok(_) = suites_i.push(decoder.u8()?) else {
779 return Err(EDHOCError::ParsingError);
780 };
781 Ok((suites_i, decoder))
782 } else if CBOR_MAJOR_ARRAY == CBORDecoder::type_of(curr)
783 && CBORDecoder::info_of(curr) >= 2
784 {
785 let received_suites_i_len = decoder.array()?;
787 if received_suites_i_len <= suites_i.capacity() {
788 for i in 0..received_suites_i_len {
789 suites_i.content[i] = decoder.u8()?;
791 }
792 suites_i.len = received_suites_i_len;
793 Ok((suites_i, decoder))
794 } else {
795 Err(EDHOCError::ParsingError)
796 }
797 } else {
798 Err(EDHOCError::ParsingError)
799 }
800 } else {
801 Err(EDHOCError::ParsingError)
802 }
803 }
804
805 pub fn parse_message_1(
806 rcvd_message_1: &BufferMessage1,
807 ) -> Result<
808 (
809 u8,
810 EdhocBuffer<MAX_SUITES_LEN>,
811 BytesP256ElemLen,
812 ConnId,
813 Option<EADItem>,
814 ),
815 EDHOCError,
816 > {
817 trace!("Enter parse_message_1");
818 let mut decoder = CBORDecoder::new(rcvd_message_1.as_slice());
819 let method = decoder.u8()?;
820
821 if let Ok((suites_i, mut decoder)) = parse_suites_i(decoder) {
822 let mut g_x: BytesP256ElemLen = [0x00; P256_ELEM_LEN];
823 g_x.copy_from_slice(decoder.bytes_sized(P256_ELEM_LEN)?);
824
825 let c_i = ConnId::from_decoder(&mut decoder)?;
827
828 if rcvd_message_1.len > decoder.position() {
830 let ead_res = parse_ead(decoder.remaining_buffer()?);
833 if let Ok(ead_1) = ead_res {
834 Ok((method, suites_i, g_x, c_i, ead_1))
835 } else {
836 Err(ead_res.unwrap_err())
837 }
838 } else if decoder.finished() {
839 Ok((method, suites_i, g_x, c_i, None))
840 } else {
841 Err(EDHOCError::ParsingError)
842 }
843 } else {
844 Err(EDHOCError::ParsingError)
845 }
846 }
847
848 pub fn parse_message_2(
849 rcvd_message_2: &BufferMessage2,
850 ) -> Result<(BytesP256ElemLen, BufferCiphertext2), EDHOCError> {
851 trace!("Enter parse_message_2");
852 let mut ciphertext_2: BufferCiphertext2 = BufferCiphertext2::new();
854
855 let mut decoder = CBORDecoder::new(rcvd_message_2.as_slice());
856
857 let decoded = decoder.bytes()?;
859 if decoder.finished() {
860 if let Some(key) = decoded.get(0..P256_ELEM_LEN) {
861 let mut g_y: BytesP256ElemLen = [0x00; P256_ELEM_LEN];
862 g_y.copy_from_slice(key);
863 if let Some(c2) = decoded.get(P256_ELEM_LEN..) {
864 if ciphertext_2.fill_with_slice(c2).is_ok() {
865 Ok((g_y, ciphertext_2))
866 } else {
867 Err(EDHOCError::ParsingError)
868 }
869 } else {
870 Err(EDHOCError::ParsingError)
871 }
872 } else {
873 Err(EDHOCError::ParsingError)
874 }
875 } else {
876 Err(EDHOCError::ParsingError)
877 }
878 }
879
880 pub fn decode_plaintext_2(
881 plaintext_2: &BufferCiphertext2,
882 ) -> Result<(ConnId, IdCred, BytesMac2, Option<EADItem>), EDHOCError> {
883 trace!("Enter decode_plaintext_2");
884 let mut mac_2: BytesMac2 = [0x00; MAC_LENGTH_2];
885
886 let mut decoder = CBORDecoder::new(plaintext_2.as_slice());
887
888 let c_r = ConnId::from_decoder(&mut decoder)?;
889
890 let id_cred_r = IdCred::from_encoded_value(decoder.any_as_encoded()?)?;
892
893 mac_2[..].copy_from_slice(decoder.bytes_sized(MAC_LENGTH_2)?);
894
895 if plaintext_2.len > decoder.position() {
897 let ead_res = parse_ead(decoder.remaining_buffer()?);
899 if let Ok(ead_2) = ead_res {
900 Ok((c_r, id_cred_r, mac_2, ead_2))
901 } else {
902 Err(ead_res.unwrap_err())
903 }
904 } else if decoder.finished() {
905 Ok((c_r, id_cred_r, mac_2, None))
906 } else {
907 Err(EDHOCError::ParsingError)
908 }
909 }
910
911 pub fn decode_plaintext_3(
912 plaintext_3: &BufferPlaintext3,
913 ) -> Result<(IdCred, BytesMac3, Option<EADItem>), EDHOCError> {
914 trace!("Enter decode_plaintext_3");
915 let mut mac_3: BytesMac3 = [0x00; MAC_LENGTH_3];
916
917 let mut decoder = CBORDecoder::new(plaintext_3.as_slice());
918
919 let id_cred_i = IdCred::from_encoded_value(decoder.any_as_encoded()?)?;
921
922 mac_3[..].copy_from_slice(decoder.bytes_sized(MAC_LENGTH_3)?);
923
924 if plaintext_3.len > decoder.position() {
926 let ead_res = parse_ead(decoder.remaining_buffer()?);
928 if let Ok(ead_3) = ead_res {
929 Ok((id_cred_i, mac_3, ead_3))
930 } else {
931 Err(ead_res.unwrap_err())
932 }
933 } else if decoder.finished() {
934 Ok((id_cred_i, mac_3, None))
935 } else {
936 Err(EDHOCError::ParsingError)
937 }
938 }
939
940 pub fn decode_plaintext_4(
941 plaintext_4: &BufferPlaintext4,
942 ) -> Result<Option<EADItem>, EDHOCError> {
943 trace!("Enter decode_plaintext_4");
944 let decoder = CBORDecoder::new(plaintext_4.as_slice());
945
946 if plaintext_4.len > decoder.position() {
947 let ead_res = parse_ead(decoder.remaining_buffer()?);
949 if let Ok(ead_4) = ead_res {
950 Ok(ead_4)
951 } else {
952 Err(ead_res.unwrap_err())
953 }
954 } else if decoder.finished() {
955 Ok(None)
956 } else {
957 Err(EDHOCError::ParsingError)
958 }
959 }
960}
961
962mod cbor_decoder {
963 use super::*;
965
966 #[derive(Debug)]
967 pub enum CBORError {
968 DecodingError,
969 }
970
971 impl From<CBORError> for EDHOCError {
972 fn from(error: CBORError) -> Self {
973 match error {
974 CBORError::DecodingError => EDHOCError::ParsingError,
975 }
976 }
977 }
978
979 #[derive(Debug)]
980 pub struct CBORDecoder<'a> {
981 buf: &'a [u8],
982 pos: usize,
983 }
984
985 impl<'a> CBORDecoder<'a> {
986 pub fn new(bytes: &'a [u8]) -> Self {
987 CBORDecoder { buf: bytes, pos: 0 }
988 }
989
990 fn read(&mut self) -> Result<u8, CBORError> {
991 if let Some(b) = self.buf.get(self.pos) {
992 self.pos += 1;
993 Ok(*b)
994 } else {
995 Err(CBORError::DecodingError)
996 }
997 }
998
999 pub fn read_slice(&mut self, n: usize) -> Result<&'a [u8], CBORError> {
1001 if let Some(b) = self
1002 .pos
1003 .checked_add(n)
1004 .and_then(|end| self.buf.get(self.pos..end))
1005 {
1006 self.pos += n;
1007 Ok(b)
1008 } else {
1009 Err(CBORError::DecodingError)
1010 }
1011 }
1012
1013 pub fn position(&self) -> usize {
1014 self.pos
1015 }
1016
1017 pub fn finished(&self) -> bool {
1018 self.pos == self.buf.len()
1019 }
1020
1021 pub fn ensure_finished(&self) -> Result<(), CBORError> {
1022 if self.finished() {
1023 Ok(())
1024 } else {
1025 Err(CBORError::DecodingError)
1026 }
1027 }
1028
1029 pub fn remaining_buffer(&self) -> Result<&[u8], CBORError> {
1030 if let Some(buffer) = self.buf.get(self.pos..) {
1031 Ok(buffer)
1032 } else {
1033 Err(CBORError::DecodingError)
1034 }
1035 }
1036
1037 pub fn current(&self) -> Result<u8, CBORError> {
1039 if let Some(b) = self.buf.get(self.pos) {
1040 Ok(*b)
1041 } else {
1042 Err(CBORError::DecodingError)
1043 }
1044 }
1045
1046 pub fn u8(&mut self) -> Result<u8, CBORError> {
1048 let n = self.read()?;
1049 if (0..=0x17).contains(&n) {
1051 Ok(n)
1052 } else if 0x18 == n {
1053 self.read()
1054 } else {
1055 Err(CBORError::DecodingError)
1056 }
1057 }
1058
1059 pub fn i8(&mut self) -> Result<i8, CBORError> {
1061 let n = self.read()?;
1062 if (0..=0x17).contains(&n) {
1063 Ok(n as i8)
1064 } else if (0x20..=0x37).contains(&n) {
1065 Ok(-1 - (n - 0x20) as i8)
1066 } else if 0x18 == n {
1067 Ok(self.read()? as i8)
1068 } else if 0x38 == n {
1069 Ok(-1 - (self.read()? - 0x20) as i8)
1070 } else {
1071 Err(CBORError::DecodingError)
1072 }
1073 }
1074
1075 pub fn int_raw(&mut self) -> Result<u8, CBORError> {
1077 let n = self.read()?;
1078 if (0..=0x17).contains(&n) || (0x20..=0x37).contains(&n) {
1079 Ok(n)
1080 } else {
1081 Err(CBORError::DecodingError)
1082 }
1083 }
1084
1085 pub fn str(&mut self) -> Result<&'a [u8], CBORError> {
1087 let b = self.read()?;
1088 if CBOR_MAJOR_TEXT_STRING != Self::type_of(b) || Self::info_of(b) == 31 {
1089 Err(CBORError::DecodingError)
1090 } else {
1091 let n = self.as_usize(Self::info_of(b))?;
1092 self.read_slice(n)
1093 }
1094 }
1095
1096 pub fn bytes(&mut self) -> Result<&'a [u8], CBORError> {
1098 let b = self.read()?;
1099 if CBOR_MAJOR_BYTE_STRING != Self::type_of(b) || Self::info_of(b) == 31 {
1100 Err(CBORError::DecodingError)
1101 } else {
1102 let n = self.as_usize(Self::info_of(b))?;
1103 self.read_slice(n)
1104 }
1105 }
1106
1107 pub fn bytes_sized(&mut self, expected_size: usize) -> Result<&'a [u8], CBORError> {
1109 let res = self.bytes()?;
1110 if res.len() == expected_size {
1111 Ok(res)
1112 } else {
1113 Err(CBORError::DecodingError)
1114 }
1115 }
1116
1117 pub fn array(&mut self) -> Result<usize, CBORError> {
1119 let b = self.read()?;
1120 if CBOR_MAJOR_ARRAY != Self::type_of(b) {
1121 Err(CBORError::DecodingError)
1122 } else {
1123 match Self::info_of(b) {
1124 31 => Err(CBORError::DecodingError), n => Ok(self.as_usize(n)?),
1126 }
1127 }
1128 }
1129
1130 pub fn map(&mut self) -> Result<usize, CBORError> {
1132 let b = self.read()?;
1133 if CBOR_MAJOR_MAP != Self::type_of(b) {
1134 Err(CBORError::DecodingError)
1135 } else {
1136 match Self::info_of(b) {
1137 n if n < 24 => Ok(self.as_usize(n)?),
1138 _ => Err(CBORError::DecodingError), }
1140 }
1141 }
1142
1143 pub fn as_usize(&mut self, b: u8) -> Result<usize, CBORError> {
1145 if (0..=0x17).contains(&b) {
1146 Ok(usize::from(b))
1147 } else if 0x18 == b {
1148 self.read().map(usize::from)
1149 } else {
1150 Err(CBORError::DecodingError)
1151 }
1152 }
1153
1154 pub fn type_of(b: u8) -> u8 {
1156 b & 0b111_00000
1157 }
1158
1159 pub fn info_of(b: u8) -> u8 {
1161 b & 0b000_11111
1162 }
1163
1164 pub fn is_u8(byte: u8) -> bool {
1166 byte >= CBOR_UINT_1BYTE_START && byte <= CBOR_UINT_1BYTE_END
1167 }
1168
1169 pub fn is_i8(byte: u8) -> bool {
1171 byte >= CBOR_NEG_INT_1BYTE_START && byte <= CBOR_NEG_INT_1BYTE_END
1172 }
1173
1174 pub fn any_as_encoded(&mut self) -> Result<&'a [u8], CBORError> {
1180 let mut remaining_items = 1;
1181 let start = self.position();
1182
1183 for _ in self.buf.iter() {
1192 if remaining_items > 0 {
1193 remaining_items -= 1;
1194 let head = self.read()?;
1195 let major = head >> 5;
1196 let minor = head & 0x1f;
1197 let argument = match minor {
1198 0..=23 => minor,
1199 24 => self.read()?,
1200 25 | 26 | 27 => return Err(CBORError::DecodingError),
1208 28 | 29 | 30 => return Err(CBORError::DecodingError),
1210 31 => return Err(CBORError::DecodingError),
1213 _ => unreachable!("Value was masked to 5 bits"),
1214 };
1215 match major {
1216 0..=1 => (), 7 => (), 6 => {
1219 remaining_items += 1;
1220 }
1221 2..=3 => {
1222 self.read_slice(argument.into())?;
1223 }
1224 4 => {
1225 remaining_items += argument;
1226 }
1227 5 => {
1228 remaining_items += argument * 2;
1229 }
1230 _ => unreachable!("Value is result of a right shift trimming it to 3 bits"),
1231 }
1232 }
1233 }
1234
1235 Ok(&self.buf[start..self.position()])
1236 }
1237 }
1238}
1239
1240#[cfg(test)]
1241mod test_cbor_decoder {
1242 use super::cbor_decoder::*;
1243 use hexlit::hex;
1244
1245 #[test]
1246 fn test_cbor_decoder() {
1247 let input = [0x01, 0x20, 0x62, 0x68, 0x69, 0x42, 0xFE, 0xFE];
1249 let mut decoder = CBORDecoder::new(&input);
1250
1251 assert_eq!(1, decoder.u8().unwrap());
1252 assert_eq!(-1, decoder.i8().unwrap());
1253 assert_eq!([0x68, 0x69], decoder.str().unwrap()); assert_eq!([0xFE, 0xFE], decoder.bytes().unwrap());
1255 }
1256
1257 #[test]
1258 fn test_cbor_decoder_any_as_decoded() {
1259 let input = hex!("A46562797465734376616C616E187B66746167676564D8FF82616120646465657082818181818181818181818181818181818181818180A101A102A103A10484E0F5F6F880");
1263 let mut decoder = CBORDecoder::new(&input);
1264
1265 assert_eq!(input, decoder.any_as_encoded().unwrap());
1266 assert!(decoder.finished())
1267 }
1268}