cose/
headers.rs

1//! Module to build COSE message headers (protected and unprotected).
2use crate::agent::CoseAgent;
3use crate::algs::HASH_ALGS;
4use crate::algs::{thumbprint, verify_chain, verify_thumbprint};
5use crate::common;
6use crate::errors::{CoseError, CoseResult, CoseResultWithRet};
7use crate::keys;
8use cbor::{types::Type, Config, Decoder, Encoder};
9use std::io::Cursor;
10
11// Common headers
12pub const SALT: i32 = -20;
13pub const ALG: i32 = 1;
14pub const CRIT: i32 = 2;
15pub const CONTENT_TYPE: i32 = 3;
16pub const KID: i32 = 4;
17pub const IV: i32 = 5;
18pub const PARTIAL_IV: i32 = 6;
19pub const COUNTER_SIG: i32 = 7;
20
21// Key Distribution headers
22pub const PARTY_U_IDENTITY: i32 = -21;
23pub const PARTY_U_NONCE: i32 = -22;
24pub const PARTY_U_OTHER: i32 = -23;
25pub const PARTY_V_IDENTITY: i32 = -24;
26pub const PARTY_V_NONCE: i32 = -25;
27pub const PARTY_V_OTHER: i32 = -26;
28
29// ECDH KEY AGREEMENT headers
30pub const EPHEMERAL_KEY: i32 = -1;
31pub const STATIC_KEY: i32 = -2;
32pub const STATIC_KEY_ID: i32 = -3;
33const UINT: [Type; 4] = [Type::UInt16, Type::UInt32, Type::UInt64, Type::UInt8];
34
35// X5
36pub const X5BAG: i32 = 32;
37pub const X5CHAIN: i32 = 33;
38pub const X5T: i32 = 34;
39pub const X5U: i32 = 35;
40pub const X5T_SENDER: i32 = -27;
41pub const X5U_SENDER: i32 = -28;
42pub const X5CHAIN_SENDER: i32 = -29;
43
44/// Enum for allowing content-type to be either a `String` or a `u32` label.
45#[derive(Clone, Debug)]
46pub enum ContentTypeTypes {
47    Uint(u32),
48    Tstr(String),
49}
50
51/// Structure for COSE message headers.
52#[derive(Clone)]
53pub struct CoseHeader {
54    /// List of labels to be included in the protected header.
55    pub protected: Vec<i32>,
56    /// List of labels to be included in the unprotected header.
57    pub unprotected: Vec<i32>,
58    /// COSE Algorithm.
59    pub alg: Option<i32>,
60    /// List of critical header labels.
61    pub crit: Vec<i32>,
62    /// COSE content-type.
63    pub content_type: Option<ContentTypeTypes>,
64    /// COSE Key ID.
65    pub kid: Option<Vec<u8>>,
66    /// Initialization Vector.
67    pub iv: Option<Vec<u8>>,
68    /// Partial Initialization Vector.
69    pub partial_iv: Option<Vec<u8>>,
70    /// Salt for the key agreement algorithms.
71    pub salt: Option<Vec<u8>>,
72    /// List of COSE counter signatures.
73    pub counters: Vec<CoseAgent>,
74    /// PartyU identity for key agreement.
75    pub party_u_identity: Option<Vec<u8>>,
76    /// PartyU nonce for key agreement.
77    pub party_u_nonce: Option<Vec<u8>>,
78    /// PartyU other information for key agreement.
79    pub party_u_other: Option<Vec<u8>>,
80    /// PartyV identity for key agreement.
81    pub party_v_identity: Option<Vec<u8>>,
82    /// PartyV nonce for key agreement.
83    pub party_v_nonce: Option<Vec<u8>>,
84    /// PartyV other information for key agreement.
85    pub party_v_other: Option<Vec<u8>>,
86    /// SuppPubInfo other
87    pub pub_other: Option<Vec<u8>>,
88    /// SuppPrivInfo
89    pub priv_info: Option<Vec<u8>>,
90    /// ECDH key of the message sender.
91    pub ecdh_key: keys::CoseKey,
92    /// Static COSE ECDH key ID of the message sender.
93    pub static_kid: Option<Vec<u8>>,
94    /// X509 bag of certificates.
95    pub x5bag: Option<Vec<Vec<u8>>>,
96    /// X509 chain of certificates.
97    pub x5chain: Option<Vec<Vec<u8>>>,
98    /// End-entity x509 thumbprint.
99    pub x5t: Option<Vec<u8>>,
100    /// End-entity x509 thumbprint Hash algorithm.
101    pub x5t_alg: Option<i32>,
102    /// X509 URI.
103    pub x5u: Option<String>,
104    /// x509 sender ECDH thumbprint.
105    pub x5t_sender: Option<Vec<u8>>,
106    /// x509 sender ECDH thumbprint algorithm.
107    pub x5t_sender_alg: Option<i32>,
108    /// X509 ECDH sender URI.
109    pub x5u_sender: Option<String>,
110    /// x509 chain of certificates sender ECDH.
111    pub x5chain_sender: Option<Vec<Vec<u8>>>,
112    /// x509 private key.
113    pub x5_private: Vec<u8>,
114    pub(crate) labels_found: Vec<i32>,
115}
116
117impl CoseHeader {
118    /// Creates empty CoseHeader structure.
119    pub fn new() -> CoseHeader {
120        CoseHeader {
121            labels_found: Vec::new(),
122            unprotected: Vec::new(),
123            protected: Vec::new(),
124            counters: Vec::new(),
125            crit: Vec::new(),
126            content_type: None,
127            partial_iv: None,
128            salt: None,
129            alg: None,
130            kid: None,
131            iv: None,
132            party_u_identity: None,
133            party_v_identity: None,
134            party_u_nonce: None,
135            party_v_nonce: None,
136            party_u_other: None,
137            party_v_other: None,
138            pub_other: None,
139            priv_info: None,
140            static_kid: None,
141            x5bag: None,
142            x5chain: None,
143            x5t: None,
144            x5_private: Vec::new(),
145            x5t_alg: None,
146            x5u: None,
147            x5t_sender: None,
148            x5t_sender_alg: None,
149            x5chain_sender: None,
150            x5u_sender: None,
151            ecdh_key: keys::CoseKey::new(),
152        }
153    }
154
155    pub(crate) fn remove_label(&mut self, label: i32) {
156        self.unprotected.retain(|&x| x != label);
157        self.protected.retain(|&x| x != label);
158    }
159
160    fn reg_label(&mut self, label: i32, prot: bool, crit: bool) {
161        self.remove_label(label);
162        if prot {
163            self.protected.push(label);
164        } else {
165            self.unprotected.push(label);
166        }
167        if crit && !self.crit.contains(&label) {
168            self.crit.push(ALG);
169        }
170    }
171
172    /// Adds algorithm to the header.
173    ///
174    /// `prot` parameter is used to specify if it is to be included in protected header or not.
175    /// `crit` parameter is used to specify if this is a critical label.
176    pub fn alg(&mut self, alg: i32, prot: bool, crit: bool) {
177        self.reg_label(ALG, prot, crit);
178        self.alg = Some(alg);
179    }
180
181    /// Adds Key ID to the header.
182    ///
183    /// `prot` parameter is used to specify if it is to be included in protected header or not.
184    /// `crit` parameter is used to specify if this is a critical label.
185    pub fn kid(&mut self, kid: Vec<u8>, prot: bool, crit: bool) {
186        self.reg_label(KID, prot, crit);
187        self.kid = Some(kid);
188    }
189
190    /// Adds Initialization Vector to the header.
191    ///
192    /// `prot` parameter is used to specify if it is to be included in protected header or not.
193    /// `crit` parameter is used to specify if this is a critical label.
194    pub fn iv(&mut self, iv: Vec<u8>, prot: bool, crit: bool) {
195        self.remove_label(PARTIAL_IV);
196        self.partial_iv = None;
197        self.reg_label(IV, prot, crit);
198        self.iv = Some(iv);
199    }
200
201    /// Adds Partial Initialization Vector to the header.
202    ///
203    /// `prot` parameter is used to specify if it is to be included in protected header or not.
204    /// `crit` parameter is used to specify if this is a critical label.
205    pub fn partial_iv(&mut self, partial_iv: Vec<u8>, prot: bool, crit: bool) {
206        self.remove_label(IV);
207        self.iv = None;
208        self.reg_label(PARTIAL_IV, prot, crit);
209        self.partial_iv = Some(partial_iv);
210    }
211
212    /// Adds salt to the header.
213    ///
214    /// `prot` parameter is used to specify if it is to be included in protected header or not.
215    /// `crit` parameter is used to specify if this is a critical label.
216    pub fn salt(&mut self, salt: Vec<u8>, prot: bool, crit: bool) {
217        self.reg_label(SALT, prot, crit);
218        self.salt = Some(salt);
219    }
220
221    /// Adds content-type to the header, this can either be a text string or `u32`.
222    ///
223    /// `prot` parameter is used to specify if it is to be included in protected header or not.
224    /// `crit` parameter is used to specify if this is a critical label.
225    pub fn content_type(&mut self, content_type: ContentTypeTypes, prot: bool, crit: bool) {
226        self.reg_label(CONTENT_TYPE, prot, crit);
227        self.content_type = Some(content_type);
228    }
229
230    /// Adds a Party identity to the header.
231    ///
232    /// `prot` parameter is used to specify if it is to be included in protected header or not.
233    /// `crit` parameter is used to specify if this is a critical label.
234    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
235    pub fn party_identity(&mut self, identity: Vec<u8>, prot: bool, crit: bool, u: bool) {
236        if u {
237            self.reg_label(PARTY_U_IDENTITY, prot, crit);
238            self.party_u_identity = Some(identity);
239        } else {
240            self.reg_label(PARTY_V_IDENTITY, prot, crit);
241            self.party_v_identity = Some(identity);
242        }
243    }
244
245    /// Adds a Party nonce to the header.
246    ///
247    /// `prot` parameter is used to specify if it is to be included in protected header or not.
248    /// `crit` parameter is used to specify if this is a critical label.
249    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
250    pub fn party_nonce(&mut self, nonce: Vec<u8>, prot: bool, crit: bool, u: bool) {
251        if u {
252            self.reg_label(PARTY_U_NONCE, prot, crit);
253            self.party_u_nonce = Some(nonce);
254        } else {
255            self.reg_label(PARTY_V_NONCE, prot, crit);
256            self.party_v_nonce = Some(nonce);
257        }
258    }
259
260    /// Adds a Party Other information to the header.
261    ///
262    /// `prot` parameter is used to specify if it is to be included in protected header or not.
263    /// `crit` parameter is used to specify if this is a critical label.
264    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
265    pub fn party_other(&mut self, other: Vec<u8>, prot: bool, crit: bool, u: bool) {
266        if u {
267            self.reg_label(PARTY_U_OTHER, prot, crit);
268            self.party_u_other = Some(other);
269        } else {
270            self.reg_label(PARTY_V_OTHER, prot, crit);
271            self.party_v_other = Some(other);
272        }
273    }
274
275    /// Adds other to SuppPubInfo to the message.
276    pub fn pub_other(&mut self, other: Vec<u8>) {
277        self.pub_other = Some(other);
278    }
279
280    /// Adds SuppPrivInfo to the message.
281    pub fn priv_info(&mut self, info: Vec<u8>) {
282        self.priv_info = Some(info);
283    }
284
285    /// Adds a X509 bag of certificates.
286    ///
287    /// `prot` parameter is used to specify if it is to be included in protected header or not.
288    /// `crit` parameter is used to specify if this is a critical label.
289    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
290    pub fn x5bag(&mut self, x5bag: Vec<Vec<u8>>, prot: bool, crit: bool) {
291        self.reg_label(X5BAG, prot, crit);
292        self.x5bag = Some(x5bag);
293    }
294
295    /// Adds a X509 chain of certificates.
296    ///
297    /// `prot` parameter is used to specify if it is to be included in protected header or not.
298    /// `crit` parameter is used to specify if this is a critical label.
299    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
300    pub fn x5chain(&mut self, x5chain: Vec<Vec<u8>>, prot: bool, crit: bool) {
301        self.reg_label(X5CHAIN, prot, crit);
302        self.x5chain = Some(x5chain);
303    }
304
305    /// Adds a X509 certificate URI.
306    ///
307    /// `prot` parameter is used to specify if it is to be included in protected header or not.
308    /// `crit` parameter is used to specify if this is a critical label.
309    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
310    pub fn x5u(&mut self, x5u: String, prot: bool, crit: bool) {
311        self.reg_label(X5U, prot, crit);
312        self.x5u = Some(x5u);
313    }
314
315    /// Adds sender X509 chain of certificates for ECDH.
316    ///
317    /// `prot` parameter is used to specify if it is to be included in protected header or not.
318    /// `crit` parameter is used to specify if this is a critical label.
319    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
320    pub fn x5chain_sender(&mut self, x5chain: Vec<Vec<u8>>, prot: bool, crit: bool) {
321        self.remove_label(EPHEMERAL_KEY);
322        self.remove_label(STATIC_KEY_ID);
323        self.remove_label(STATIC_KEY);
324        self.reg_label(X5CHAIN_SENDER, prot, crit);
325        self.x5chain_sender = Some(x5chain);
326    }
327
328    /// Compute and add X509 thumbprint, by providing x509 certificate and the algorithm ID to be
329    /// used.
330    ///
331    /// `prot` parameter is used to specify if it is to be included in protected header or not.
332    /// `crit` parameter is used to specify if this is a critical label.
333    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
334    pub fn x5t(&mut self, x5: Vec<u8>, alg: i32, prot: bool, crit: bool) -> CoseResult {
335        if !HASH_ALGS.contains(&alg) {
336            return Err(CoseError::InvalidAlg());
337        }
338        self.reg_label(X5T, prot, crit);
339        self.x5t = Some(thumbprint(&x5, &alg)?);
340        self.x5t_alg = Some(alg);
341        Ok(())
342    }
343
344    /// Adds sender X509 private key in DER format, to be used when encoding a message with ECDH.
345    ///
346    /// `prot` parameter is used to specify if it is to be included in protected header or not.
347    /// `crit` parameter is used to specify if this is a critical label.
348    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
349    pub fn x5_private(&mut self, x5: Vec<u8>) {
350        self.x5_private = x5;
351    }
352
353    /// Compute and add X509 sender thumbprint for ECDH, by providing x509 certificate and the algorithm ID to be
354    /// used.
355    ///
356    /// `prot` parameter is used to specify if it is to be included in protected header or not.
357    /// `crit` parameter is used to specify if this is a critical label.
358    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
359    pub fn x5t_sender(&mut self, x5: Vec<u8>, alg: i32, prot: bool, crit: bool) -> CoseResult {
360        if !HASH_ALGS.contains(&alg) {
361            return Err(CoseError::InvalidAlg());
362        }
363        self.reg_label(X5T_SENDER, prot, crit);
364        self.x5t_sender = Some(thumbprint(&x5, &alg)?);
365        self.x5t_sender_alg = Some(alg);
366        Ok(())
367    }
368
369    /// Adds sender X509 certificate URI.
370    ///
371    /// `prot` parameter is used to specify if it is to be included in protected header or not.
372    /// `crit` parameter is used to specify if this is a critical label.
373    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
374    pub fn x5u_sender(&mut self, x5u: String, prot: bool, crit: bool) {
375        self.reg_label(X5U_SENDER, prot, crit);
376        self.x5u_sender = Some(x5u);
377    }
378
379    /// Adds an Ephemeral ECDH COSE Key to the header.
380    ///
381    /// `prot` parameter is used to specify if it is to be included in protected header or not.
382    /// `crit` parameter is used to specify if this is a critical label.
383    pub fn ephemeral_key(&mut self, key: keys::CoseKey, prot: bool, crit: bool) {
384        self.remove_label(X5T_SENDER);
385        self.remove_label(STATIC_KEY_ID);
386        self.remove_label(STATIC_KEY);
387        self.static_kid = None;
388        self.reg_label(EPHEMERAL_KEY, prot, crit);
389        self.ecdh_key = key;
390    }
391
392    /// Adds an Static ECDH COSE Key to the header.
393    ///
394    /// `prot` parameter is used to specify if it is to be included in protected header or not.
395    /// `crit` parameter is used to specify if this is a critical label.
396    pub fn static_key(&mut self, key: keys::CoseKey, prot: bool, crit: bool) {
397        self.remove_label(X5T_SENDER);
398        self.remove_label(STATIC_KEY_ID);
399        self.remove_label(EPHEMERAL_KEY);
400        self.static_kid = None;
401        self.reg_label(STATIC_KEY, prot, crit);
402        self.ecdh_key = key;
403    }
404
405    /// Adds an Static ECDH COSE Key ID to the header.
406    ///
407    /// `prot` parameter is used to specify if it is to be included in protected header or not.
408    /// `crit` parameter is used to specify if this is a critical label.
409    pub fn static_key_id(&mut self, kid: Vec<u8>, key: keys::CoseKey, prot: bool, crit: bool) {
410        self.remove_label(X5T_SENDER);
411        self.remove_label(STATIC_KEY);
412        self.remove_label(EPHEMERAL_KEY);
413        self.reg_label(STATIC_KEY_ID, prot, crit);
414        self.ecdh_key = key;
415        self.static_kid = Some(kid);
416    }
417
418    /// Adds an ECDH COSE Key to the header structure (It will not be included in encoding).
419    ///
420    /// This is meant to be used when decoding a message that uses static kid.
421    pub fn ecdh_key(&mut self, key: keys::CoseKey) {
422        self.ecdh_key = key;
423    }
424
425    pub(crate) fn encode_unprotected(&mut self, encoder: &mut Encoder<Vec<u8>>) -> CoseResult {
426        encoder.object(self.unprotected.len())?;
427        for i in 0..self.unprotected.len() {
428            if !self.labels_found.contains(&self.unprotected[i]) {
429                self.labels_found.push(self.unprotected[i]);
430            } else {
431                return Err(CoseError::DuplicateLabel(self.unprotected[i]));
432            };
433            encoder.i32(self.unprotected[i])?;
434            self.encode_label(self.unprotected[i], encoder, false)?;
435        }
436        Ok(())
437    }
438
439    pub(crate) fn get_protected_bstr(&mut self, verify_label: bool) -> CoseResultWithRet<Vec<u8>> {
440        let mut ph_bstr = Vec::new();
441        let mut encoder = Encoder::new(Vec::new());
442        let prot_len = self.protected.len();
443        let crit_len = self.crit.len();
444        if crit_len > 0 || prot_len > 0 {
445            if crit_len > 0 {
446                encoder.object(prot_len + 1)?;
447                encoder.i32(CRIT)?;
448                encoder.array(crit_len)?;
449                for i in &self.crit {
450                    encoder.i32(*i)?;
451                }
452            } else {
453                encoder.object(prot_len)?;
454            }
455            for i in 0..self.protected.len() {
456                if verify_label {
457                    if !self.labels_found.contains(&self.protected[i]) {
458                        self.labels_found.push(self.protected[i]);
459                    } else {
460                        return Err(CoseError::DuplicateLabel(self.protected[i]));
461                    };
462                }
463                encoder.i32(self.protected[i])?;
464                self.encode_label(self.protected[i], &mut encoder, true)?;
465            }
466            ph_bstr = encoder.into_writer().to_vec();
467        }
468        Ok(ph_bstr)
469    }
470
471    pub(crate) fn decode_unprotected(
472        &mut self,
473        decoder: &mut Decoder<Cursor<Vec<u8>>>,
474        is_counter_sig: bool,
475    ) -> CoseResult {
476        let unprot_len = decoder.object()?;
477        self.unprotected = Vec::new();
478        for _ in 0..unprot_len {
479            let label = decoder.i32()?;
480            if !self.labels_found.contains(&label) {
481                self.labels_found.push(label);
482            } else {
483                return Err(CoseError::DuplicateLabel(label));
484            }
485            self.decode_label(label, decoder, false, is_counter_sig)?;
486        }
487        Ok(())
488    }
489
490    pub(crate) fn decode_protected_bstr(&mut self, ph_bstr: &Vec<u8>) -> CoseResult {
491        let mut decoder = Decoder::new(Config::default(), Cursor::new(ph_bstr.clone()));
492        let prot_len = decoder.object()?;
493        self.protected = Vec::new();
494        for _ in 0..prot_len {
495            let label = decoder.i32()?;
496            if !self.labels_found.contains(&label) {
497                self.labels_found.push(label);
498            } else {
499                return Err(CoseError::DuplicateLabel(label));
500            };
501            self.decode_label(label, &mut decoder, true, false)?;
502        }
503        Ok(())
504    }
505
506    fn encode_label(
507        &mut self,
508        label: i32,
509        encoder: &mut Encoder<Vec<u8>>,
510        protected: bool,
511    ) -> CoseResult {
512        if label == ALG {
513            encoder.i32(self.alg.ok_or(CoseError::MissingAlg())?)?;
514        } else if label == KID {
515            encoder.bytes(&self.kid.as_ref().ok_or(CoseError::MissingKID())?)?;
516        } else if label == IV {
517            encoder.bytes(&self.iv.as_ref().ok_or(CoseError::MissingIV())?)?;
518        } else if label == PARTIAL_IV {
519            encoder.bytes(
520                &self
521                    .partial_iv
522                    .as_ref()
523                    .ok_or(CoseError::MissingPartialIV())?,
524            )?;
525        } else if label == SALT {
526            encoder.bytes(&self.salt.as_ref().ok_or(CoseError::MissingSalt())?)?;
527        } else if label == CONTENT_TYPE {
528            match &self
529                .content_type
530                .as_ref()
531                .ok_or(CoseError::MissingContentType())?
532            {
533                ContentTypeTypes::Uint(v) => encoder.u32(*v)?,
534                ContentTypeTypes::Tstr(v) => encoder.text(v)?,
535            }
536        } else if label == PARTY_U_IDENTITY {
537            encoder.bytes(
538                &self
539                    .party_u_identity
540                    .as_ref()
541                    .ok_or(CoseError::MissingPartyUID())?,
542            )?;
543        } else if label == PARTY_U_NONCE {
544            encoder.bytes(
545                &self
546                    .party_u_nonce
547                    .as_ref()
548                    .ok_or(CoseError::MissingPartyUNonce())?,
549            )?;
550        } else if label == PARTY_U_OTHER {
551            encoder.bytes(
552                &self
553                    .party_u_other
554                    .as_ref()
555                    .ok_or(CoseError::MissingPartyUOther())?,
556            )?;
557        } else if label == PARTY_V_IDENTITY {
558            encoder.bytes(
559                &self
560                    .party_v_identity
561                    .as_ref()
562                    .ok_or(CoseError::MissingPartyVID())?,
563            )?;
564        } else if label == PARTY_V_NONCE {
565            encoder.bytes(
566                &self
567                    .party_v_nonce
568                    .as_ref()
569                    .ok_or(CoseError::MissingPartyVNonce())?,
570            )?;
571        } else if label == PARTY_V_OTHER {
572            encoder.bytes(
573                &self
574                    .party_v_other
575                    .as_ref()
576                    .ok_or(CoseError::MissingPartyVOther())?,
577            )?;
578        } else if [X5BAG, X5CHAIN, X5CHAIN_SENDER].contains(&label) {
579            let x5;
580            if label == X5BAG {
581                x5 = self.x5bag.as_ref().ok_or(CoseError::MissingX5Bag())?;
582            } else if label == X5CHAIN {
583                x5 = self.x5chain.as_ref().ok_or(CoseError::MissingX5Chain())?;
584            } else {
585                x5 = self
586                    .x5chain_sender
587                    .as_ref()
588                    .ok_or(CoseError::MissingX5Chain())?;
589            }
590            let x5_len = x5.len();
591            if x5_len > 0 {
592                if x5_len == 1 {
593                    encoder.bytes(&x5[0])?;
594                } else {
595                    if label != X5BAG {
596                        verify_chain(&x5)?;
597                    }
598                    encoder.array(x5_len)?;
599                    for x in x5 {
600                        encoder.bytes(x)?;
601                    }
602                }
603            }
604        } else if label == X5T {
605            let x5t = self.x5t.as_ref().ok_or(CoseError::MissingX5T())?;
606            let x5t_alg = self.x5t_alg.ok_or(CoseError::MissingX5T())?;
607            if self.x5chain != None {
608                verify_thumbprint(&self.x5chain.as_ref().unwrap()[0].clone(), &x5t, &x5t_alg)?;
609            }
610            encoder.array(2)?;
611            encoder.i32(x5t_alg)?;
612            encoder.bytes(x5t)?;
613        } else if label == X5T_SENDER {
614            let x5t_sender = self
615                .x5t_sender
616                .as_ref()
617                .ok_or(CoseError::MissingX5TSender())?;
618            let x5t_sender_alg = self.x5t_sender_alg.ok_or(CoseError::MissingX5TSender())?;
619            if self.x5chain_sender != None {
620                verify_thumbprint(
621                    &self.x5chain_sender.as_ref().unwrap()[0].clone(),
622                    &x5t_sender,
623                    &x5t_sender_alg,
624                )?;
625            }
626            encoder.array(2)?;
627            encoder.i32(x5t_sender_alg)?;
628            encoder.bytes(x5t_sender)?;
629        } else if label == X5U {
630            encoder.text(self.x5u.as_ref().ok_or(CoseError::MissingX5U())?)?;
631        } else if label == X5U_SENDER {
632            encoder.text(
633                self.x5u_sender
634                    .as_ref()
635                    .ok_or(CoseError::MissingX5USender())?,
636            )?;
637        } else if label == EPHEMERAL_KEY || label == STATIC_KEY {
638            let mut encode_ecdh = self.ecdh_key.clone();
639            encode_ecdh.remove_label(keys::D);
640            encode_ecdh.d = None;
641            encode_ecdh.encode_key(encoder)?;
642        } else if label == STATIC_KEY_ID {
643            encoder.bytes(
644                &self
645                    .static_kid
646                    .as_ref()
647                    .ok_or(CoseError::MissingStaticKID())?,
648            )?;
649        } else if label == COUNTER_SIG && !protected {
650            if self.counters.len() > 1 {
651                encoder.array(self.counters.len())?;
652            }
653            for counter in &mut self.counters {
654                counter.encode(encoder)?;
655            }
656        } else {
657            return Err(CoseError::InvalidLabel(label));
658        }
659        Ok(())
660    }
661
662    fn decode_label(
663        &mut self,
664        label: i32,
665        decoder: &mut Decoder<Cursor<Vec<u8>>>,
666        protected: bool,
667        is_counter_sig: bool,
668    ) -> CoseResult {
669        if protected {
670            self.protected.push(label);
671        } else {
672            self.unprotected.push(label);
673        }
674        if label == ALG {
675            let type_info = decoder.kernel().typeinfo()?;
676            if type_info.0 == Type::Text {
677                self.alg = Some(common::get_alg_id(
678                    std::str::from_utf8(
679                        &decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?,
680                    )
681                    .unwrap()
682                    .to_string(),
683                )?);
684            } else if common::CBOR_NUMBER_TYPES.contains(&type_info.0) {
685                self.alg = Some(decoder.kernel().i32(&type_info)?);
686            } else {
687                return Err(CoseError::InvalidCoseStructure());
688            }
689        } else if label == CRIT && protected {
690            self.crit = Vec::new();
691            for _ in 0..decoder.array()? {
692                self.crit.push(decoder.i32()?);
693            }
694        } else if label == CONTENT_TYPE {
695            let type_info = decoder.kernel().typeinfo()?;
696            if type_info.0 == Type::Text {
697                self.content_type = Some(ContentTypeTypes::Tstr(
698                    std::str::from_utf8(
699                        &decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?,
700                    )
701                    .unwrap()
702                    .to_string(),
703                ));
704            } else if UINT.contains(&type_info.0) {
705                self.content_type = Some(ContentTypeTypes::Uint(decoder.kernel().u32(&type_info)?));
706            } else {
707                return Err(CoseError::InvalidCoseStructure());
708            }
709        } else if label == KID {
710            let type_info = decoder.kernel().typeinfo()?;
711            if type_info.0 == Type::Bytes {
712                self.kid = Some(decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?);
713            } else if type_info.0 == Type::Text {
714                self.kid = Some(decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?);
715            } else {
716                return Err(CoseError::InvalidCoseStructure());
717            }
718        } else if label == IV {
719            self.iv = Some(decoder.bytes()?.to_vec());
720        } else if label == SALT {
721            self.salt = Some(decoder.bytes()?.to_vec());
722        } else if label == PARTY_U_IDENTITY {
723            self.party_u_identity = Some(decoder.bytes()?.to_vec());
724        } else if label == PARTY_U_NONCE {
725            self.party_u_nonce = match decoder.bytes() {
726                Ok(value) => Some(value),
727                Err(ref err) => match err {
728                    cbor::decoder::DecodeError::UnexpectedType { datatype, info: _ } => {
729                        if *datatype == Type::Bool {
730                            None
731                        } else {
732                            return Err(CoseError::InvalidCoseStructure());
733                        }
734                    }
735                    _ => {
736                        return Err(CoseError::InvalidCoseStructure());
737                    }
738                },
739            };
740        } else if label == PARTY_U_OTHER {
741            self.party_u_other = Some(decoder.bytes()?.to_vec());
742        } else if label == PARTY_V_IDENTITY {
743            self.party_v_identity = Some(decoder.bytes()?.to_vec());
744        } else if label == PARTY_V_NONCE {
745            self.party_v_nonce = match decoder.bytes() {
746                Ok(value) => Some(value),
747                Err(ref err) => match err {
748                    cbor::decoder::DecodeError::UnexpectedType { datatype, info: _ } => {
749                        if *datatype == Type::Bool {
750                            None
751                        } else {
752                            return Err(CoseError::InvalidCoseStructure());
753                        }
754                    }
755                    _ => {
756                        return Err(CoseError::InvalidCoseStructure());
757                    }
758                },
759            };
760        } else if label == PARTY_V_OTHER {
761            self.party_v_other = Some(decoder.bytes()?.to_vec());
762        } else if label == PARTIAL_IV {
763            self.partial_iv = Some(decoder.bytes()?.to_vec());
764        } else if [X5BAG, X5CHAIN, X5CHAIN_SENDER].contains(&label) {
765            let type_info = decoder.kernel().typeinfo()?;
766            if type_info.0 == Type::Array {
767                let x5_len = type_info.1;
768                let mut x5 = Vec::new();
769                for _ in 0..x5_len {
770                    x5.push(decoder.bytes()?.to_vec());
771                }
772                if label == X5BAG {
773                    self.x5bag = Some(x5);
774                } else if label == X5CHAIN {
775                    verify_chain(&x5)?;
776                    self.x5chain = Some(x5);
777                } else {
778                    verify_chain(&x5)?;
779                    self.x5chain_sender = Some(x5);
780                }
781            } else if type_info.0 == Type::Bytes {
782                let x5 = Some(vec![decoder
783                    .kernel()
784                    .raw_data(type_info.1, common::MAX_BYTES)?]);
785                if label == X5BAG {
786                    self.x5bag = x5;
787                } else if label == X5CHAIN {
788                    self.x5chain = x5;
789                } else {
790                    self.x5chain_sender = x5;
791                }
792            } else {
793                return Err(CoseError::InvalidCoseStructure());
794            }
795        } else if [X5T, X5T_SENDER].contains(&label) {
796            if decoder.array()? != 2 {
797                return Err(CoseError::InvalidCoseStructure());
798            }
799            let type_info = decoder.kernel().typeinfo()?;
800            let x5t_alg;
801            if type_info.0 == Type::Text {
802                x5t_alg = Some(common::get_alg_id(
803                    std::str::from_utf8(
804                        &decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?,
805                    )
806                    .unwrap()
807                    .to_string(),
808                )?);
809            } else if common::CBOR_NUMBER_TYPES.contains(&type_info.0) {
810                x5t_alg = Some(decoder.kernel().i32(&type_info)?);
811            } else {
812                return Err(CoseError::InvalidCoseStructure());
813            }
814            let x5t = Some(decoder.bytes()?);
815            if label == X5T {
816                if self.x5chain != None {
817                    verify_thumbprint(
818                        &self.x5chain.as_ref().unwrap()[0].clone(),
819                        &x5t.as_ref().unwrap(),
820                        &x5t_alg.as_ref().unwrap(),
821                    )?;
822                }
823                self.x5t = x5t;
824                self.x5t_alg = x5t_alg;
825            } else {
826                if self.x5chain_sender != None {
827                    verify_thumbprint(
828                        &self.x5chain_sender.as_ref().unwrap()[0].clone(),
829                        &x5t.as_ref().unwrap(),
830                        &x5t_alg.as_ref().unwrap(),
831                    )?;
832                }
833                self.x5t_sender = x5t;
834                self.x5t_sender_alg = x5t_alg;
835            }
836        } else if label == X5U {
837            self.x5u = Some(decoder.text()?);
838        } else if label == X5U_SENDER {
839            self.x5u_sender = Some(decoder.text()?);
840        } else if label == EPHEMERAL_KEY {
841            if [X5CHAIN_SENDER, STATIC_KEY, STATIC_KEY_ID]
842                .iter()
843                .any(|i| self.labels_found.contains(i))
844            {
845                return Err(CoseError::InvalidCoseStructure());
846            }
847            self.ecdh_key.decode_key(decoder)?;
848        } else if label == STATIC_KEY {
849            if [X5CHAIN_SENDER, EPHEMERAL_KEY, STATIC_KEY_ID]
850                .iter()
851                .any(|i| self.labels_found.contains(i))
852            {
853                return Err(CoseError::InvalidCoseStructure());
854            }
855            self.ecdh_key.decode_key(decoder)?;
856        } else if label == STATIC_KEY_ID {
857            if [X5CHAIN_SENDER, EPHEMERAL_KEY, STATIC_KEY]
858                .iter()
859                .any(|i| self.labels_found.contains(i))
860            {
861                return Err(CoseError::InvalidCoseStructure());
862            }
863            self.static_kid = Some(decoder.bytes()?.to_vec());
864        } else if label == COUNTER_SIG && !is_counter_sig {
865            let mut counter = CoseAgent::new_counter_sig();
866            let n = decoder.array()?;
867            let mut n1 = 0;
868            match decoder.bytes() {
869                Ok(value) => {
870                    counter.ph_bstr = value;
871                }
872                Err(ref err) => match err {
873                    cbor::decoder::DecodeError::UnexpectedType { datatype, info } => {
874                        if *datatype == Type::Array {
875                            n1 = *info;
876                        }
877                    }
878                    _ => {
879                        return Err(CoseError::InvalidCoseStructure());
880                    }
881                },
882            };
883            if n1 == 0 && n == 3 {
884                counter.decode(decoder)?;
885                self.counters.push(counter);
886            } else {
887                counter.ph_bstr = decoder.bytes()?;
888                counter.decode(decoder)?;
889                self.counters.push(counter);
890                for _ in 1..n {
891                    counter = CoseAgent::new_counter_sig();
892                    decoder.array()?;
893                    counter.ph_bstr = decoder.bytes()?;
894                    counter.decode(decoder)?;
895                    self.counters.push(counter);
896                }
897            }
898        } else {
899            return Err(CoseError::InvalidLabel(label));
900        }
901        Ok(())
902    }
903
904    /// Method that returns a copy of all counter signatures with the key ID provided
905    pub fn get_counter(&self, kid: &Vec<u8>) -> CoseResultWithRet<Vec<usize>> {
906        let mut counters: Vec<usize> = Vec::new();
907        for i in 0..self.counters.len() {
908            if self.counters[i]
909                .header
910                .kid
911                .as_ref()
912                .ok_or(CoseError::MissingKID())?
913                == kid
914            {
915                counters.push(i);
916            }
917        }
918        Ok(counters)
919    }
920}