1#![allow(
5 clippy::all,
6 clippy::pedantic,
7 dead_code,
8 unreachable_pub,
9 unused_imports
10)]
11
12use crate::datatypes::SemanticTagStruct;
13use crate::error::ClusterError;
14use crate::types::Nullable;
15use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter, Value};
16
17pub const CLUSTER_ID: u32 = 0x003E;
19pub const CLUSTER_REVISION: u16 = 2;
21
22pub mod command_id {
24 pub const ATTESTATION_REQUEST: u32 = 0x00;
26 pub const ATTESTATION_RESPONSE: u32 = 0x01;
28 pub const CERTIFICATE_CHAIN_REQUEST: u32 = 0x02;
30 pub const CERTIFICATE_CHAIN_RESPONSE: u32 = 0x03;
32 pub const CSR_REQUEST: u32 = 0x04;
34 pub const CSR_RESPONSE: u32 = 0x05;
36 pub const ADD_NOC: u32 = 0x06;
38 pub const UPDATE_NOC: u32 = 0x07;
40 pub const NOC_RESPONSE: u32 = 0x08;
42 pub const UPDATE_FABRIC_LABEL: u32 = 0x09;
44 pub const REMOVE_FABRIC: u32 = 0x0A;
46 pub const ADD_TRUSTED_ROOT_CERTIFICATE: u32 = 0x0B;
48 pub const SET_VID_VERIFICATION_STATEMENT: u32 = 0x0C;
50 pub const SIGN_VID_VERIFICATION_REQUEST: u32 = 0x0D;
52 pub const SIGN_VID_VERIFICATION_RESPONSE: u32 = 0x0E;
54}
55
56pub mod attribute_id {
58 pub const NOCS: u32 = 0x0000;
60 pub const FABRICS: u32 = 0x0001;
62 pub const SUPPORTED_FABRICS: u32 = 0x0002;
64 pub const COMMISSIONED_FABRICS: u32 = 0x0003;
66 pub const TRUSTED_ROOT_CERTIFICATES: u32 = 0x0004;
68 pub const CURRENT_FABRIC_INDEX: u32 = 0x0005;
70}
71
72#[derive(Copy, Clone, Debug, PartialEq, Eq)]
74pub enum CertificateChainTypeEnum {
75 DacCertificate,
77 PaiCertificate,
79 Unknown(u8),
81}
82
83impl CertificateChainTypeEnum {
84 #[must_use]
86 pub fn from_raw(v: u8) -> Self {
87 match v {
88 1 => Self::DacCertificate,
89 2 => Self::PaiCertificate,
90 other => Self::Unknown(other),
91 }
92 }
93 #[must_use]
95 pub fn to_raw(self) -> u8 {
96 match self {
97 Self::DacCertificate => 1,
98 Self::PaiCertificate => 2,
99 Self::Unknown(v) => v,
100 }
101 }
102}
103
104#[derive(Clone, Debug, PartialEq)]
106#[non_exhaustive]
107pub struct FabricDescriptorStruct {
108 pub root_public_key: Vec<u8>,
110 pub vendor_id: u16,
112 pub fabric_id: u64,
114 pub node_id: u64,
116 pub label: String,
118 pub vid_verification_statement: Option<Vec<u8>>,
120 pub fabric_index: u8,
122}
123
124#[derive(Clone, Debug, PartialEq)]
126#[non_exhaustive]
127pub struct NOCStruct {
128 pub noc: Vec<u8>,
130 pub icac: Nullable<Vec<u8>>,
132 pub vvsc: Option<Vec<u8>>,
134 pub fabric_index: u8,
136}
137
138#[derive(Copy, Clone, Debug, PartialEq, Eq)]
140pub enum NodeOperationalCertStatusEnum {
141 Ok,
143 InvalidPublicKey,
145 InvalidNodeOpId,
147 InvalidNoc,
149 MissingCsr,
151 TableFull,
153 InvalidAdminSubject,
155 FabricConflict,
157 LabelConflict,
159 InvalidFabricIndex,
161 Unknown(u8),
163}
164
165impl NodeOperationalCertStatusEnum {
166 #[must_use]
168 pub fn from_raw(v: u8) -> Self {
169 match v {
170 0 => Self::Ok,
171 1 => Self::InvalidPublicKey,
172 2 => Self::InvalidNodeOpId,
173 3 => Self::InvalidNoc,
174 4 => Self::MissingCsr,
175 5 => Self::TableFull,
176 6 => Self::InvalidAdminSubject,
177 9 => Self::FabricConflict,
178 10 => Self::LabelConflict,
179 11 => Self::InvalidFabricIndex,
180 other => Self::Unknown(other),
181 }
182 }
183 #[must_use]
185 pub fn to_raw(self) -> u8 {
186 match self {
187 Self::Ok => 0,
188 Self::InvalidPublicKey => 1,
189 Self::InvalidNodeOpId => 2,
190 Self::InvalidNoc => 3,
191 Self::MissingCsr => 4,
192 Self::TableFull => 5,
193 Self::InvalidAdminSubject => 6,
194 Self::FabricConflict => 9,
195 Self::LabelConflict => 10,
196 Self::InvalidFabricIndex => 11,
197 Self::Unknown(v) => v,
198 }
199 }
200}
201
202impl FabricDescriptorStruct {
203 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
209 let mut f_root_public_key: Option<Vec<u8>> = None;
210 let mut f_vendor_id: Option<u16> = None;
211 let mut f_fabric_id: Option<u64> = None;
212 let mut f_node_id: Option<u64> = None;
213 let mut f_label: Option<String> = None;
214 let mut f_vid_verification_statement: Option<Vec<u8>> = None;
215 let mut f_fabric_index: Option<u8> = None;
216 loop {
217 match r.next()? {
218 Some(Element::ContainerEnd) => break,
219 Some(Element::Scalar {
220 tag: Tag::Context(1),
221 value: Value::Bytes(v),
222 }) => f_root_public_key = Some(v),
223 Some(Element::Scalar {
224 tag: Tag::Context(2),
225 value: Value::Uint(v),
226 }) => {
227 f_vendor_id = Some(
228 u16::try_from(v).map_err(|_| ClusterError::InvalidLength("VendorId"))?,
229 )
230 }
231 Some(Element::Scalar {
232 tag: Tag::Context(3),
233 value: Value::Uint(v),
234 }) => {
235 f_fabric_id = Some(
236 u64::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricId"))?,
237 )
238 }
239 Some(Element::Scalar {
240 tag: Tag::Context(4),
241 value: Value::Uint(v),
242 }) => {
243 f_node_id =
244 Some(u64::try_from(v).map_err(|_| ClusterError::InvalidLength("NodeId"))?)
245 }
246 Some(Element::Scalar {
247 tag: Tag::Context(5),
248 value: Value::Utf8(v),
249 }) => f_label = Some(v),
250 Some(Element::Scalar {
251 tag: Tag::Context(6),
252 value: Value::Bytes(v),
253 }) => f_vid_verification_statement = Some(v),
254 Some(Element::Scalar {
255 tag: Tag::Context(254),
256 value: Value::Uint(v),
257 }) => {
258 f_fabric_index = Some(
259 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
260 )
261 }
262 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
263 Some(Element::ContainerStart { .. }) => r.skip_container()?,
264 Some(_) => {} }
266 }
267 Ok(Self {
268 root_public_key: f_root_public_key
269 .ok_or(ClusterError::MissingField("RootPublicKey"))?,
270 vendor_id: f_vendor_id.ok_or(ClusterError::MissingField("VendorId"))?,
271 fabric_id: f_fabric_id.ok_or(ClusterError::MissingField("FabricId"))?,
272 node_id: f_node_id.ok_or(ClusterError::MissingField("NodeId"))?,
273 label: f_label.ok_or(ClusterError::MissingField("Label"))?,
274 vid_verification_statement: f_vid_verification_statement,
275 fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
276 })
277 }
278 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
283 let mut r = TlvReader::new(tlv);
284 match r.next()? {
285 Some(Element::ContainerStart {
286 kind: ContainerKind::Structure,
287 ..
288 }) => {}
289 _ => {
290 return Err(ClusterError::UnexpectedType {
291 context: "FabricDescriptorStruct",
292 })
293 }
294 }
295 Self::decode_from(&mut r)
296 }
297 #[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
300 w.put_bytes(Tag::Context(1), &self.root_public_key)
301 .expect("infallible: vec writer");
302 w.put_uint(Tag::Context(2), u64::from(self.vendor_id))
303 .expect("infallible: vec writer");
304 w.put_uint(Tag::Context(3), u64::from(self.fabric_id))
305 .expect("infallible: vec writer");
306 w.put_uint(Tag::Context(4), u64::from(self.node_id))
307 .expect("infallible: vec writer");
308 w.put_utf8(Tag::Context(5), &self.label)
309 .expect("infallible: vec writer");
310 if let Some(vid_verification_statement) = &self.vid_verification_statement {
311 w.put_bytes(Tag::Context(6), &*vid_verification_statement)
312 .expect("infallible: vec writer");
313 }
314 w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
315 .expect("infallible: vec writer");
316 }
317 #[must_use]
319 #[allow(clippy::expect_used)] pub fn encode(&self) -> Vec<u8> {
321 let mut buf = Vec::new();
322 let mut w = TlvWriter::new(&mut buf);
323 w.start_structure(Tag::Anonymous)
324 .expect("infallible: vec writer");
325 self.write_fields(&mut w);
326 w.end_container().expect("infallible: vec writer");
327 buf
328 }
329}
330
331impl NOCStruct {
332 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
338 let mut f_noc: Option<Vec<u8>> = None;
339 let mut f_icac: Option<Nullable<Vec<u8>>> = None;
340 let mut f_vvsc: Option<Vec<u8>> = None;
341 let mut f_fabric_index: Option<u8> = None;
342 loop {
343 match r.next()? {
344 Some(Element::ContainerEnd) => break,
345 Some(Element::Scalar {
346 tag: Tag::Context(1),
347 value: Value::Bytes(v),
348 }) => f_noc = Some(v),
349 Some(Element::Scalar {
350 tag: Tag::Context(2),
351 value: Value::Null,
352 }) => f_icac = Some(Nullable::Null),
353 Some(Element::Scalar {
354 tag: Tag::Context(2),
355 value: Value::Bytes(v),
356 }) => f_icac = Some(Nullable::Value(v)),
357 Some(Element::Scalar {
358 tag: Tag::Context(3),
359 value: Value::Bytes(v),
360 }) => f_vvsc = Some(v),
361 Some(Element::Scalar {
362 tag: Tag::Context(254),
363 value: Value::Uint(v),
364 }) => {
365 f_fabric_index = Some(
366 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
367 )
368 }
369 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
370 Some(Element::ContainerStart { .. }) => r.skip_container()?,
371 Some(_) => {} }
373 }
374 Ok(Self {
375 noc: f_noc.ok_or(ClusterError::MissingField("Noc"))?,
376 icac: f_icac.ok_or(ClusterError::MissingField("Icac"))?,
377 vvsc: f_vvsc,
378 fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
379 })
380 }
381 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
386 let mut r = TlvReader::new(tlv);
387 match r.next()? {
388 Some(Element::ContainerStart {
389 kind: ContainerKind::Structure,
390 ..
391 }) => {}
392 _ => {
393 return Err(ClusterError::UnexpectedType {
394 context: "NOCStruct",
395 })
396 }
397 }
398 Self::decode_from(&mut r)
399 }
400 #[allow(clippy::expect_used)] pub fn write_fields(&self, w: &mut TlvWriter<'_>) {
403 w.put_bytes(Tag::Context(1), &self.noc)
404 .expect("infallible: vec writer");
405 match &self.icac {
406 Nullable::Null => w.put_null(Tag::Context(2)).expect("infallible: vec writer"),
407 Nullable::Value(icac) => {
408 w.put_bytes(Tag::Context(2), &*icac)
409 .expect("infallible: vec writer");
410 }
411 }
412 if let Some(vvsc) = &self.vvsc {
413 w.put_bytes(Tag::Context(3), &*vvsc)
414 .expect("infallible: vec writer");
415 }
416 w.put_uint(Tag::Context(254), u64::from(self.fabric_index))
417 .expect("infallible: vec writer");
418 }
419 #[must_use]
421 #[allow(clippy::expect_used)] pub fn encode(&self) -> Vec<u8> {
423 let mut buf = Vec::new();
424 let mut w = TlvWriter::new(&mut buf);
425 w.start_structure(Tag::Anonymous)
426 .expect("infallible: vec writer");
427 self.write_fields(&mut w);
428 w.end_container().expect("infallible: vec writer");
429 buf
430 }
431}
432
433pub fn decode_nocs(tlv: &[u8]) -> Result<Vec<NOCStruct>, ClusterError> {
438 let mut r = TlvReader::new(tlv);
439 match r.next()? {
440 Some(Element::ContainerStart {
441 kind: ContainerKind::Array,
442 ..
443 }) => {}
444 _ => return Err(ClusterError::UnexpectedType { context: "Nocs" }),
445 }
446 let r = &mut r;
447 let mut out = Vec::new();
448 loop {
449 match r.next()? {
450 Some(Element::ContainerEnd) => break,
451 Some(Element::ContainerStart {
452 kind: ContainerKind::Structure,
453 ..
454 }) => {
455 out.push(NOCStruct::decode_from(r)?);
456 }
457 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
458 Some(Element::ContainerStart { .. }) => r.skip_container()?,
459 Some(_) => {} }
461 }
462 Ok(out)
463}
464
465pub fn decode_fabrics(tlv: &[u8]) -> Result<Vec<FabricDescriptorStruct>, ClusterError> {
470 let mut r = TlvReader::new(tlv);
471 match r.next()? {
472 Some(Element::ContainerStart {
473 kind: ContainerKind::Array,
474 ..
475 }) => {}
476 _ => return Err(ClusterError::UnexpectedType { context: "Fabrics" }),
477 }
478 let r = &mut r;
479 let mut out = Vec::new();
480 loop {
481 match r.next()? {
482 Some(Element::ContainerEnd) => break,
483 Some(Element::ContainerStart {
484 kind: ContainerKind::Structure,
485 ..
486 }) => {
487 out.push(FabricDescriptorStruct::decode_from(r)?);
488 }
489 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
490 Some(Element::ContainerStart { .. }) => r.skip_container()?,
491 Some(_) => {} }
493 }
494 Ok(out)
495}
496
497pub fn decode_supported_fabrics(tlv: &[u8]) -> Result<u8, ClusterError> {
502 let mut r = TlvReader::new(tlv);
503 match r.next()? {
504 Some(Element::Scalar {
505 value: Value::Uint(v),
506 ..
507 }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("SupportedFabrics"))?),
508 _ => Err(ClusterError::UnexpectedType {
509 context: "SupportedFabrics",
510 }),
511 }
512}
513
514pub fn decode_commissioned_fabrics(tlv: &[u8]) -> Result<u8, ClusterError> {
519 let mut r = TlvReader::new(tlv);
520 match r.next()? {
521 Some(Element::Scalar {
522 value: Value::Uint(v),
523 ..
524 }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("CommissionedFabrics"))?),
525 _ => Err(ClusterError::UnexpectedType {
526 context: "CommissionedFabrics",
527 }),
528 }
529}
530
531pub fn decode_trusted_root_certificates(tlv: &[u8]) -> Result<Vec<Vec<u8>>, ClusterError> {
536 let mut r = TlvReader::new(tlv);
537 match r.next()? {
538 Some(Element::ContainerStart {
539 kind: ContainerKind::Array,
540 ..
541 }) => {}
542 _ => {
543 return Err(ClusterError::UnexpectedType {
544 context: "TrustedRootCertificates",
545 })
546 }
547 }
548 let r = &mut r;
549 let mut out = Vec::new();
550 loop {
551 match r.next()? {
552 Some(Element::ContainerEnd) => break,
553 Some(Element::Scalar {
554 value: Value::Bytes(v),
555 ..
556 }) => out.push(v),
557 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
558 Some(Element::ContainerStart { .. }) => r.skip_container()?,
559 Some(_) => {} }
561 }
562 Ok(out)
563}
564
565pub fn decode_current_fabric_index(tlv: &[u8]) -> Result<u8, ClusterError> {
570 let mut r = TlvReader::new(tlv);
571 match r.next()? {
572 Some(Element::Scalar {
573 value: Value::Uint(v),
574 ..
575 }) => Ok(u8::try_from(v).map_err(|_| ClusterError::InvalidLength("CurrentFabricIndex"))?),
576 _ => Err(ClusterError::UnexpectedType {
577 context: "CurrentFabricIndex",
578 }),
579 }
580}
581
582#[must_use]
584#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_attestation_request(attestation_nonce: &Vec<u8>) -> Vec<u8> {
586 let mut buf = Vec::new();
587 let mut w = TlvWriter::new(&mut buf);
588 w.start_structure(Tag::Anonymous)
589 .expect("infallible: vec writer");
590 w.put_bytes(Tag::Context(0), &attestation_nonce)
591 .expect("infallible: vec writer");
592 w.end_container().expect("infallible: vec writer");
593 buf
594}
595
596#[derive(Clone, Debug, PartialEq)]
598#[non_exhaustive]
599pub struct AttestationResponse {
600 pub attestation_elements: Vec<u8>,
602 pub attestation_signature: Vec<u8>,
604}
605
606impl AttestationResponse {
607 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
613 let mut f_attestation_elements: Option<Vec<u8>> = None;
614 let mut f_attestation_signature: Option<Vec<u8>> = None;
615 loop {
616 match r.next()? {
617 Some(Element::ContainerEnd) => break,
618 Some(Element::Scalar {
619 tag: Tag::Context(0),
620 value: Value::Bytes(v),
621 }) => f_attestation_elements = Some(v),
622 Some(Element::Scalar {
623 tag: Tag::Context(1),
624 value: Value::Bytes(v),
625 }) => f_attestation_signature = Some(v),
626 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
627 Some(Element::ContainerStart { .. }) => r.skip_container()?,
628 Some(_) => {} }
630 }
631 Ok(Self {
632 attestation_elements: f_attestation_elements
633 .ok_or(ClusterError::MissingField("AttestationElements"))?,
634 attestation_signature: f_attestation_signature
635 .ok_or(ClusterError::MissingField("AttestationSignature"))?,
636 })
637 }
638 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
643 let mut r = TlvReader::new(tlv);
644 match r.next()? {
645 Some(Element::ContainerStart {
646 kind: ContainerKind::Structure,
647 ..
648 }) => {}
649 _ => {
650 return Err(ClusterError::UnexpectedType {
651 context: "AttestationResponse",
652 })
653 }
654 }
655 Self::decode_from(&mut r)
656 }
657}
658
659#[must_use]
661#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_certificate_chain_request(certificate_type: CertificateChainTypeEnum) -> Vec<u8> {
663 let mut buf = Vec::new();
664 let mut w = TlvWriter::new(&mut buf);
665 w.start_structure(Tag::Anonymous)
666 .expect("infallible: vec writer");
667 w.put_uint(Tag::Context(0), u64::from(certificate_type.to_raw()))
668 .expect("infallible: vec writer");
669 w.end_container().expect("infallible: vec writer");
670 buf
671}
672
673#[derive(Clone, Debug, PartialEq)]
675#[non_exhaustive]
676pub struct CertificateChainResponse {
677 pub certificate: Vec<u8>,
679}
680
681impl CertificateChainResponse {
682 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
688 let mut f_certificate: Option<Vec<u8>> = None;
689 loop {
690 match r.next()? {
691 Some(Element::ContainerEnd) => break,
692 Some(Element::Scalar {
693 tag: Tag::Context(0),
694 value: Value::Bytes(v),
695 }) => f_certificate = Some(v),
696 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
697 Some(Element::ContainerStart { .. }) => r.skip_container()?,
698 Some(_) => {} }
700 }
701 Ok(Self {
702 certificate: f_certificate.ok_or(ClusterError::MissingField("Certificate"))?,
703 })
704 }
705 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
710 let mut r = TlvReader::new(tlv);
711 match r.next()? {
712 Some(Element::ContainerStart {
713 kind: ContainerKind::Structure,
714 ..
715 }) => {}
716 _ => {
717 return Err(ClusterError::UnexpectedType {
718 context: "CertificateChainResponse",
719 })
720 }
721 }
722 Self::decode_from(&mut r)
723 }
724}
725
726#[must_use]
728#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_csr_request(csr_nonce: &Vec<u8>, is_for_update_noc: Option<bool>) -> Vec<u8> {
730 let mut buf = Vec::new();
731 let mut w = TlvWriter::new(&mut buf);
732 w.start_structure(Tag::Anonymous)
733 .expect("infallible: vec writer");
734 w.put_bytes(Tag::Context(0), &csr_nonce)
735 .expect("infallible: vec writer");
736 if let Some(is_for_update_noc) = is_for_update_noc {
737 w.put_bool(Tag::Context(1), is_for_update_noc)
738 .expect("infallible: vec writer");
739 }
740 w.end_container().expect("infallible: vec writer");
741 buf
742}
743
744#[derive(Clone, Debug, PartialEq)]
746#[non_exhaustive]
747pub struct CsrResponse {
748 pub nocsr_elements: Vec<u8>,
750 pub attestation_signature: Vec<u8>,
752}
753
754impl CsrResponse {
755 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
761 let mut f_nocsr_elements: Option<Vec<u8>> = None;
762 let mut f_attestation_signature: Option<Vec<u8>> = None;
763 loop {
764 match r.next()? {
765 Some(Element::ContainerEnd) => break,
766 Some(Element::Scalar {
767 tag: Tag::Context(0),
768 value: Value::Bytes(v),
769 }) => f_nocsr_elements = Some(v),
770 Some(Element::Scalar {
771 tag: Tag::Context(1),
772 value: Value::Bytes(v),
773 }) => f_attestation_signature = Some(v),
774 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
775 Some(Element::ContainerStart { .. }) => r.skip_container()?,
776 Some(_) => {} }
778 }
779 Ok(Self {
780 nocsr_elements: f_nocsr_elements.ok_or(ClusterError::MissingField("NocsrElements"))?,
781 attestation_signature: f_attestation_signature
782 .ok_or(ClusterError::MissingField("AttestationSignature"))?,
783 })
784 }
785 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
790 let mut r = TlvReader::new(tlv);
791 match r.next()? {
792 Some(Element::ContainerStart {
793 kind: ContainerKind::Structure,
794 ..
795 }) => {}
796 _ => {
797 return Err(ClusterError::UnexpectedType {
798 context: "CsrResponse",
799 })
800 }
801 }
802 Self::decode_from(&mut r)
803 }
804}
805
806#[must_use]
808#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_add_noc(
810 noc_value: &Vec<u8>,
811 icac_value: Option<Vec<u8>>,
812 ipk_value: &Vec<u8>,
813 case_admin_subject: u64,
814 admin_vendor_id: u16,
815) -> Vec<u8> {
816 let mut buf = Vec::new();
817 let mut w = TlvWriter::new(&mut buf);
818 w.start_structure(Tag::Anonymous)
819 .expect("infallible: vec writer");
820 w.put_bytes(Tag::Context(0), &noc_value)
821 .expect("infallible: vec writer");
822 if let Some(icac_value) = icac_value {
823 w.put_bytes(Tag::Context(1), &icac_value)
824 .expect("infallible: vec writer");
825 }
826 w.put_bytes(Tag::Context(2), &ipk_value)
827 .expect("infallible: vec writer");
828 w.put_uint(Tag::Context(3), u64::from(case_admin_subject))
829 .expect("infallible: vec writer");
830 w.put_uint(Tag::Context(4), u64::from(admin_vendor_id))
831 .expect("infallible: vec writer");
832 w.end_container().expect("infallible: vec writer");
833 buf
834}
835
836#[must_use]
838#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_update_noc(noc_value: &Vec<u8>, icac_value: Option<Vec<u8>>) -> Vec<u8> {
840 let mut buf = Vec::new();
841 let mut w = TlvWriter::new(&mut buf);
842 w.start_structure(Tag::Anonymous)
843 .expect("infallible: vec writer");
844 w.put_bytes(Tag::Context(0), &noc_value)
845 .expect("infallible: vec writer");
846 if let Some(icac_value) = icac_value {
847 w.put_bytes(Tag::Context(1), &icac_value)
848 .expect("infallible: vec writer");
849 }
850 w.end_container().expect("infallible: vec writer");
851 buf
852}
853
854#[derive(Clone, Debug, PartialEq)]
856#[non_exhaustive]
857pub struct NocResponse {
858 pub status_code: NodeOperationalCertStatusEnum,
860 pub fabric_index: Option<u8>,
862 pub debug_text: Option<String>,
864}
865
866impl NocResponse {
867 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
873 let mut f_status_code: Option<NodeOperationalCertStatusEnum> = None;
874 let mut f_fabric_index: Option<u8> = None;
875 let mut f_debug_text: Option<String> = None;
876 loop {
877 match r.next()? {
878 Some(Element::ContainerEnd) => break,
879 Some(Element::Scalar {
880 tag: Tag::Context(0),
881 value: Value::Uint(v),
882 }) => {
883 f_status_code = Some(NodeOperationalCertStatusEnum::from_raw(
884 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("StatusCode"))?,
885 ))
886 }
887 Some(Element::Scalar {
888 tag: Tag::Context(1),
889 value: Value::Uint(v),
890 }) => {
891 f_fabric_index = Some(
892 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
893 )
894 }
895 Some(Element::Scalar {
896 tag: Tag::Context(2),
897 value: Value::Utf8(v),
898 }) => f_debug_text = Some(v),
899 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
900 Some(Element::ContainerStart { .. }) => r.skip_container()?,
901 Some(_) => {} }
903 }
904 Ok(Self {
905 status_code: f_status_code.ok_or(ClusterError::MissingField("StatusCode"))?,
906 fabric_index: f_fabric_index,
907 debug_text: f_debug_text,
908 })
909 }
910 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
915 let mut r = TlvReader::new(tlv);
916 match r.next()? {
917 Some(Element::ContainerStart {
918 kind: ContainerKind::Structure,
919 ..
920 }) => {}
921 _ => {
922 return Err(ClusterError::UnexpectedType {
923 context: "NocResponse",
924 })
925 }
926 }
927 Self::decode_from(&mut r)
928 }
929}
930
931#[must_use]
933#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_update_fabric_label(label: &String) -> Vec<u8> {
935 let mut buf = Vec::new();
936 let mut w = TlvWriter::new(&mut buf);
937 w.start_structure(Tag::Anonymous)
938 .expect("infallible: vec writer");
939 w.put_utf8(Tag::Context(0), &label)
940 .expect("infallible: vec writer");
941 w.end_container().expect("infallible: vec writer");
942 buf
943}
944
945#[must_use]
947#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_remove_fabric(fabric_index: u8) -> Vec<u8> {
949 let mut buf = Vec::new();
950 let mut w = TlvWriter::new(&mut buf);
951 w.start_structure(Tag::Anonymous)
952 .expect("infallible: vec writer");
953 w.put_uint(Tag::Context(0), u64::from(fabric_index))
954 .expect("infallible: vec writer");
955 w.end_container().expect("infallible: vec writer");
956 buf
957}
958
959#[must_use]
961#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_add_trusted_root_certificate(root_ca_certificate: &Vec<u8>) -> Vec<u8> {
963 let mut buf = Vec::new();
964 let mut w = TlvWriter::new(&mut buf);
965 w.start_structure(Tag::Anonymous)
966 .expect("infallible: vec writer");
967 w.put_bytes(Tag::Context(0), &root_ca_certificate)
968 .expect("infallible: vec writer");
969 w.end_container().expect("infallible: vec writer");
970 buf
971}
972
973#[must_use]
975#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_set_vid_verification_statement(
977 vendor_id: Option<u16>,
978 vid_verification_statement: Option<Vec<u8>>,
979 vvsc: Option<Vec<u8>>,
980) -> Vec<u8> {
981 let mut buf = Vec::new();
982 let mut w = TlvWriter::new(&mut buf);
983 w.start_structure(Tag::Anonymous)
984 .expect("infallible: vec writer");
985 if let Some(vendor_id) = vendor_id {
986 w.put_uint(Tag::Context(0), u64::from(vendor_id))
987 .expect("infallible: vec writer");
988 }
989 if let Some(vid_verification_statement) = vid_verification_statement {
990 w.put_bytes(Tag::Context(1), &vid_verification_statement)
991 .expect("infallible: vec writer");
992 }
993 if let Some(vvsc) = vvsc {
994 w.put_bytes(Tag::Context(2), &vvsc)
995 .expect("infallible: vec writer");
996 }
997 w.end_container().expect("infallible: vec writer");
998 buf
999}
1000
1001#[must_use]
1003#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_sign_vid_verification_request(
1005 fabric_index: u8,
1006 client_challenge: &Vec<u8>,
1007) -> Vec<u8> {
1008 let mut buf = Vec::new();
1009 let mut w = TlvWriter::new(&mut buf);
1010 w.start_structure(Tag::Anonymous)
1011 .expect("infallible: vec writer");
1012 w.put_uint(Tag::Context(0), u64::from(fabric_index))
1013 .expect("infallible: vec writer");
1014 w.put_bytes(Tag::Context(1), &client_challenge)
1015 .expect("infallible: vec writer");
1016 w.end_container().expect("infallible: vec writer");
1017 buf
1018}
1019
1020#[derive(Clone, Debug, PartialEq)]
1022#[non_exhaustive]
1023pub struct SignVidVerificationResponse {
1024 pub fabric_index: u8,
1026 pub fabric_binding_version: u8,
1028 pub signature: Vec<u8>,
1030}
1031
1032impl SignVidVerificationResponse {
1033 pub fn decode_from(r: &mut TlvReader<'_>) -> Result<Self, ClusterError> {
1039 let mut f_fabric_index: Option<u8> = None;
1040 let mut f_fabric_binding_version: Option<u8> = None;
1041 let mut f_signature: Option<Vec<u8>> = None;
1042 loop {
1043 match r.next()? {
1044 Some(Element::ContainerEnd) => break,
1045 Some(Element::Scalar {
1046 tag: Tag::Context(0),
1047 value: Value::Uint(v),
1048 }) => {
1049 f_fabric_index = Some(
1050 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("FabricIndex"))?,
1051 )
1052 }
1053 Some(Element::Scalar {
1054 tag: Tag::Context(1),
1055 value: Value::Uint(v),
1056 }) => {
1057 f_fabric_binding_version = Some(
1058 u8::try_from(v)
1059 .map_err(|_| ClusterError::InvalidLength("FabricBindingVersion"))?,
1060 )
1061 }
1062 Some(Element::Scalar {
1063 tag: Tag::Context(2),
1064 value: Value::Bytes(v),
1065 }) => f_signature = Some(v),
1066 None => return Err(ClusterError::Tlv(matter_codec::Error::UnclosedContainer)),
1067 Some(Element::ContainerStart { .. }) => r.skip_container()?,
1068 Some(_) => {} }
1070 }
1071 Ok(Self {
1072 fabric_index: f_fabric_index.ok_or(ClusterError::MissingField("FabricIndex"))?,
1073 fabric_binding_version: f_fabric_binding_version
1074 .ok_or(ClusterError::MissingField("FabricBindingVersion"))?,
1075 signature: f_signature.ok_or(ClusterError::MissingField("Signature"))?,
1076 })
1077 }
1078 pub fn decode(tlv: &[u8]) -> Result<Self, ClusterError> {
1083 let mut r = TlvReader::new(tlv);
1084 match r.next()? {
1085 Some(Element::ContainerStart {
1086 kind: ContainerKind::Structure,
1087 ..
1088 }) => {}
1089 _ => {
1090 return Err(ClusterError::UnexpectedType {
1091 context: "SignVidVerificationResponse",
1092 })
1093 }
1094 }
1095 Self::decode_from(&mut r)
1096 }
1097}