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}