1use crate::cbor::{
19 self, Cbor, Decode, Encode, MapDecode, MapEncode, MapEncodeBuffer, MapEntryAccess,
20};
21
22#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
30pub struct Ueid {
31 #[cbor(key = 256)]
33 pub ueid: Vec<u8>,
34}
35
36#[derive(Clone, Debug, PartialEq, Eq)]
39pub struct Oemid {
40 value: OemidValue,
41}
42
43impl Oemid {
44 pub fn new_random(id: [u8; 16]) -> Self {
46 Self {
47 value: OemidValue::Random(id),
48 }
49 }
50
51 pub fn new_ieee(id: [u8; 3]) -> Self {
53 Self {
54 value: OemidValue::Ieee(id),
55 }
56 }
57
58 pub fn new_pen(pen: u64) -> Self {
60 Self {
61 value: OemidValue::Pen(pen),
62 }
63 }
64
65 pub fn random(&self) -> Option<[u8; 16]> {
67 match self.value {
68 OemidValue::Random(id) => Some(id),
69 _ => None,
70 }
71 }
72
73 pub fn ieee(&self) -> Option<[u8; 3]> {
75 match self.value {
76 OemidValue::Ieee(id) => Some(id),
77 _ => None,
78 }
79 }
80
81 pub fn pen(&self) -> Option<u64> {
83 match self.value {
84 OemidValue::Pen(pen) => Some(pen),
85 _ => None,
86 }
87 }
88}
89
90#[derive(Clone, Debug, PartialEq, Eq)]
92enum OemidValue {
93 Random([u8; 16]),
94 Ieee([u8; 3]),
95 Pen(u64),
96}
97
98impl Encode for OemidValue {
99 fn encode_cbor_to(&self, buf: &mut Vec<u8>) -> Result<(), cbor::Error> {
100 match self {
101 OemidValue::Random(id) => id.as_slice().encode_cbor_to(buf),
102 OemidValue::Ieee(id) => id.as_slice().encode_cbor_to(buf),
103 OemidValue::Pen(pen) => pen.encode_cbor_to(buf),
104 }
105 }
106}
107
108impl Decode for OemidValue {
109 fn decode_cbor(data: &[u8]) -> Result<Self, cbor::Error> {
110 let mut dec = cbor::Decoder::new(data);
111 let result = Self::decode_cbor_notrail(&mut dec)?;
112 dec.finish()?;
113 Ok(result)
114 }
115
116 fn decode_cbor_notrail(dec: &mut cbor::Decoder<'_>) -> Result<Self, cbor::Error> {
117 if dec.peek_uint().is_ok() {
119 let pen = dec.decode_uint()?;
120 return Ok(OemidValue::Pen(pen));
121 }
122 let bytes = dec.decode_bytes()?;
124 match bytes.len() {
125 3 => {
126 let mut id = [0u8; 3];
127 id.copy_from_slice(&bytes);
128 Ok(OemidValue::Ieee(id))
129 }
130 16 => {
131 let mut id = [0u8; 16];
132 id.copy_from_slice(&bytes);
133 Ok(OemidValue::Random(id))
134 }
135 n => Err(cbor::Error::DecodeFailed(format!(
136 "oemid: unexpected bstr length {n}"
137 ))),
138 }
139 }
140}
141
142impl Encode for Oemid {
143 fn encode_cbor_to(&self, buf: &mut Vec<u8>) -> Result<(), cbor::Error> {
144 let mut enc = MapEncodeBuffer::new(1);
145 <Self as MapEncode>::encode_map(self, &mut enc)?;
146 enc.finish_to(buf)
147 }
148}
149
150impl Decode for Oemid {
151 fn decode_cbor(data: &[u8]) -> Result<Self, cbor::Error> {
152 let mut dec = cbor::Decoder::new(data);
153 let result = Self::decode_cbor_notrail(&mut dec)?;
154 dec.finish()?;
155 Ok(result)
156 }
157
158 fn decode_cbor_notrail(dec: &mut cbor::Decoder<'_>) -> Result<Self, cbor::Error> {
159 let entries = cbor::decode_map_entries_slices_notrail(dec)?;
160 let mut remaining = cbor::MapEntries::new(entries);
161 let value = <Self as MapDecode>::decode_map(&mut remaining)?;
162 if !remaining.is_empty() {
163 let unknown: Vec<i64> = remaining.remaining_keys();
164 return Err(cbor::Error::DecodeFailed(format!(
165 "unknown CBOR map keys: {unknown:?}"
166 )));
167 }
168 Ok(value)
169 }
170}
171
172impl MapEncode for Oemid {
173 fn encode_map(&self, enc: &mut MapEncodeBuffer) -> Result<(), cbor::Error> {
174 enc.push(258, &self.value)
175 }
176}
177
178impl MapDecode for Oemid {
179 fn cbor_map_keys() -> &'static [i64] {
180 &[258]
181 }
182
183 fn decode_map<'a, E: MapEntryAccess<'a>>(entries: &mut E) -> Result<Self, cbor::Error> {
184 let raw = entries
185 .take(258)
186 .ok_or(cbor::Error::DecodeFailed("missing required key 258".into()))?;
187 let value = OemidValue::decode_cbor(raw)?;
188 Ok(Self { value })
189 }
190}
191
192#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
194pub struct HwModel {
195 #[cbor(key = 259)]
197 pub hw_model: Vec<u8>,
198}
199
200#[derive(Clone, Debug, PartialEq, Eq)]
204pub struct HwVersion {
205 version: String,
206}
207
208impl HwVersion {
209 pub fn new(version: String) -> Self {
211 Self { version }
212 }
213
214 pub fn version(&self) -> &str {
216 &self.version
217 }
218}
219
220#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
222#[cbor(array)]
223struct VersionArray {
224 version: String,
225}
226
227impl Encode for HwVersion {
228 fn encode_cbor_to(&self, buf: &mut Vec<u8>) -> Result<(), cbor::Error> {
229 let mut enc = MapEncodeBuffer::new(1);
230 <Self as MapEncode>::encode_map(self, &mut enc)?;
231 enc.finish_to(buf)
232 }
233}
234
235impl Decode for HwVersion {
236 fn decode_cbor(data: &[u8]) -> Result<Self, cbor::Error> {
237 let mut dec = cbor::Decoder::new(data);
238 let result = Self::decode_cbor_notrail(&mut dec)?;
239 dec.finish()?;
240 Ok(result)
241 }
242
243 fn decode_cbor_notrail(dec: &mut cbor::Decoder<'_>) -> Result<Self, cbor::Error> {
244 let entries = cbor::decode_map_entries_slices_notrail(dec)?;
245 let mut remaining = cbor::MapEntries::new(entries);
246 let value = <Self as MapDecode>::decode_map(&mut remaining)?;
247 if !remaining.is_empty() {
248 let unknown: Vec<i64> = remaining.remaining_keys();
249 return Err(cbor::Error::DecodeFailed(format!(
250 "unknown CBOR map keys: {unknown:?}"
251 )));
252 }
253 Ok(value)
254 }
255}
256
257impl MapEncode for HwVersion {
258 fn encode_map(&self, enc: &mut MapEncodeBuffer) -> Result<(), cbor::Error> {
259 let arr = VersionArray {
260 version: self.version.clone(),
261 };
262 enc.push(260, &arr)
263 }
264}
265
266impl MapDecode for HwVersion {
267 fn cbor_map_keys() -> &'static [i64] {
268 &[260]
269 }
270
271 fn decode_map<'a, E: MapEntryAccess<'a>>(entries: &mut E) -> Result<Self, cbor::Error> {
272 let raw = entries
273 .take(260)
274 .ok_or(cbor::Error::DecodeFailed("missing required key 260".into()))?;
275 let arr = VersionArray::decode_cbor(raw)?;
276 Ok(Self {
277 version: arr.version,
278 })
279 }
280}
281
282#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
284pub struct Uptime {
285 #[cbor(key = 261)]
287 pub uptime: u64,
288}
289
290#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
293pub struct OemBoot {
294 #[cbor(key = 262)]
296 pub oem_boot: bool,
297}
298
299#[derive(Clone, Copy, Debug, PartialEq, Eq)]
301#[repr(u64)]
302pub enum DebugState {
303 Enabled = 0,
305 Disabled = 1,
307 DisabledSinceBoot = 2,
309 DisabledPermanently = 3,
313 DisabledFullyPermanently = 4,
316}
317
318impl Encode for DebugState {
319 fn encode_cbor_to(&self, buf: &mut Vec<u8>) -> Result<(), cbor::Error> {
320 (*self as u64).encode_cbor_to(buf)
321 }
322}
323
324impl Decode for DebugState {
325 fn decode_cbor(data: &[u8]) -> Result<Self, cbor::Error> {
326 let mut dec = cbor::Decoder::new(data);
327 let result = Self::decode_cbor_notrail(&mut dec)?;
328 dec.finish()?;
329 Ok(result)
330 }
331
332 fn decode_cbor_notrail(dec: &mut cbor::Decoder<'_>) -> Result<Self, cbor::Error> {
333 let value = dec.decode_uint()?;
334 match value {
335 0 => Ok(DebugState::Enabled),
336 1 => Ok(DebugState::Disabled),
337 2 => Ok(DebugState::DisabledSinceBoot),
338 3 => Ok(DebugState::DisabledPermanently),
339 4 => Ok(DebugState::DisabledFullyPermanently),
340 _ => Err(cbor::Error::DecodeFailed(format!(
341 "invalid debug state: {value}"
342 ))),
343 }
344 }
345}
346
347#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
349pub struct DebugStatus {
350 #[cbor(key = 263)]
352 pub debug_status: DebugState,
353}
354
355#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
358pub struct BootCount {
359 #[cbor(key = 267)]
361 pub boot_count: u64,
362}
363
364#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
366pub struct BootSeed {
367 #[cbor(key = 268)]
369 pub boot_seed: Vec<u8>,
370}
371
372#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
375pub struct SwName {
376 #[cbor(key = 270)]
378 pub sw_name: String,
379}
380
381#[derive(Clone, Debug, PartialEq, Eq)]
385pub struct SwVersion {
386 version: String,
387}
388
389impl SwVersion {
390 pub fn new(version: String) -> Self {
392 Self { version }
393 }
394
395 pub fn version(&self) -> &str {
397 &self.version
398 }
399}
400
401impl Encode for SwVersion {
402 fn encode_cbor_to(&self, buf: &mut Vec<u8>) -> Result<(), cbor::Error> {
403 let mut enc = MapEncodeBuffer::new(1);
404 <Self as MapEncode>::encode_map(self, &mut enc)?;
405 enc.finish_to(buf)
406 }
407}
408
409impl Decode for SwVersion {
410 fn decode_cbor(data: &[u8]) -> Result<Self, cbor::Error> {
411 let mut dec = cbor::Decoder::new(data);
412 let result = Self::decode_cbor_notrail(&mut dec)?;
413 dec.finish()?;
414 Ok(result)
415 }
416
417 fn decode_cbor_notrail(dec: &mut cbor::Decoder<'_>) -> Result<Self, cbor::Error> {
418 let entries = cbor::decode_map_entries_slices_notrail(dec)?;
419 let mut remaining = cbor::MapEntries::new(entries);
420 let value = <Self as MapDecode>::decode_map(&mut remaining)?;
421 if !remaining.is_empty() {
422 let unknown: Vec<i64> = remaining.remaining_keys();
423 return Err(cbor::Error::DecodeFailed(format!(
424 "unknown CBOR map keys: {unknown:?}"
425 )));
426 }
427 Ok(value)
428 }
429}
430
431impl MapEncode for SwVersion {
432 fn encode_map(&self, enc: &mut MapEncodeBuffer) -> Result<(), cbor::Error> {
433 let arr = VersionArray {
434 version: self.version.clone(),
435 };
436 enc.push(271, &arr)
437 }
438}
439
440impl MapDecode for SwVersion {
441 fn cbor_map_keys() -> &'static [i64] {
442 &[271]
443 }
444
445 fn decode_map<'a, E: MapEntryAccess<'a>>(entries: &mut E) -> Result<Self, cbor::Error> {
446 let raw = entries
447 .take(271)
448 .ok_or(cbor::Error::DecodeFailed("missing required key 271".into()))?;
449 let arr = VersionArray::decode_cbor(raw)?;
450 Ok(Self {
451 version: arr.version,
452 })
453 }
454}
455
456#[derive(Clone, Copy, Debug, PartialEq, Eq)]
458#[repr(u64)]
459pub enum Use {
460 Generic = 1,
462 Registration = 2,
464 Provisioning = 3,
466 CertIssuance = 4,
468 ProofOfPossession = 5,
470}
471
472impl Encode for Use {
473 fn encode_cbor_to(&self, buf: &mut Vec<u8>) -> Result<(), cbor::Error> {
474 (*self as u64).encode_cbor_to(buf)
475 }
476}
477
478impl Decode for Use {
479 fn decode_cbor(data: &[u8]) -> Result<Self, cbor::Error> {
480 let mut dec = cbor::Decoder::new(data);
481 let result = Self::decode_cbor_notrail(&mut dec)?;
482 dec.finish()?;
483 Ok(result)
484 }
485
486 fn decode_cbor_notrail(dec: &mut cbor::Decoder<'_>) -> Result<Self, cbor::Error> {
487 let value = dec.decode_uint()?;
488 match value {
489 1 => Ok(Use::Generic),
490 2 => Ok(Use::Registration),
491 3 => Ok(Use::Provisioning),
492 4 => Ok(Use::CertIssuance),
493 5 => Ok(Use::ProofOfPossession),
494 _ => Err(cbor::Error::DecodeFailed(format!(
495 "invalid intended use: {value}"
496 ))),
497 }
498 }
499}
500
501#[derive(Clone, Debug, PartialEq, Eq, Cbor)]
503pub struct IntendedUse {
504 #[cbor(key = 275)]
506 pub intended_use: Use,
507}
508
509#[cfg(test)]
510mod tests {
511 use super::*;
512
513 #[test]
515 fn test_oemid_random() {
516 let id: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
517
518 #[derive(Debug, Cbor)]
519 struct Token {
520 #[cbor(embed)]
521 oemid: Oemid,
522 }
523 let orig = Token {
524 oemid: Oemid::new_random(id),
525 };
526 let data = cbor::encode(&orig).expect("encode");
527 let got = Token::decode_cbor(&data).expect("decode");
528
529 assert_eq!(got.oemid.random(), Some(id));
530 }
531
532 #[test]
534 fn test_oemid_ieee() {
535 let id: [u8; 3] = [0xAC, 0xDE, 0x48];
536
537 #[derive(Debug, Cbor)]
538 struct Token {
539 #[cbor(embed)]
540 oemid: Oemid,
541 }
542 let orig = Token {
543 oemid: Oemid::new_ieee(id),
544 };
545 let data = cbor::encode(&orig).expect("encode");
546 let got = Token::decode_cbor(&data).expect("decode");
547
548 assert_eq!(got.oemid.ieee(), Some(id));
549 }
550
551 #[test]
553 fn test_oemid_pen() {
554 let pen: u64 = 76543;
555
556 #[derive(Debug, Cbor)]
557 struct Token {
558 #[cbor(embed)]
559 oemid: Oemid,
560 }
561 let orig = Token {
562 oemid: Oemid::new_pen(pen),
563 };
564 let data = cbor::encode(&orig).expect("encode");
565 let got = Token::decode_cbor(&data).expect("decode");
566
567 assert_eq!(got.oemid.pen(), Some(pen));
568 }
569
570 #[test]
572 fn test_oemid_wrong_accessor() {
573 let o = Oemid::new_pen(42);
574 assert_eq!(o.random(), None);
575 assert_eq!(o.ieee(), None);
576 }
577
578 #[test]
580 fn test_hw_version() {
581 #[derive(Debug, Cbor)]
582 struct Token {
583 #[cbor(embed)]
584 hw: HwVersion,
585 }
586 let orig = Token {
587 hw: HwVersion::new("1.2.3".into()),
588 };
589 let data = cbor::encode(&orig).expect("encode");
590 let got = Token::decode_cbor(&data).expect("decode");
591
592 assert_eq!(got.hw.version(), "1.2.3");
593 }
594
595 #[test]
597 fn test_sw_version() {
598 #[derive(Debug, Cbor)]
599 struct Token {
600 #[cbor(embed)]
601 sw: SwVersion,
602 }
603 let orig = Token {
604 sw: SwVersion::new("4.5.6".into()),
605 };
606 let data = cbor::encode(&orig).expect("encode");
607 let got = Token::decode_cbor(&data).expect("decode");
608
609 assert_eq!(got.sw.version(), "4.5.6");
610 }
611
612 #[test]
614 fn test_simple_claims() {
615 #[derive(Debug, Cbor)]
616 struct Token {
617 #[cbor(embed)]
618 ueid: Ueid,
619 #[cbor(embed)]
620 hw_model: HwModel,
621 #[cbor(embed)]
622 uptime: Uptime,
623 #[cbor(embed)]
624 oem_boot: OemBoot,
625 #[cbor(embed)]
626 debug_status: DebugStatus,
627 #[cbor(embed)]
628 boot_count: BootCount,
629 #[cbor(embed)]
630 boot_seed: BootSeed,
631 #[cbor(embed)]
632 sw_name: SwName,
633 #[cbor(embed)]
634 intended_use: IntendedUse,
635 }
636 let orig = Token {
637 ueid: Ueid {
638 ueid: vec![0x01, 0x02, 0x03],
639 },
640 hw_model: HwModel {
641 hw_model: b"board-v2".to_vec(),
642 },
643 uptime: Uptime { uptime: 3600 },
644 oem_boot: OemBoot { oem_boot: true },
645 debug_status: DebugStatus {
646 debug_status: DebugState::DisabledPermanently,
647 },
648 boot_count: BootCount { boot_count: 42 },
649 boot_seed: BootSeed {
650 boot_seed: vec![0xDE, 0xAD],
651 },
652 sw_name: SwName {
653 sw_name: "firmware-v3".into(),
654 },
655 intended_use: IntendedUse {
656 intended_use: Use::CertIssuance,
657 },
658 };
659 let data = cbor::encode(&orig).expect("encode");
660 let got = Token::decode_cbor(&data).expect("decode");
661
662 assert_eq!(got.ueid.ueid, vec![0x01, 0x02, 0x03]);
663 assert_eq!(got.hw_model.hw_model, b"board-v2");
664 assert_eq!(got.uptime.uptime, 3600);
665 assert!(got.oem_boot.oem_boot);
666 assert_eq!(
667 got.debug_status.debug_status,
668 DebugState::DisabledPermanently
669 );
670 assert_eq!(got.boot_count.boot_count, 42);
671 assert_eq!(got.boot_seed.boot_seed, vec![0xDE, 0xAD]);
672 assert_eq!(got.sw_name.sw_name, "firmware-v3");
673 assert_eq!(got.intended_use.intended_use, Use::CertIssuance);
674 }
675
676 #[test]
678 fn test_oemid_invalid_length() {
679 let mut enc = cbor::Encoder::new();
680 enc.encode_map_header(1);
681 enc.encode_int(258);
682 enc.encode_bytes(&[1, 2, 3, 4, 5]); #[derive(Debug, Cbor)]
685 struct Token {
686 #[cbor(embed)]
687 oemid: Oemid,
688 }
689 assert!(Token::decode_cbor(&enc.finish()).is_err());
690 }
691
692 #[test]
694 fn test_oemid_invalid_type() {
695 let mut enc = cbor::Encoder::new();
696 enc.encode_map_header(1);
697 enc.encode_int(258);
698 enc.encode_text("not-bytes");
699
700 #[derive(Debug, Cbor)]
701 struct Token {
702 #[cbor(embed)]
703 oemid: Oemid,
704 }
705 assert!(Token::decode_cbor(&enc.finish()).is_err());
706 }
707
708 #[test]
710 fn test_debug_state_invalid() {
711 let mut enc = cbor::Encoder::new();
712 enc.encode_map_header(1);
713 enc.encode_int(263);
714 enc.encode_uint(99); #[derive(Debug, Cbor)]
717 struct Token {
718 #[cbor(embed)]
719 debug: DebugStatus,
720 }
721 assert!(Token::decode_cbor(&enc.finish()).is_err());
722 }
723
724 #[test]
726 fn test_use_invalid() {
727 let mut enc = cbor::Encoder::new();
728 enc.encode_map_header(1);
729 enc.encode_int(275);
730 enc.encode_uint(0); #[derive(Debug, Cbor)]
733 struct Token {
734 #[cbor(embed)]
735 intended_use: IntendedUse,
736 }
737 assert!(Token::decode_cbor(&enc.finish()).is_err());
738 }
739}