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, CoseField, 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        self.crit.retain(|&x| x != label);
159    }
160
161    fn reg_label(&mut self, label: i32, prot: bool, crit: bool) {
162        self.remove_label(label);
163        if prot {
164            self.protected.push(label);
165        } else {
166            self.unprotected.push(label);
167        }
168        if crit && !self.crit.contains(&label) {
169            self.crit.push(label);
170        }
171    }
172
173    /// Adds algorithm to the header.
174    ///
175    /// `prot` parameter is used to specify if it is to be included in protected header or not.
176    /// `crit` parameter is used to specify if this is a critical label.
177    pub fn alg(&mut self, alg: i32, prot: bool, crit: bool) {
178        self.reg_label(ALG, prot, crit);
179        self.alg = Some(alg);
180    }
181
182    /// Adds Key ID to the header.
183    ///
184    /// `prot` parameter is used to specify if it is to be included in protected header or not.
185    /// `crit` parameter is used to specify if this is a critical label.
186    pub fn kid(&mut self, kid: Vec<u8>, prot: bool, crit: bool) {
187        self.reg_label(KID, prot, crit);
188        self.kid = Some(kid);
189    }
190
191    /// Adds Initialization Vector to the header.
192    ///
193    /// `prot` parameter is used to specify if it is to be included in protected header or not.
194    /// `crit` parameter is used to specify if this is a critical label.
195    pub fn iv(&mut self, iv: Vec<u8>, prot: bool, crit: bool) {
196        self.remove_label(PARTIAL_IV);
197        self.partial_iv = None;
198        self.reg_label(IV, prot, crit);
199        self.iv = Some(iv);
200    }
201
202    /// Adds Partial Initialization Vector to the header.
203    ///
204    /// `prot` parameter is used to specify if it is to be included in protected header or not.
205    /// `crit` parameter is used to specify if this is a critical label.
206    pub fn partial_iv(&mut self, partial_iv: Vec<u8>, prot: bool, crit: bool) {
207        self.remove_label(IV);
208        self.iv = None;
209        self.reg_label(PARTIAL_IV, prot, crit);
210        self.partial_iv = Some(partial_iv);
211    }
212
213    /// Adds salt to the header.
214    ///
215    /// `prot` parameter is used to specify if it is to be included in protected header or not.
216    /// `crit` parameter is used to specify if this is a critical label.
217    pub fn salt(&mut self, salt: Vec<u8>, prot: bool, crit: bool) {
218        self.reg_label(SALT, prot, crit);
219        self.salt = Some(salt);
220    }
221
222    /// Adds content-type to the header, this can either be a text string or `u32`.
223    ///
224    /// `prot` parameter is used to specify if it is to be included in protected header or not.
225    /// `crit` parameter is used to specify if this is a critical label.
226    pub fn content_type(&mut self, content_type: ContentTypeTypes, prot: bool, crit: bool) {
227        self.reg_label(CONTENT_TYPE, prot, crit);
228        self.content_type = Some(content_type);
229    }
230
231    /// Adds a Party identity to the header.
232    ///
233    /// `prot` parameter is used to specify if it is to be included in protected header or not.
234    /// `crit` parameter is used to specify if this is a critical label.
235    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
236    pub fn party_identity(
237        &mut self,
238        identity: Vec<u8>,
239        prot: bool,
240        crit: bool,
241        u: bool,
242        include: bool,
243    ) {
244        if u {
245            if include {
246                self.reg_label(PARTY_U_IDENTITY, prot, crit);
247            }
248            self.party_u_identity = Some(identity);
249        } else {
250            if include {
251                self.reg_label(PARTY_V_IDENTITY, prot, crit);
252            }
253            self.party_v_identity = Some(identity);
254        }
255    }
256
257    /// Adds a Party nonce to the header.
258    ///
259    /// `prot` parameter is used to specify if it is to be included in protected header or not.
260    /// `crit` parameter is used to specify if this is a critical label.
261    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
262    pub fn party_nonce(&mut self, nonce: Vec<u8>, prot: bool, crit: bool, u: bool) {
263        if u {
264            self.reg_label(PARTY_U_NONCE, prot, crit);
265            self.party_u_nonce = Some(nonce);
266        } else {
267            self.reg_label(PARTY_V_NONCE, prot, crit);
268            self.party_v_nonce = Some(nonce);
269        }
270    }
271
272    /// Adds a Party Other information to the header.
273    ///
274    /// `prot` parameter is used to specify if it is to be included in protected header or not.
275    /// `crit` parameter is used to specify if this is a critical label.
276    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
277    pub fn party_other(&mut self, other: Vec<u8>, prot: bool, crit: bool, u: bool) {
278        if u {
279            self.reg_label(PARTY_U_OTHER, prot, crit);
280            self.party_u_other = Some(other);
281        } else {
282            self.reg_label(PARTY_V_OTHER, prot, crit);
283            self.party_v_other = Some(other);
284        }
285    }
286
287    /// Adds other to SuppPubInfo to the message.
288    pub fn pub_other(&mut self, other: Vec<u8>) {
289        self.pub_other = Some(other);
290    }
291
292    /// Adds SuppPrivInfo to the message.
293    pub fn priv_info(&mut self, info: Vec<u8>) {
294        self.priv_info = Some(info);
295    }
296
297    /// Adds a X509 bag of certificates.
298    ///
299    /// `prot` parameter is used to specify if it is to be included in protected header or not.
300    /// `crit` parameter is used to specify if this is a critical label.
301    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
302    pub fn x5bag(&mut self, x5bag: Vec<Vec<u8>>, prot: bool, crit: bool) {
303        self.reg_label(X5BAG, prot, crit);
304        self.x5bag = Some(x5bag);
305    }
306
307    /// Adds a X509 chain of certificates.
308    ///
309    /// `prot` parameter is used to specify if it is to be included in protected header or not.
310    /// `crit` parameter is used to specify if this is a critical label.
311    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
312    pub fn x5chain(&mut self, x5chain: Vec<Vec<u8>>, prot: bool, crit: bool) {
313        self.reg_label(X5CHAIN, prot, crit);
314        self.x5chain = Some(x5chain);
315    }
316
317    /// Adds a X509 certificate URI.
318    ///
319    /// `prot` parameter is used to specify if it is to be included in protected header or not.
320    /// `crit` parameter is used to specify if this is a critical label.
321    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
322    pub fn x5u(&mut self, x5u: String, prot: bool, crit: bool) {
323        self.reg_label(X5U, prot, crit);
324        self.x5u = Some(x5u);
325    }
326
327    /// Adds sender X509 chain of certificates for ECDH.
328    ///
329    /// `prot` parameter is used to specify if it is to be included in protected header or not.
330    /// `crit` parameter is used to specify if this is a critical label.
331    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
332    pub fn x5chain_sender(&mut self, x5chain: Vec<Vec<u8>>, prot: bool, crit: bool) {
333        self.remove_label(EPHEMERAL_KEY);
334        self.remove_label(STATIC_KEY_ID);
335        self.remove_label(STATIC_KEY);
336        self.reg_label(X5CHAIN_SENDER, prot, crit);
337        self.x5chain_sender = Some(x5chain);
338    }
339
340    /// Compute and add X509 thumbprint, by providing x509 certificate and the algorithm ID to be
341    /// used.
342    ///
343    /// `prot` parameter is used to specify if it is to be included in protected header or not.
344    /// `crit` parameter is used to specify if this is a critical label.
345    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
346    pub fn x5t(&mut self, x5: Vec<u8>, alg: i32, prot: bool, crit: bool) -> CoseResult {
347        if !HASH_ALGS.contains(&alg) {
348            return Err(CoseError::Invalid(CoseField::Alg));
349        }
350        self.reg_label(X5T, prot, crit);
351        self.x5t = Some(x5);
352        self.x5t_alg = Some(alg);
353        Ok(())
354    }
355
356    /// Adds sender X509 private key in DER format, to be used when encoding a message with ECDH.
357    ///
358    /// `prot` parameter is used to specify if it is to be included in protected header or not.
359    /// `crit` parameter is used to specify if this is a critical label.
360    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
361    pub fn x5_private(&mut self, x5: Vec<u8>) {
362        self.x5_private = x5;
363    }
364
365    /// Compute and add X509 sender thumbprint for ECDH, by providing x509 certificate and the algorithm ID to be
366    /// used.
367    ///
368    /// `prot` parameter is used to specify if it is to be included in protected header or not.
369    /// `crit` parameter is used to specify if this is a critical label.
370    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
371    pub fn x5t_sender(&mut self, x5: Vec<u8>, alg: i32, prot: bool, crit: bool) -> CoseResult {
372        if !HASH_ALGS.contains(&alg) {
373            return Err(CoseError::Invalid(CoseField::Alg));
374        }
375        self.reg_label(X5T_SENDER, prot, crit);
376        self.x5t_sender = Some(thumbprint(&x5, &alg)?);
377        self.x5t_sender_alg = Some(alg);
378        Ok(())
379    }
380
381    /// Adds sender X509 certificate URI.
382    ///
383    /// `prot` parameter is used to specify if it is to be included in protected header or not.
384    /// `crit` parameter is used to specify if this is a critical label.
385    /// `u` parameter is used to specify if this is for PartyU or not (PartyV).
386    pub fn x5u_sender(&mut self, x5u: String, prot: bool, crit: bool) {
387        self.reg_label(X5U_SENDER, prot, crit);
388        self.x5u_sender = Some(x5u);
389    }
390
391    /// Adds an Ephemeral ECDH COSE Key to the header.
392    ///
393    /// `prot` parameter is used to specify if it is to be included in protected header or not.
394    /// `crit` parameter is used to specify if this is a critical label.
395    pub fn ephemeral_key(&mut self, key: keys::CoseKey, prot: bool, crit: bool) {
396        self.remove_label(X5T_SENDER);
397        self.remove_label(STATIC_KEY_ID);
398        self.remove_label(STATIC_KEY);
399        self.static_kid = None;
400        self.reg_label(EPHEMERAL_KEY, prot, crit);
401        self.ecdh_key = key;
402    }
403
404    /// Adds an Static ECDH COSE Key to the header.
405    ///
406    /// `prot` parameter is used to specify if it is to be included in protected header or not.
407    /// `crit` parameter is used to specify if this is a critical label.
408    pub fn static_key(&mut self, key: keys::CoseKey, prot: bool, crit: bool) {
409        self.remove_label(X5T_SENDER);
410        self.remove_label(STATIC_KEY_ID);
411        self.remove_label(EPHEMERAL_KEY);
412        self.static_kid = None;
413        self.reg_label(STATIC_KEY, prot, crit);
414        self.ecdh_key = key;
415    }
416
417    /// Adds an Static ECDH COSE Key ID to the header.
418    ///
419    /// `prot` parameter is used to specify if it is to be included in protected header or not.
420    /// `crit` parameter is used to specify if this is a critical label.
421    pub fn static_key_id(&mut self, kid: Vec<u8>, key: keys::CoseKey, prot: bool, crit: bool) {
422        self.remove_label(X5T_SENDER);
423        self.remove_label(STATIC_KEY);
424        self.remove_label(EPHEMERAL_KEY);
425        self.reg_label(STATIC_KEY_ID, prot, crit);
426        self.ecdh_key = key;
427        self.static_kid = Some(kid);
428    }
429
430    /// Adds an ECDH COSE Key to the header structure (It will not be included in encoding).
431    ///
432    /// This is meant to be used when decoding a message that uses static kid.
433    pub fn ecdh_key(&mut self, key: keys::CoseKey) {
434        self.ecdh_key = key;
435    }
436
437    pub(crate) fn encode_unprotected(&mut self, encoder: &mut Encoder<Vec<u8>>) -> CoseResult {
438        encoder.object(self.unprotected.len())?;
439        for i in 0..self.unprotected.len() {
440            if !self.labels_found.contains(&self.unprotected[i]) {
441                self.labels_found.push(self.unprotected[i]);
442            } else {
443                return Err(CoseError::DuplicateLabel(self.unprotected[i]));
444            };
445            encoder.i32(self.unprotected[i])?;
446            self.encode_label(self.unprotected[i], encoder, false)?;
447        }
448        Ok(())
449    }
450
451    pub(crate) fn get_protected_bstr(&mut self, verify_label: bool) -> CoseResultWithRet<Vec<u8>> {
452        let mut ph_bstr = Vec::new();
453        let mut encoder = Encoder::new(Vec::new());
454        let prot_len = self.protected.len();
455        let crit_len = self.crit.len();
456        if crit_len > 0 || prot_len > 0 {
457            if crit_len > 0 {
458                encoder.object(prot_len + 1)?;
459                encoder.i32(CRIT)?;
460                encoder.array(crit_len)?;
461                for i in &self.crit {
462                    encoder.i32(*i)?;
463                }
464            } else {
465                encoder.object(prot_len)?;
466            }
467            for i in 0..self.protected.len() {
468                if verify_label {
469                    if !self.labels_found.contains(&self.protected[i]) {
470                        self.labels_found.push(self.protected[i]);
471                    } else {
472                        return Err(CoseError::DuplicateLabel(self.protected[i]));
473                    };
474                }
475                encoder.i32(self.protected[i])?;
476                self.encode_label(self.protected[i], &mut encoder, true)?;
477            }
478            ph_bstr = encoder.into_writer().to_vec();
479        }
480        Ok(ph_bstr)
481    }
482
483    pub(crate) fn decode_unprotected(
484        &mut self,
485        decoder: &mut Decoder<Cursor<Vec<u8>>>,
486        is_counter_sig: bool,
487    ) -> CoseResult {
488        let unprot_len = decoder.object()?;
489        self.unprotected = Vec::new();
490        for _ in 0..unprot_len {
491            let label = decoder.i32()?;
492            if !self.labels_found.contains(&label) {
493                self.labels_found.push(label);
494            } else {
495                return Err(CoseError::DuplicateLabel(label));
496            }
497            self.decode_label(label, decoder, false, is_counter_sig)?;
498        }
499        Ok(())
500    }
501
502    pub(crate) fn decode_protected_bstr(&mut self, ph_bstr: &Vec<u8>) -> CoseResult {
503        let mut decoder = Decoder::new(Config::default(), Cursor::new(ph_bstr.clone()));
504        let prot_len = decoder.object()?;
505        self.protected = Vec::new();
506        for _ in 0..prot_len {
507            let label = decoder.i32()?;
508            if !self.labels_found.contains(&label) {
509                self.labels_found.push(label);
510            } else {
511                return Err(CoseError::DuplicateLabel(label));
512            };
513            self.decode_label(label, &mut decoder, true, false)?;
514        }
515        Ok(())
516    }
517
518    fn encode_label(
519        &mut self,
520        label: i32,
521        encoder: &mut Encoder<Vec<u8>>,
522        protected: bool,
523    ) -> CoseResult {
524        match label {
525            ALG => {
526                encoder.i32(self.alg.ok_or(CoseError::Missing(CoseField::Alg))?)?;
527            }
528            KID => {
529                encoder.bytes(
530                    &self
531                        .kid
532                        .as_ref()
533                        .ok_or(CoseError::Missing(CoseField::Kid))?,
534                )?;
535            }
536            IV => {
537                encoder.bytes(&self.iv.as_ref().ok_or(CoseError::Missing(CoseField::Iv))?)?;
538            }
539            PARTIAL_IV => {
540                encoder.bytes(
541                    &self
542                        .partial_iv
543                        .as_ref()
544                        .ok_or(CoseError::Missing(CoseField::PartialIv))?,
545                )?;
546            }
547            SALT => {
548                encoder.bytes(
549                    &self
550                        .salt
551                        .as_ref()
552                        .ok_or(CoseError::Missing(CoseField::Salt))?,
553                )?;
554            }
555            CONTENT_TYPE => {
556                match &self
557                    .content_type
558                    .as_ref()
559                    .ok_or(CoseError::Missing(CoseField::ContentType))?
560                {
561                    ContentTypeTypes::Uint(v) => encoder.u32(*v)?,
562                    ContentTypeTypes::Tstr(v) => encoder.text(v)?,
563                }
564            }
565            PARTY_U_IDENTITY => {
566                encoder.bytes(
567                    &self
568                        .party_u_identity
569                        .as_ref()
570                        .ok_or(CoseError::Missing(CoseField::PartyUIdentity))?,
571                )?;
572            }
573            PARTY_U_NONCE => {
574                encoder.bytes(
575                    &self
576                        .party_u_nonce
577                        .as_ref()
578                        .ok_or(CoseError::Missing(CoseField::PartyUNonce))?,
579                )?;
580            }
581            PARTY_U_OTHER => {
582                encoder.bytes(
583                    &self
584                        .party_u_other
585                        .as_ref()
586                        .ok_or(CoseError::Missing(CoseField::PartyUOther))?,
587                )?;
588            }
589            PARTY_V_IDENTITY => {
590                encoder.bytes(
591                    &self
592                        .party_v_identity
593                        .as_ref()
594                        .ok_or(CoseError::Missing(CoseField::PartyVIdentity))?,
595                )?;
596            }
597            PARTY_V_NONCE => {
598                encoder.bytes(
599                    &self
600                        .party_v_nonce
601                        .as_ref()
602                        .ok_or(CoseError::Missing(CoseField::PartyVNonce))?,
603                )?;
604            }
605            PARTY_V_OTHER => {
606                encoder.bytes(
607                    &self
608                        .party_v_other
609                        .as_ref()
610                        .ok_or(CoseError::Missing(CoseField::PartyVOther))?,
611                )?;
612            }
613            X5BAG | X5CHAIN | X5CHAIN_SENDER => {
614                let x5;
615                if label == X5BAG {
616                    x5 = self
617                        .x5bag
618                        .as_ref()
619                        .ok_or(CoseError::Missing(CoseField::X5Bag))?;
620                } else if label == X5CHAIN {
621                    x5 = self
622                        .x5chain
623                        .as_ref()
624                        .ok_or(CoseError::Missing(CoseField::X5Chain))?;
625                } else {
626                    x5 = self
627                        .x5chain_sender
628                        .as_ref()
629                        .ok_or(CoseError::Missing(CoseField::X5ChainSender))?;
630                }
631                let x5_len = x5.len();
632                if x5_len > 0 {
633                    if x5_len == 1 {
634                        encoder.bytes(&x5[0])?;
635                    } else {
636                        if label != X5BAG {
637                            verify_chain(&x5)?;
638                        }
639                        encoder.array(x5_len)?;
640                        for x in x5 {
641                            encoder.bytes(x)?;
642                        }
643                    }
644                }
645            }
646            X5T => {
647                let x5t = self
648                    .x5t
649                    .as_ref()
650                    .ok_or(CoseError::Missing(CoseField::X5T))?;
651                let x5t_alg = self.x5t_alg.ok_or(CoseError::Missing(CoseField::X5TAlg))?;
652                if self.x5chain != None {
653                    verify_thumbprint(&self.x5chain.as_ref().unwrap()[0].clone(), &x5t, &x5t_alg)?;
654                }
655                encoder.array(2)?;
656                encoder.i32(x5t_alg)?;
657                encoder.bytes(x5t)?;
658            }
659            X5T_SENDER => {
660                let x5t_sender = self
661                    .x5t_sender
662                    .as_ref()
663                    .ok_or(CoseError::Missing(CoseField::X5TSender))?;
664                let x5t_sender_alg = self
665                    .x5t_sender_alg
666                    .ok_or(CoseError::Missing(CoseField::X5TSenderAlg))?;
667                if self.x5chain_sender != None {
668                    verify_thumbprint(
669                        &self.x5chain_sender.as_ref().unwrap()[0].clone(),
670                        &x5t_sender,
671                        &x5t_sender_alg,
672                    )?;
673                }
674                encoder.array(2)?;
675                encoder.i32(x5t_sender_alg)?;
676                encoder.bytes(x5t_sender)?;
677            }
678            X5U => {
679                encoder.text(
680                    self.x5u
681                        .as_ref()
682                        .ok_or(CoseError::Missing(CoseField::X5U))?,
683                )?;
684            }
685            X5U_SENDER => {
686                encoder.text(
687                    self.x5u_sender
688                        .as_ref()
689                        .ok_or(CoseError::Missing(CoseField::X5USender))?,
690                )?;
691            }
692            EPHEMERAL_KEY | STATIC_KEY => {
693                let mut encode_ecdh = self.ecdh_key.clone();
694                encode_ecdh.remove_label(keys::D);
695                encode_ecdh.d = None;
696                if label == EPHEMERAL_KEY {
697                    encode_ecdh.remove_label(keys::KID);
698                    encode_ecdh.kid = None;
699                }
700                encode_ecdh.encode_key(encoder)?;
701            }
702            STATIC_KEY_ID => {
703                encoder.bytes(
704                    &self
705                        .static_kid
706                        .as_ref()
707                        .ok_or(CoseError::Missing(CoseField::StaticKid))?,
708                )?;
709            }
710            COUNTER_SIG if !protected => {
711                if self.counters.len() > 1 {
712                    encoder.array(self.counters.len())?;
713                }
714                for counter in &mut self.counters {
715                    counter.encode(encoder)?;
716                }
717            }
718            _ => {
719                return Err(CoseError::InvalidLabel(label));
720            }
721        }
722        Ok(())
723    }
724
725    fn decode_label(
726        &mut self,
727        label: i32,
728        decoder: &mut Decoder<Cursor<Vec<u8>>>,
729        protected: bool,
730        is_counter_sig: bool,
731    ) -> CoseResult {
732        if protected {
733            self.protected.push(label);
734        } else {
735            self.unprotected.push(label);
736        }
737        match label {
738            ALG => {
739                let type_info = decoder.kernel().typeinfo()?;
740                if type_info.0 == Type::Text {
741                    self.alg = Some(common::get_alg_id(
742                        std::str::from_utf8(
743                            &decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?,
744                        )
745                        .unwrap()
746                        .to_string(),
747                    )?);
748                } else if common::CBOR_NUMBER_TYPES.contains(&type_info.0) {
749                    self.alg = Some(decoder.kernel().i32(&type_info)?);
750                } else {
751                    return Err(CoseError::InvalidCoseStructure());
752                }
753            }
754            CRIT if protected => {
755                self.crit = Vec::new();
756                for _ in 0..decoder.array()? {
757                    self.crit.push(decoder.i32()?);
758                }
759            }
760            CONTENT_TYPE => {
761                let type_info = decoder.kernel().typeinfo()?;
762                if type_info.0 == Type::Text {
763                    self.content_type = Some(ContentTypeTypes::Tstr(
764                        std::str::from_utf8(
765                            &decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?,
766                        )
767                        .unwrap()
768                        .to_string(),
769                    ));
770                } else if UINT.contains(&type_info.0) {
771                    self.content_type =
772                        Some(ContentTypeTypes::Uint(decoder.kernel().u32(&type_info)?));
773                } else {
774                    return Err(CoseError::InvalidCoseStructure());
775                }
776            }
777            KID => {
778                let type_info = decoder.kernel().typeinfo()?;
779                if type_info.0 == Type::Bytes {
780                    self.kid = Some(decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?);
781                } else if type_info.0 == Type::Text {
782                    self.kid = Some(decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?);
783                } else {
784                    return Err(CoseError::InvalidCoseStructure());
785                }
786            }
787            IV => {
788                self.iv = Some(decoder.bytes()?.to_vec());
789            }
790            SALT => {
791                self.salt = Some(decoder.bytes()?.to_vec());
792            }
793            PARTY_U_IDENTITY => {
794                self.party_u_identity = Some(decoder.bytes()?.to_vec());
795            }
796            PARTY_U_NONCE => {
797                self.party_u_nonce = match decoder.bytes() {
798                    Ok(value) => Some(value),
799                    Err(ref err) => match err {
800                        cbor::decoder::DecodeError::UnexpectedType { datatype, info: _ } => {
801                            if *datatype == Type::Bool {
802                                None
803                            } else {
804                                return Err(CoseError::InvalidCoseStructure());
805                            }
806                        }
807                        _ => {
808                            return Err(CoseError::InvalidCoseStructure());
809                        }
810                    },
811                };
812            }
813            PARTY_U_OTHER => {
814                self.party_u_other = Some(decoder.bytes()?.to_vec());
815            }
816            PARTY_V_IDENTITY => {
817                self.party_v_identity = Some(decoder.bytes()?.to_vec());
818            }
819            PARTY_V_NONCE => {
820                self.party_v_nonce = match decoder.bytes() {
821                    Ok(value) => Some(value),
822                    Err(ref err) => match err {
823                        cbor::decoder::DecodeError::UnexpectedType { datatype, info: _ } => {
824                            if *datatype == Type::Bool {
825                                None
826                            } else {
827                                return Err(CoseError::InvalidCoseStructure());
828                            }
829                        }
830                        _ => {
831                            return Err(CoseError::InvalidCoseStructure());
832                        }
833                    },
834                };
835            }
836            PARTY_V_OTHER => {
837                self.party_v_other = Some(decoder.bytes()?.to_vec());
838            }
839            PARTIAL_IV => {
840                self.partial_iv = Some(decoder.bytes()?.to_vec());
841            }
842            X5BAG | X5CHAIN | X5CHAIN_SENDER => {
843                let type_info = decoder.kernel().typeinfo()?;
844                if type_info.0 == Type::Array {
845                    let x5_len = type_info.1;
846                    let mut x5 = Vec::new();
847                    for _ in 0..x5_len {
848                        x5.push(decoder.bytes()?.to_vec());
849                    }
850                    if label == X5BAG {
851                        self.x5bag = Some(x5);
852                    } else if label == X5CHAIN {
853                        verify_chain(&x5)?;
854                        self.x5chain = Some(x5);
855                    } else {
856                        verify_chain(&x5)?;
857                        self.x5chain_sender = Some(x5);
858                    }
859                } else if type_info.0 == Type::Bytes {
860                    let x5 = Some(vec![decoder
861                        .kernel()
862                        .raw_data(type_info.1, common::MAX_BYTES)?]);
863                    if label == X5BAG {
864                        self.x5bag = x5;
865                    } else if label == X5CHAIN {
866                        self.x5chain = x5;
867                    } else {
868                        self.x5chain_sender = x5;
869                    }
870                } else {
871                    return Err(CoseError::InvalidCoseStructure());
872                }
873            }
874            X5T | X5T_SENDER => {
875                if decoder.array()? != 2 {
876                    return Err(CoseError::InvalidCoseStructure());
877                }
878                let type_info = decoder.kernel().typeinfo()?;
879                let x5t_alg;
880                if type_info.0 == Type::Text {
881                    x5t_alg = Some(common::get_alg_id(
882                        std::str::from_utf8(
883                            &decoder.kernel().raw_data(type_info.1, common::MAX_BYTES)?,
884                        )
885                        .unwrap()
886                        .to_string(),
887                    )?);
888                } else if common::CBOR_NUMBER_TYPES.contains(&type_info.0) {
889                    x5t_alg = Some(decoder.kernel().i32(&type_info)?);
890                } else {
891                    return Err(CoseError::InvalidCoseStructure());
892                }
893                let x5t = Some(decoder.bytes()?);
894                if label == X5T {
895                    if self.x5chain != None {
896                        verify_thumbprint(
897                            &self.x5chain.as_ref().unwrap()[0].clone(),
898                            &x5t.as_ref().unwrap(),
899                            &x5t_alg.as_ref().unwrap(),
900                        )?;
901                    }
902                    self.x5t = x5t;
903                    self.x5t_alg = x5t_alg;
904                } else {
905                    if self.x5chain_sender != None {
906                        verify_thumbprint(
907                            &self.x5chain_sender.as_ref().unwrap()[0].clone(),
908                            &x5t.as_ref().unwrap(),
909                            &x5t_alg.as_ref().unwrap(),
910                        )?;
911                    }
912                    self.x5t_sender = x5t;
913                    self.x5t_sender_alg = x5t_alg;
914                }
915            }
916            X5U => {
917                self.x5u = Some(decoder.text()?);
918            }
919            X5U_SENDER => {
920                self.x5u_sender = Some(decoder.text()?);
921            }
922            EPHEMERAL_KEY => {
923                if [X5CHAIN_SENDER, STATIC_KEY, STATIC_KEY_ID]
924                    .iter()
925                    .any(|i| self.labels_found.contains(i))
926                {
927                    return Err(CoseError::InvalidCoseStructure());
928                }
929                self.ecdh_key.decode_key(decoder)?;
930            }
931            STATIC_KEY => {
932                if [X5CHAIN_SENDER, EPHEMERAL_KEY, STATIC_KEY_ID]
933                    .iter()
934                    .any(|i| self.labels_found.contains(i))
935                {
936                    return Err(CoseError::InvalidCoseStructure());
937                }
938                self.ecdh_key.decode_key(decoder)?;
939            }
940            STATIC_KEY_ID => {
941                if [X5CHAIN_SENDER, EPHEMERAL_KEY, STATIC_KEY]
942                    .iter()
943                    .any(|i| self.labels_found.contains(i))
944                {
945                    return Err(CoseError::InvalidCoseStructure());
946                }
947                self.static_kid = Some(decoder.bytes()?.to_vec());
948            }
949            COUNTER_SIG if !is_counter_sig => {
950                let mut counter = CoseAgent::new_counter_sig();
951                let n = decoder.array()?;
952                let mut n1 = 0;
953                match decoder.bytes() {
954                    Ok(value) => {
955                        counter.ph_bstr = value;
956                    }
957                    Err(ref err) => match err {
958                        cbor::decoder::DecodeError::UnexpectedType { datatype, info } => {
959                            if *datatype == Type::Array {
960                                n1 = *info;
961                            }
962                        }
963                        _ => {
964                            return Err(CoseError::InvalidCoseStructure());
965                        }
966                    },
967                };
968                if n1 == 0 && n == 3 {
969                    counter.decode(decoder)?;
970                    self.counters.push(counter);
971                } else {
972                    counter.ph_bstr = decoder.bytes()?;
973                    counter.decode(decoder)?;
974                    self.counters.push(counter);
975                    for _ in 1..n {
976                        counter = CoseAgent::new_counter_sig();
977                        decoder.array()?;
978                        counter.ph_bstr = decoder.bytes()?;
979                        counter.decode(decoder)?;
980                        self.counters.push(counter);
981                    }
982                }
983            }
984            _ => {
985                return Err(CoseError::InvalidLabel(label));
986            }
987        }
988        Ok(())
989    }
990
991    /// Method that returns a copy of all counter signatures with the key ID provided
992    pub fn get_counter(&self, kid: &Vec<u8>) -> CoseResultWithRet<Vec<usize>> {
993        let mut counters: Vec<usize> = Vec::new();
994        for i in 0..self.counters.len() {
995            if self.counters[i]
996                .header
997                .kid
998                .as_ref()
999                .ok_or(CoseError::Missing(CoseField::Kid))?
1000                == kid
1001            {
1002                counters.push(i);
1003            }
1004        }
1005        Ok(counters)
1006    }
1007}