cose/
agent.rs

1//! Module to build recipients/signers for the various types of COSE messages.
2//!
3//! This structure is also used to build counter signatures that can be present in any type of COSE
4//! message.
5//!
6//! # Example
7//!
8//! This example shows a cose-sign1 message with 2 counter signatures present in it, one of them is
9//! counter signed externally to the crate.
10//!
11//! ## Encoding the message
12//!
13//! ```
14//! use cose::message::CoseMessage;
15//! use cose::agent::CoseAgent;
16//! use cose::keys;
17//! use cose::algs;
18//! use openssl::bn::BigNum;
19//! use openssl::bn::BigNumContext;
20//! use openssl::ec::EcPoint;
21//! use openssl::ec::{EcGroup, EcKey};
22//! use openssl::hash::MessageDigest;
23//! use openssl::pkey::PKey;
24//! use openssl::sign::{Signer, Verifier};
25//! use openssl::nid::Nid;
26//! use hex;
27//!
28//! fn main() {
29//!     let msg = b"This is the content.".to_vec();
30//!     let kid = b"kid2".to_vec();
31//!
32//!     // Prepare cose-key to encode the message
33//!     let mut key = keys::CoseKey::new();
34//!     key.kty(keys::OKP);
35//!     key.alg(algs::EDDSA);
36//!     key.crv(keys::ED25519);
37//!     key.x(hex::decode("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a").unwrap());
38//!     key.d(hex::decode("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60").unwrap());
39//!     key.key_ops(vec![keys::KEY_OPS_SIGN]);
40//!
41//!     // Prepare cose_sign1 message
42//!     let mut sign1 = CoseMessage::new_sign();
43//!     sign1.header.alg(algs::EDDSA, true, false);
44//!     sign1.payload(msg);
45//!
46//!     // Add key and generate the signature without AAD
47//!     sign1.key(&key).unwrap();
48//!     sign1.secure_content(None).unwrap();
49//!
50//!
51//!     // Prepare counter signature 1 key
52//!     let mut counter1_key = keys::CoseKey::new();
53//!     counter1_key.kty(keys::EC2);
54//!     counter1_key.alg(algs::ES256);
55//!     counter1_key.crv(keys::P_256);
56//!     counter1_key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
57//!     counter1_key.y(hex::decode("20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e").unwrap());
58//!     counter1_key.d(hex::decode("57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3").unwrap());
59//!     counter1_key.key_ops(vec![keys::KEY_OPS_SIGN]);
60//!
61//!     // Prepare counter signature 1
62//!     let mut counter1 = CoseAgent::new_counter_sig();
63//!     counter1.header.kid(vec![0], true, false);
64//!     counter1.header.alg(algs::ES256, true, false);
65//!
66//!     // Add counter signature 1 key, counter sign and add to the cose-sign1 message
67//!     counter1.key(&counter1_key).unwrap();
68//!     sign1.counter_sig(None, &mut counter1).unwrap();
69//!     sign1.add_counter_sig(counter1).unwrap();
70//!
71//!
72//!     // Prepare counter signature 2
73//!     let mut counter2 = CoseAgent::new_counter_sig();
74//!     counter2.header.alg(algs::ES256, true, false);
75//!     counter2.header.kid([3].to_vec(), true, false);
76//!
77//!     // Get content to counter sign externally
78//!     let to_sign = sign1.get_to_sign(None, &mut counter2).unwrap();
79//!
80//!     // Prepare private key to sign the content
81//!     let counter2_priv_key = hex::decode("02d1f7e6f26c43d4868d87ceb2353161740aacf1f7163647984b522a848df1c3").unwrap();
82//!
83//!     // Sign the content externally
84//!     let number = BigNum::from_slice(counter2_priv_key.as_slice()).unwrap();
85//!     let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
86//!     let ec_key = EcKey::from_private_components(&group, &number, &EcPoint::new(&group).unwrap()).unwrap();
87//!     let final_key = PKey::from_ec_key(ec_key).unwrap();
88//!     let mut signer = Signer::new(MessageDigest::sha256(), &final_key).unwrap();
89//!     signer.update(to_sign.as_slice()).unwrap();
90//!
91//!     // Add counter signature to the cose-sign1 message
92//!     counter2.add_signature(signer.sign_to_vec().unwrap()).unwrap();
93//!     sign1.add_counter_sig(counter2).unwrap();
94//!
95//!     // Encode cose-sign1 message
96//!     sign1.encode(true).unwrap();
97//! }
98//!
99//! ```
100//!
101//! ## Decoding the message
102//!
103//! ```
104//! use cose::message::CoseMessage;
105//! use cose::agent::CoseAgent;
106//! use cose::keys;
107//! use cose::algs;
108//! use openssl::bn::BigNum;
109//! use openssl::bn::BigNumContext;
110//! use openssl::ec::EcPoint;
111//! use openssl::ec::{EcGroup, EcKey};
112//! use openssl::hash::MessageDigest;
113//! use openssl::pkey::PKey;
114//! use openssl::sign::{Signer, Verifier};
115//! use openssl::nid::Nid;
116//! use hex;
117//!
118//! fn main() {
119//!
120//!     // Prepare cose-key to encode the message
121//!     let mut key = keys::CoseKey::new();
122//!     key.kty(keys::OKP);
123//!     key.alg(algs::EDDSA);
124//!     key.crv(keys::ED25519);
125//!     key.x(hex::decode("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a").unwrap());
126//!     key.key_ops(vec![keys::KEY_OPS_VERIFY]);
127//!
128//!     // Prepare CoseMessage with the cose-sign1 message to decode
129//!     let mut verify = CoseMessage::new_sign();
130//!     verify.bytes = hex::decode("d28443a10127a107828346a20441000126a058402d9410644cfe376119fcb4ff9c48ee97a14fec58e6b02fc10b61d3dc667b2fcb74ab7cce6b2303066e5440e3d5cdd5a164c4483972eba8a9d85e924384365d4d8346a20126044103a058473045022100ce59168dd9e23b229c7f9362deb0efb9c1210ae0ed3e224c968210493ed96d97022024da25640eabd57e0f306abcc9e46973d530c34d7f112eea8ab27f0464312c0c54546869732069732074686520636f6e74656e742e58406354488f9f290e36cd80e23762e664a5cb03e4267c66a8cffaef7c66d89a40bf2cbb8222432a08e5ee410d8b540c6931d26fb6af673f7e2100655d8bae765c04").unwrap();
131//!     verify.init_decoder(None).unwrap();
132//!
133//!     // Add key and decode the message
134//!     verify.key(&key).unwrap();
135//!     verify.decode(None, None).unwrap();
136//!
137//!
138//!     // Prepare counter signature 1 cose-key
139//!     let mut c1_key = keys::CoseKey::new();
140//!     c1_key.kty(keys::EC2);
141//!     c1_key.alg(algs::ES256);
142//!     c1_key.crv(keys::P_256);
143//!     c1_key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
144//!     c1_key.y(hex::decode("20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e").unwrap());
145//!     c1_key.key_ops(vec![keys::KEY_OPS_VERIFY]);
146//!
147//!     // Prepare counter signature 2 public key
148//!     let counter2_pub_key =
149//!     hex::decode("0398f50a4ff6c05861c8860d13a638ea56c3f5ad7590bbfbf054e1c7b4d91d6280").unwrap();
150//!
151//!     // Get counter signature 1 index
152//!     let mut c1 = verify.header.get_counter(&vec![0]).unwrap()[0];
153//!
154//!     // Add counter signature 1 key and verify
155//!     verify.header.counters[c1].key(&c1_key).unwrap();
156//!     verify.counters_verify(None, c1).unwrap();
157//!
158//!     // Get counter signature 2
159//!     let mut c2 = verify.header.get_counter(&vec![3]).unwrap()[0];
160//!
161//!     // Get content to verify the counter signature externally
162//!     let to_verify = verify.get_to_verify(None, &c2).unwrap();
163//!
164//!     // Verify signture externally
165//!     let mut ctx = BigNumContext::new().unwrap();
166//!     let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
167//!     let point = EcPoint::from_bytes(&group, &counter2_pub_key, &mut ctx).unwrap();
168//!     let ec_key = EcKey::from_public_key(&group, &point).unwrap();
169//!     let final_key = PKey::from_ec_key(ec_key).unwrap();
170//!     let mut verifier = Verifier::new(MessageDigest::sha256(), &final_key).unwrap();
171//!     verifier.update(&to_verify).unwrap();
172//!     assert!(verifier.verify(&verify.header.counters[c2].payload).unwrap());
173//! }
174//! ```
175
176use crate::algs;
177use crate::cose_struct;
178use crate::errors::{CoseError, CoseResult, CoseResultWithRet};
179use crate::headers::{CoseHeader, COUNTER_SIG};
180use crate::keys;
181use cbor::{Decoder, Encoder};
182use std::io::Cursor;
183
184/// COSE recipient, signer or counter-signature structure.
185#[derive(Clone)]
186pub struct CoseAgent {
187    /// Header of the CoseAgent (recipient, signer or counter-signature).
188    pub header: CoseHeader,
189    /// Payload (signature, ciphertext or MAC).
190    pub payload: Vec<u8>,
191    pub(crate) ph_bstr: Vec<u8>,
192    /// Public key.
193    pub pub_key: Vec<u8>,
194    /// Private/Symmetric key.
195    pub s_key: Vec<u8>,
196    pub(crate) context: String,
197    pub(crate) crv: Option<i32>,
198    pub(crate) key_ops: Vec<i32>,
199    pub(crate) base_iv: Option<Vec<u8>>,
200    pub(crate) enc: bool,
201}
202const KEY_OPS_SKEY: [i32; 8] = [
203    keys::KEY_OPS_DERIVE_BITS,
204    keys::KEY_OPS_DERIVE,
205    keys::KEY_OPS_DECRYPT,
206    keys::KEY_OPS_ENCRYPT,
207    keys::KEY_OPS_WRAP,
208    keys::KEY_OPS_UNWRAP,
209    keys::KEY_OPS_MAC_VERIFY,
210    keys::KEY_OPS_MAC,
211];
212
213const SIZE: usize = 3;
214
215impl CoseAgent {
216    /// Creates an empty CoseAgent structure.
217    pub fn new() -> CoseAgent {
218        CoseAgent {
219            header: CoseHeader::new(),
220            payload: Vec::new(),
221            ph_bstr: Vec::new(),
222            pub_key: Vec::new(),
223            key_ops: Vec::new(),
224            s_key: Vec::new(),
225            crv: None,
226            base_iv: None,
227            context: "".to_string(),
228            enc: false,
229        }
230    }
231
232    /// Creates an empty CoseAgent structure for counter signatures.
233    pub fn new_counter_sig() -> CoseAgent {
234        CoseAgent {
235            header: CoseHeader::new(),
236            payload: Vec::new(),
237            ph_bstr: Vec::new(),
238            pub_key: Vec::new(),
239            key_ops: Vec::new(),
240            s_key: Vec::new(),
241            crv: None,
242            base_iv: None,
243            context: cose_struct::COUNTER_SIGNATURE.to_string(),
244            enc: false,
245        }
246    }
247
248    /// Adds an [header](../headers/struct.CoseHeader.html).
249    pub fn add_header(&mut self, header: CoseHeader) {
250        self.header = header;
251    }
252
253    /// Adds a [cose-key](../keys/struct.CoseKey.html).
254    pub fn key(&mut self, key: &keys::CoseKey) -> CoseResult {
255        let alg = self.header.alg.ok_or(CoseError::MissingAlg())?;
256        key.verify_kty()?;
257        if algs::ECDH_ALGS.contains(&alg) {
258            if !keys::ECDH_KTY.contains(key.kty.as_ref().ok_or(CoseError::MissingKTY())?) {
259                return Err(CoseError::InvalidKTY());
260            }
261            if key.alg != None {
262                if key.alg.ok_or(CoseError::MissingAlg())? != alg {
263                    return Err(CoseError::AlgsDontMatch());
264                }
265            }
266        } else if (alg != algs::DIRECT
267            && !algs::A_KW.contains(&alg)
268            && !algs::RSA_OAEP.contains(&alg))
269            && key.alg.ok_or(CoseError::MissingAlg())? != alg
270        {
271            return Err(CoseError::AlgsDontMatch());
272        }
273        if algs::SIGNING_ALGS.contains(&alg) {
274            if key.key_ops.contains(&keys::KEY_OPS_SIGN) {
275                self.s_key = key.get_s_key()?;
276            }
277            if key.key_ops.contains(&keys::KEY_OPS_VERIFY) {
278                self.pub_key = key.get_pub_key()?;
279            }
280        } else if algs::KEY_DISTRIBUTION_ALGS.contains(&alg) || algs::ENCRYPT_ALGS.contains(&alg) {
281            if KEY_OPS_SKEY.iter().any(|i| key.key_ops.contains(i)) {
282                self.s_key = key.get_s_key()?;
283            }
284            if algs::ECDH_ALGS.contains(&alg) {
285                if key.key_ops.len() == 0 {
286                    self.pub_key = key.get_pub_key()?;
287                }
288            }
289        }
290        self.crv = key.crv;
291        self.base_iv = key.base_iv.clone();
292        self.key_ops = key.key_ops.clone();
293        Ok(())
294    }
295
296    pub(crate) fn enc(
297        &mut self,
298        content: &Vec<u8>,
299        external_aad: &Vec<u8>,
300        body_protected: &Vec<u8>,
301        alg: &i32,
302        iv: &Vec<u8>,
303    ) -> CoseResultWithRet<Vec<u8>> {
304        if !self.key_ops.contains(&keys::KEY_OPS_ENCRYPT) {
305            return Err(CoseError::KeyOpNotSupported());
306        }
307        Ok(cose_struct::gen_cipher(
308            &self.s_key,
309            alg,
310            iv,
311            &external_aad,
312            &self.context,
313            &body_protected,
314            &content,
315        )?)
316    }
317
318    pub(crate) fn sign(
319        &mut self,
320        content: &Vec<u8>,
321        external_aad: &Vec<u8>,
322        body_protected: &Vec<u8>,
323    ) -> CoseResult {
324        self.ph_bstr = self.header.get_protected_bstr(false)?;
325        if !self.key_ops.contains(&keys::KEY_OPS_SIGN) {
326            return Err(CoseError::KeyOpNotSupported());
327        }
328        self.payload = cose_struct::gen_sig(
329            &self.s_key,
330            &self.header.alg.ok_or(CoseError::MissingAlg())?,
331            &self.crv,
332            &external_aad,
333            &self.context,
334            &body_protected,
335            &self.ph_bstr,
336            &content,
337        )?;
338        Ok(())
339    }
340    pub(crate) fn verify(
341        &self,
342        content: &Vec<u8>,
343        external_aad: &Vec<u8>,
344        body_protected: &Vec<u8>,
345    ) -> CoseResultWithRet<bool> {
346        if !self.key_ops.contains(&keys::KEY_OPS_VERIFY) {
347            return Err(CoseError::KeyOpNotSupported());
348        }
349        Ok(cose_struct::verify_sig(
350            &self.pub_key,
351            &self.header.alg.ok_or(CoseError::MissingAlg())?,
352            &self.crv,
353            &external_aad,
354            &self.context,
355            &body_protected,
356            &self.ph_bstr,
357            &content,
358            &self.payload,
359        )?)
360    }
361
362    pub(crate) fn mac(
363        &mut self,
364        content: &Vec<u8>,
365        external_aad: &Vec<u8>,
366        body_protected: &Vec<u8>,
367    ) -> CoseResultWithRet<Vec<u8>> {
368        self.ph_bstr = self.header.get_protected_bstr(false)?;
369        if !self.key_ops.contains(&keys::KEY_OPS_MAC) {
370            return Err(CoseError::KeyOpNotSupported());
371        }
372        Ok(cose_struct::gen_mac(
373            &self.s_key,
374            &self.header.alg.ok_or(CoseError::MissingAlg())?,
375            &external_aad,
376            &self.context,
377            &body_protected,
378            &content,
379        )?)
380    }
381
382    /// Adds the counter signature to the CoseAgent.
383    ///
384    /// Function to use when signature was produce externally to the module.
385    /// This function is to use only in the context of counter signatures, not message
386    /// recipients/signers.
387    pub fn add_signature(&mut self, signature: Vec<u8>) -> CoseResult {
388        if self.context != cose_struct::COUNTER_SIGNATURE {
389            return Err(CoseError::InvalidContext());
390        }
391        self.payload = signature;
392        Ok(())
393    }
394
395    pub(crate) fn get_sign_content(
396        &mut self,
397        content: &Vec<u8>,
398        external_aad: &Vec<u8>,
399        body_protected: &Vec<u8>,
400    ) -> CoseResultWithRet<Vec<u8>> {
401        if self.context != cose_struct::COUNTER_SIGNATURE {
402            return Err(CoseError::InvalidContext());
403        }
404        self.ph_bstr = self.header.get_protected_bstr(false)?;
405        cose_struct::get_to_sign(
406            &external_aad,
407            cose_struct::COUNTER_SIGNATURE,
408            &body_protected,
409            &self.ph_bstr,
410            &content,
411        )
412    }
413
414    /// Adds a counter signature to the signer/recipient.
415    pub fn counter_sig(
416        &self,
417        external_aad: Option<Vec<u8>>,
418        counter: &mut CoseAgent,
419    ) -> CoseResult {
420        if !self.enc {
421            Err(CoseError::MissingPayload())
422        } else {
423            let aead = match external_aad {
424                None => Vec::new(),
425                Some(v) => v,
426            };
427            counter.sign(&self.payload, &aead, &self.ph_bstr)?;
428            Ok(())
429        }
430    }
431
432    /// Function to get the content to sign by the counter signature.
433    ///
434    /// This function is meant to be called if the counter signature process needs to be external
435    /// to this crate, like a timestamp authority.
436    pub fn get_to_sign(
437        &self,
438        external_aad: Option<Vec<u8>>,
439        counter: &mut CoseAgent,
440    ) -> CoseResultWithRet<Vec<u8>> {
441        if !self.enc {
442            Err(CoseError::MissingPayload())
443        } else {
444            let aead = match external_aad {
445                None => Vec::new(),
446                Some(v) => v,
447            };
448            counter.get_sign_content(&self.payload, &aead, &self.ph_bstr)
449        }
450    }
451
452    /// Function to get the content to verify with the counter signature.
453    ///
454    /// This function is meant to be called if the counter signature process needs to be external
455    /// to this crate, like a timestamp authority.
456    pub fn get_to_verify(
457        &mut self,
458        external_aad: Option<Vec<u8>>,
459        counter: &usize,
460    ) -> CoseResultWithRet<Vec<u8>> {
461        if !self.enc {
462            Err(CoseError::MissingPayload())
463        } else {
464            let aead = match external_aad {
465                None => Vec::new(),
466                Some(v) => v,
467            };
468            self.header.counters[*counter].get_sign_content(&self.payload, &aead, &self.ph_bstr)
469        }
470    }
471
472    /// Function that verifies a given counter signature on the respective signer/recipient.
473    pub fn counters_verify(&mut self, external_aad: Option<Vec<u8>>, counter: usize) -> CoseResult {
474        if !self.enc {
475            Err(CoseError::MissingPayload())
476        } else {
477            let aead = match external_aad {
478                None => Vec::new(),
479                Some(v) => v,
480            };
481            if self.header.counters[counter].verify(&self.payload, &aead, &self.ph_bstr)? {
482                Ok(())
483            } else {
484                Err(CoseError::InvalidCounterSignature())
485            }
486        }
487    }
488
489    /// Function that adds a counter signature which was signed externally with the use of
490    /// [get_to_sign](#method.get_to_sign)
491    pub fn add_counter_sig(&mut self, counter: CoseAgent) -> CoseResult {
492        if !algs::SIGNING_ALGS.contains(&counter.header.alg.ok_or(CoseError::MissingAlg())?) {
493            return Err(CoseError::InvalidAlg());
494        }
495        if counter.context != cose_struct::COUNTER_SIGNATURE {
496            return Err(CoseError::InvalidContext());
497        }
498        if self.header.unprotected.contains(&COUNTER_SIG) {
499            self.header.counters.push(counter);
500            Ok(())
501        } else {
502            self.header.counters.push(counter);
503            self.header.remove_label(COUNTER_SIG);
504            self.header.unprotected.push(COUNTER_SIG);
505            Ok(())
506        }
507    }
508
509    pub(crate) fn derive_key(
510        &mut self,
511        cek: &Vec<u8>,
512        size: usize,
513        sender: bool,
514        true_alg: &i32,
515    ) -> CoseResultWithRet<Vec<u8>> {
516        if self.ph_bstr.len() <= 0 {
517            self.ph_bstr = self.header.get_protected_bstr(false)?;
518        }
519        let alg = self.header.alg.as_ref().ok_or(CoseError::MissingAlg())?;
520        if algs::A_KW.contains(alg) {
521            if sender {
522                self.payload = algs::aes_key_wrap(&self.s_key, size, &cek)?;
523            } else {
524                return Ok(algs::aes_key_unwrap(&self.s_key, size, &cek)?);
525            }
526            return Ok(cek.to_vec());
527        } else if algs::RSA_OAEP.contains(alg) {
528            if sender {
529                self.payload = algs::rsa_oaep_enc(&self.s_key, size, &cek, alg)?;
530            } else {
531                return Ok(algs::rsa_oaep_dec(&self.s_key, size, &cek, alg)?);
532            }
533            return Ok(cek.to_vec());
534        } else if algs::D_HA.contains(alg) {
535            let mut kdf_context = cose_struct::gen_kdf(
536                true_alg,
537                &self.header.party_u_identity,
538                &self.header.party_u_nonce,
539                &self.header.party_u_other,
540                &self.header.party_v_identity,
541                &self.header.party_v_nonce,
542                &self.header.party_v_other,
543                size as u16 * 8,
544                &self.ph_bstr,
545                &self.header.pub_other,
546                &self.header.priv_info,
547            )?;
548            return Ok(algs::hkdf(
549                size,
550                &self.s_key,
551                self.header.salt.as_ref(),
552                &mut kdf_context,
553                self.header.alg.unwrap(),
554            )?);
555        } else if algs::D_HS.contains(alg) {
556            let mut kdf_context = cose_struct::gen_kdf(
557                true_alg,
558                &self.header.party_u_identity,
559                &self.header.party_u_nonce,
560                &self.header.party_u_other,
561                &self.header.party_v_identity,
562                &self.header.party_v_nonce,
563                &self.header.party_v_other,
564                size as u16 * 8,
565                &self.ph_bstr,
566                &self.header.pub_other,
567                &self.header.priv_info,
568            )?;
569            return Ok(algs::hkdf(
570                size,
571                &self.s_key,
572                self.header.salt.as_ref(),
573                &mut kdf_context,
574                self.header.alg.unwrap(),
575            )?);
576        } else if algs::ECDH_H.contains(alg) || algs::ECDH_A.contains(alg) {
577            let (receiver_key, sender_key, crv_rec, crv_send);
578            if sender {
579                if self.pub_key.len() == 0 {
580                    return Err(CoseError::MissingKey());
581                }
582                receiver_key = self.pub_key.clone();
583                if self.header.x5_private.len() > 0 {
584                    sender_key = self.header.x5_private.clone();
585                    crv_send = None;
586                } else {
587                    sender_key = self.header.ecdh_key.get_s_key()?;
588                    crv_send = Some(self.header.ecdh_key.crv.unwrap());
589                }
590                crv_rec = Some(self.crv.unwrap());
591            } else {
592                if self.s_key.len() == 0 {
593                    return Err(CoseError::MissingKey());
594                }
595                if self.header.x5chain_sender != None {
596                    algs::verify_chain(self.header.x5chain_sender.as_ref().unwrap())?;
597                    receiver_key = self.header.x5chain_sender.as_ref().unwrap()[0].clone();
598                    crv_rec = None;
599                } else {
600                    receiver_key = self.header.ecdh_key.get_pub_key()?;
601                    crv_rec = Some(self.crv.unwrap());
602                }
603                sender_key = self.s_key.clone();
604                crv_send = Some(self.crv.unwrap());
605            }
606            let shared = algs::ecdh_derive_key(crv_rec, crv_send, &receiver_key, &sender_key)?;
607
608            if algs::ECDH_H.contains(alg) {
609                let mut kdf_context = cose_struct::gen_kdf(
610                    true_alg,
611                    &self.header.party_u_identity,
612                    &self.header.party_u_nonce,
613                    &self.header.party_u_other,
614                    &self.header.party_v_identity,
615                    &self.header.party_v_nonce,
616                    &self.header.party_v_other,
617                    size as u16 * 8,
618                    &self.ph_bstr,
619                    &self.header.pub_other,
620                    &self.header.priv_info,
621                )?;
622                return Ok(algs::hkdf(
623                    size,
624                    &shared,
625                    self.header.salt.as_ref(),
626                    &mut kdf_context,
627                    self.header.alg.unwrap(),
628                )?);
629            } else {
630                let size_akw = algs::get_cek_size(&alg)?;
631
632                let alg_akw;
633                if [algs::ECDH_ES_A128KW, algs::ECDH_SS_A128KW].contains(alg) {
634                    alg_akw = algs::A128KW;
635                } else if [algs::ECDH_ES_A192KW, algs::ECDH_SS_A192KW].contains(alg) {
636                    alg_akw = algs::A192KW;
637                } else {
638                    alg_akw = algs::A256KW;
639                }
640
641                let mut kdf_context = cose_struct::gen_kdf(
642                    &alg_akw,
643                    &self.header.party_u_identity,
644                    &self.header.party_u_nonce,
645                    &self.header.party_u_other,
646                    &self.header.party_v_identity,
647                    &self.header.party_v_nonce,
648                    &self.header.party_v_other,
649                    size_akw as u16 * 8,
650                    &self.ph_bstr,
651                    &self.header.pub_other,
652                    &self.header.priv_info,
653                )?;
654                let kek = algs::hkdf(
655                    size_akw,
656                    &shared,
657                    self.header.salt.as_ref(),
658                    &mut kdf_context,
659                    self.header.alg.unwrap(),
660                )?;
661                if sender {
662                    self.payload = algs::aes_key_wrap(&kek, size, &cek)?;
663                } else {
664                    return Ok(algs::aes_key_unwrap(&kek, size, &cek)?);
665                }
666                return Ok(cek.to_vec());
667            }
668        } else {
669            return Err(CoseError::InvalidAlg());
670        }
671    }
672
673    pub(crate) fn decode(&mut self, d: &mut Decoder<Cursor<Vec<u8>>>) -> CoseResult {
674        if self.ph_bstr.len() > 0 {
675            self.header.decode_protected_bstr(&self.ph_bstr)?;
676        }
677        self.header
678            .decode_unprotected(d, self.context == cose_struct::COUNTER_SIGNATURE)?;
679        self.payload = d.bytes()?;
680        Ok(())
681    }
682
683    pub(crate) fn encode(&mut self, e: &mut Encoder<Vec<u8>>) -> CoseResult {
684        e.array(SIZE)?;
685        e.bytes(&self.ph_bstr)?;
686        self.header.encode_unprotected(e)?;
687        e.bytes(&self.payload)?;
688        Ok(())
689    }
690}