1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, serde::Serialize)]
14pub struct FabricDescriptor {
15 pub root_public_key: Option<Vec<u8>>,
16 pub vendor_id: Option<u16>,
17 pub fabric_id: Option<u8>,
18 pub node_id: Option<u64>,
19 pub label: Option<String>,
20 pub vid_verification_statement: Option<Vec<u8>>,
21}
22
23#[derive(Debug, serde::Serialize)]
24pub struct NOC {
25 pub noc: Option<Vec<u8>>,
26 pub icac: Option<Vec<u8>>,
27 pub vvsc: Option<Vec<u8>>,
28}
29
30pub fn encode_attestation_request(attestation_nonce: Vec<u8>) -> anyhow::Result<Vec<u8>> {
34 let tlv = tlv::TlvItemEnc {
35 tag: 0,
36 value: tlv::TlvItemValueEnc::StructInvisible(vec![
37 (0, tlv::TlvItemValueEnc::OctetString(attestation_nonce)).into(),
38 ]),
39 };
40 Ok(tlv.encode()?)
41}
42
43pub fn encode_certificate_chain_request(certificate_type: u8) -> anyhow::Result<Vec<u8>> {
45 let tlv = tlv::TlvItemEnc {
46 tag: 0,
47 value: tlv::TlvItemValueEnc::StructInvisible(vec![
48 (0, tlv::TlvItemValueEnc::UInt8(certificate_type)).into(),
49 ]),
50 };
51 Ok(tlv.encode()?)
52}
53
54pub fn encode_csr_request(csr_nonce: Vec<u8>, is_for_update_noc: bool) -> anyhow::Result<Vec<u8>> {
56 let tlv = tlv::TlvItemEnc {
57 tag: 0,
58 value: tlv::TlvItemValueEnc::StructInvisible(vec![
59 (0, tlv::TlvItemValueEnc::OctetString(csr_nonce)).into(),
60 (1, tlv::TlvItemValueEnc::Bool(is_for_update_noc)).into(),
61 ]),
62 };
63 Ok(tlv.encode()?)
64}
65
66pub fn encode_add_noc(noc_value: Vec<u8>, icac_value: Vec<u8>, ipk_value: Vec<u8>, case_admin_subject: u64, admin_vendor_id: u16) -> anyhow::Result<Vec<u8>> {
68 let tlv = tlv::TlvItemEnc {
69 tag: 0,
70 value: tlv::TlvItemValueEnc::StructInvisible(vec![
71 (0, tlv::TlvItemValueEnc::OctetString(noc_value)).into(),
72 (1, tlv::TlvItemValueEnc::OctetString(icac_value)).into(),
73 (2, tlv::TlvItemValueEnc::OctetString(ipk_value)).into(),
74 (3, tlv::TlvItemValueEnc::UInt64(case_admin_subject)).into(),
75 (4, tlv::TlvItemValueEnc::UInt16(admin_vendor_id)).into(),
76 ]),
77 };
78 Ok(tlv.encode()?)
79}
80
81pub fn encode_update_noc(noc_value: Vec<u8>, icac_value: Vec<u8>) -> anyhow::Result<Vec<u8>> {
83 let tlv = tlv::TlvItemEnc {
84 tag: 0,
85 value: tlv::TlvItemValueEnc::StructInvisible(vec![
86 (0, tlv::TlvItemValueEnc::OctetString(noc_value)).into(),
87 (1, tlv::TlvItemValueEnc::OctetString(icac_value)).into(),
88 ]),
89 };
90 Ok(tlv.encode()?)
91}
92
93pub fn encode_update_fabric_label(label: String) -> anyhow::Result<Vec<u8>> {
95 let tlv = tlv::TlvItemEnc {
96 tag: 0,
97 value: tlv::TlvItemValueEnc::StructInvisible(vec![
98 (0, tlv::TlvItemValueEnc::String(label)).into(),
99 ]),
100 };
101 Ok(tlv.encode()?)
102}
103
104pub fn encode_remove_fabric(fabric_index: u8) -> anyhow::Result<Vec<u8>> {
106 let tlv = tlv::TlvItemEnc {
107 tag: 0,
108 value: tlv::TlvItemValueEnc::StructInvisible(vec![
109 (0, tlv::TlvItemValueEnc::UInt8(fabric_index)).into(),
110 ]),
111 };
112 Ok(tlv.encode()?)
113}
114
115pub fn encode_add_trusted_root_certificate(root_ca_certificate: Vec<u8>) -> anyhow::Result<Vec<u8>> {
117 let tlv = tlv::TlvItemEnc {
118 tag: 0,
119 value: tlv::TlvItemValueEnc::StructInvisible(vec![
120 (0, tlv::TlvItemValueEnc::OctetString(root_ca_certificate)).into(),
121 ]),
122 };
123 Ok(tlv.encode()?)
124}
125
126pub fn encode_set_vid_verification_statement(vendor_id: u16, vid_verification_statement: Vec<u8>, vvsc: Vec<u8>) -> anyhow::Result<Vec<u8>> {
128 let tlv = tlv::TlvItemEnc {
129 tag: 0,
130 value: tlv::TlvItemValueEnc::StructInvisible(vec![
131 (0, tlv::TlvItemValueEnc::UInt16(vendor_id)).into(),
132 (1, tlv::TlvItemValueEnc::OctetString(vid_verification_statement)).into(),
133 (2, tlv::TlvItemValueEnc::OctetString(vvsc)).into(),
134 ]),
135 };
136 Ok(tlv.encode()?)
137}
138
139pub fn encode_sign_vid_verification_request(fabric_index: u8, client_challenge: Vec<u8>) -> anyhow::Result<Vec<u8>> {
141 let tlv = tlv::TlvItemEnc {
142 tag: 0,
143 value: tlv::TlvItemValueEnc::StructInvisible(vec![
144 (0, tlv::TlvItemValueEnc::UInt8(fabric_index)).into(),
145 (1, tlv::TlvItemValueEnc::OctetString(client_challenge)).into(),
146 ]),
147 };
148 Ok(tlv.encode()?)
149}
150
151pub fn decode_no_cs(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<NOC>> {
155 let mut res = Vec::new();
156 if let tlv::TlvItemValue::List(v) = inp {
157 for item in v {
158 res.push(NOC {
159 noc: item.get_octet_string_owned(&[1]),
160 icac: item.get_octet_string_owned(&[2]),
161 vvsc: item.get_octet_string_owned(&[3]),
162 });
163 }
164 }
165 Ok(res)
166}
167
168pub fn decode_fabrics(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<FabricDescriptor>> {
170 let mut res = Vec::new();
171 if let tlv::TlvItemValue::List(v) = inp {
172 for item in v {
173 res.push(FabricDescriptor {
174 root_public_key: item.get_octet_string_owned(&[1]),
175 vendor_id: item.get_int(&[2]).map(|v| v as u16),
176 fabric_id: item.get_int(&[3]).map(|v| v as u8),
177 node_id: item.get_int(&[4]),
178 label: item.get_string_owned(&[5]),
179 vid_verification_statement: item.get_octet_string_owned(&[6]),
180 });
181 }
182 }
183 Ok(res)
184}
185
186pub fn decode_supported_fabrics(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
188 if let tlv::TlvItemValue::Int(v) = inp {
189 Ok(*v as u8)
190 } else {
191 Err(anyhow::anyhow!("Expected Integer"))
192 }
193}
194
195pub fn decode_commissioned_fabrics(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
197 if let tlv::TlvItemValue::Int(v) = inp {
198 Ok(*v as u8)
199 } else {
200 Err(anyhow::anyhow!("Expected Integer"))
201 }
202}
203
204pub fn decode_trusted_root_certificates(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Vec<u8>>> {
206 let mut res = Vec::new();
207 if let tlv::TlvItemValue::List(v) = inp {
208 for item in v {
209 if let tlv::TlvItemValue::OctetString(o) = &item.value {
210 res.push(o.clone());
211 }
212 }
213 }
214 Ok(res)
215}
216
217pub fn decode_current_fabric_index(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
219 if let tlv::TlvItemValue::Int(v) = inp {
220 Ok(*v as u8)
221 } else {
222 Err(anyhow::anyhow!("Expected Integer"))
223 }
224}
225
226
227pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
239 if cluster_id != 0x003E {
241 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x003E, got {}\"}}", cluster_id);
242 }
243
244 match attribute_id {
245 0x0000 => {
246 match decode_no_cs(tlv_value) {
247 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
248 Err(e) => format!("{{\"error\": \"{}\"}}", e),
249 }
250 }
251 0x0001 => {
252 match decode_fabrics(tlv_value) {
253 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
254 Err(e) => format!("{{\"error\": \"{}\"}}", e),
255 }
256 }
257 0x0002 => {
258 match decode_supported_fabrics(tlv_value) {
259 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
260 Err(e) => format!("{{\"error\": \"{}\"}}", e),
261 }
262 }
263 0x0003 => {
264 match decode_commissioned_fabrics(tlv_value) {
265 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
266 Err(e) => format!("{{\"error\": \"{}\"}}", e),
267 }
268 }
269 0x0004 => {
270 match decode_trusted_root_certificates(tlv_value) {
271 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
272 Err(e) => format!("{{\"error\": \"{}\"}}", e),
273 }
274 }
275 0x0005 => {
276 match decode_current_fabric_index(tlv_value) {
277 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
278 Err(e) => format!("{{\"error\": \"{}\"}}", e),
279 }
280 }
281 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
282 }
283}
284
285pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
290 vec![
291 (0x0000, "NOCs"),
292 (0x0001, "Fabrics"),
293 (0x0002, "SupportedFabrics"),
294 (0x0003, "CommissionedFabrics"),
295 (0x0004, "TrustedRootCertificates"),
296 (0x0005, "CurrentFabricIndex"),
297 ]
298}
299