cose/
message.rs

1//! Module to encode/decode COSE messages.
2//!
3//! # Examples
4//!
5//! ## cose-sign1
6//!
7//! cose-sign1 message with ECDSA w/ SHA-256  algorithm
8//!
9//! ### Encode cose-sign1 message
10//! ```
11//! use cose::message::CoseMessage;
12//! use cose::keys;
13//! use cose::algs;
14//! use hex;
15//!
16//! fn main() {
17//!     let msg = b"This is the content.".to_vec();
18//!     let kid = b"11".to_vec();
19//!
20//!     // cose-key to encode the message
21//!     let mut key = keys::CoseKey::new();
22//!     key.kty(keys::EC2);
23//!     key.alg(algs::ES256);
24//!     key.crv(keys::P_256);
25//!     key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
26//!     key.y(hex::decode("20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e").unwrap());
27//!     key.d(hex::decode("57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3").unwrap());
28//!     key.key_ops(vec![keys::KEY_OPS_SIGN, keys::KEY_OPS_VERIFY]);
29//!
30//!     // Prepare cose_sign1 message
31//!     let mut sign1 = CoseMessage::new_sign();
32//!     sign1.header.alg(algs::ES256, true, false);
33//!     sign1.header.kid(kid, true, false);
34//!     sign1.payload(msg);
35//!     sign1.key(&key).unwrap();
36//!
37//!     // Generate the Signature
38//!     sign1.secure_content(None).unwrap();
39//!
40//!     // Encode the message with the payload
41//!     sign1.encode(true).unwrap();
42//! }
43//! ```
44//!
45//! ### Decode cose-sign1 message
46//! ```
47//! use cose::message::CoseMessage;
48//! use cose::keys;
49//! use cose::algs;
50//! use hex;
51//!
52//! fn main() {
53//!     // COSE_KEY to decode the message
54//!     let mut key = keys::CoseKey::new();
55//!     key.kty(keys::EC2);
56//!     key.alg(algs::ES256);
57//!     key.crv(keys::P_256);
58//!     key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
59//!     key.y(hex::decode("20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e").unwrap());
60//!     key.d(hex::decode("57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3").unwrap());
61//!     key.key_ops(vec![keys::KEY_OPS_SIGN, keys::KEY_OPS_VERIFY]);
62//!
63//!     // Generate CoseSign struct with the cose-sign1 message to decode
64//!     let mut verify = CoseMessage::new_sign();
65//!     verify.bytes =
66//!     hex::decode("d28447a2012604423131a054546869732069732074686520636f6e74656e742e5840dc93ddf7d5aff58131589087eaa65eeffa0baf2e72201ee91c0ca876ec42fdfb2a67dbc6ea1a95d2257cec645cf789808c0a392af045e2bc1bdb6746d80f221b").unwrap();
67//!
68//!     // Initial decoding
69//!     verify.init_decoder(None).unwrap();
70//!
71//!     // Add key and verify the signature
72//!     verify.key(&key).unwrap();
73//!     verify.decode(None, None).unwrap();
74//! }
75//! ```
76//!
77//! ## cose-sign
78//!
79//! Encode and decode cose-sign message with 2 signers, both using ECDSA w/ SHA-256
80//!
81//! ### Encode cose-sign message
82//! ```
83//! use cose::message::CoseMessage;
84//! use cose::keys;
85//! use cose::algs;
86//! use cose::agent::CoseAgent;
87//! use hex;
88//!
89//! fn main() {
90//!     let msg = b"This is the content.".to_vec();
91//!     let s1_kid = b"11".to_vec();
92//!     let s2_kid = b"22".to_vec();
93//!
94//!     // Prepare signer 1 key
95//!     let mut s1_key = keys::CoseKey::new();
96//!     s1_key.kty(keys::EC2);
97//!     s1_key.alg(algs::ES256);
98//!     s1_key.crv(keys::P_256);
99//!     s1_key.d(hex::decode("57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3").unwrap());
100//!     s1_key.key_ops(vec![keys::KEY_OPS_SIGN]);
101//!
102//!     // Prepare signer 2 key
103//!     let mut s2_key = keys::CoseKey::new();
104//!     s2_key.kty(keys::OKP);
105//!     s2_key.alg(algs::EDDSA);
106//!     s2_key.crv(keys::ED25519);
107//!     s2_key.d(hex::decode("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60").unwrap());
108//!     s2_key.key_ops(vec![keys::KEY_OPS_SIGN]);
109//!
110//!     // Prepare cose-sign message
111//!     let mut sign = CoseMessage::new_sign();
112//!     sign.payload(msg);
113//!
114//!     // Add signer 1
115//!     let mut signer1 = CoseAgent::new();
116//!     signer1.header.alg(algs::ES256, true, false);
117//!     signer1.header.kid(s1_kid.clone(), false, false);
118//!     signer1.key(&s1_key).unwrap();
119//!     sign.add_agent(&mut signer1).unwrap();
120//!
121//!     // Add signer 2
122//!     let mut signer2 = CoseAgent::new();
123//!     signer2.header.alg(algs::EDDSA, true, false);
124//!     signer2.header.kid(s2_kid.clone(), false, false);
125//!     signer2.key(&s2_key).unwrap();
126//!     sign.add_agent(&mut signer2).unwrap();
127//!
128//!     // Generate signature without AAD
129//!     sign.secure_content(None).unwrap();
130//!
131//!     // Encode the cose-sign message
132//!     sign.encode(true).unwrap();
133//!
134//! }
135//! ```
136//!
137//! ### Decode cose-sign message
138//! ```
139//! use cose::message::CoseMessage;
140//! use cose::keys;
141//! use cose::algs;
142//! use cose::agent::CoseAgent;
143//! use hex;
144//!
145//! fn main() {
146//!     let s1_kid = b"11".to_vec();
147//!     let s2_kid = b"22".to_vec();
148//!
149//!     // Prepare signer 1 key
150//!     let mut s1_key = keys::CoseKey::new();
151//!     s1_key.kty(keys::EC2);
152//!     s1_key.alg(algs::ES256);
153//!     s1_key.crv(keys::P_256);
154//!     s1_key.kid(b"1".to_vec());
155//!     s1_key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
156//!     s1_key.y(hex::decode("20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e").unwrap());
157//!     s1_key.key_ops(vec![keys::KEY_OPS_VERIFY]);
158//!
159//!     // Prepare signer 2 key
160//!     let mut s2_key = keys::CoseKey::new();
161//!     s2_key.kty(keys::OKP);
162//!     s2_key.alg(algs::EDDSA);
163//!     s2_key.crv(keys::ED25519);
164//!     s2_key.x(hex::decode("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a").unwrap());
165//!     s2_key.key_ops(vec![keys::KEY_OPS_VERIFY]);
166//!
167//!     // Generate CoseSign with the cose-sign message to decode
168//!     let mut verify = CoseMessage::new_sign();
169//!     verify.bytes =
170//!     hex::decode("d8628440a054546869732069732074686520636f6e74656e742e828343a10126a1044231315840a45d63392d72cfef8bd08ec6a17e40364f8b3094558f1f8078c497718de536dceadfb4a637804b31e21572ba3714e03b0b5510e243b0240c252da3a827ba4e998343a10127a104423232584081d92439ecaf31f11f611054346d50b5fbd4e5cfe00c1c237cf673fa3948678b378eacd5eecf6f680980f818a8ecc57a8b4c733ec2fd8d03ae3ba04a02ea4a06").unwrap();
171//!     verify.init_decoder(None).unwrap();
172//!
173//!     // Get signer 1 and verify
174//!     let mut index1 = verify.get_agent(&s1_kid).unwrap()[0];
175//!     verify.agents[index1].key(&s1_key).unwrap();
176//!     verify.decode(None, Some(index1)).unwrap();
177//!
178//!     // Get signer 2 and verify
179//!     let mut index2 = verify.get_agent(&s2_kid).unwrap()[0];
180//!     verify.agents[index2].key(&s2_key).unwrap();
181//!     verify.decode(None, Some(index2)).unwrap();
182//! }
183//! ```
184//! //! ## cose-encrypt0
185//!
186//! cose-encrypt0 message with ChaCha20/Poly1305 algorithm
187//!
188//! ### Encode cose-encrypt0 message
189//! ```
190//! use cose::message::CoseMessage;
191//! use cose::keys;
192//! use cose::algs;
193//! use hex;
194//!
195//! fn main() {
196//!     let msg = b"This is the content.".to_vec();
197//!     let kid = b"secret".to_vec();
198//!
199//!     // Prepare the cose-key
200//!     let mut key = keys::CoseKey::new();
201//!     key.kty(keys::SYMMETRIC);
202//!     key.alg(algs::CHACHA20);
203//!     key.k(hex::decode("849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188").unwrap());
204//!     key.key_ops(vec![keys::KEY_OPS_ENCRYPT, keys::KEY_OPS_DECRYPT]);
205//!
206//!     // Prepare cose-encrypt0 message
207//!     let mut enc0 = CoseMessage::new_encrypt();
208//!     enc0.header.alg(algs::CHACHA20, true, false);
209//!     enc0.header.iv(hex::decode("89f52f65a1c580933b5261a7").unwrap(), true, false);
210//!     enc0.payload(msg);
211//!     enc0.key(&key).unwrap();
212//!
213//!     // Generate the ciphertext with no AAD.
214//!     enc0.secure_content(None).unwrap();
215//!     // Encode the cose-encrypt0 message with the ciphertext included
216//!     enc0.encode(true).unwrap();
217//! }
218//!
219//! ```
220//!
221//! ### Decode cose-encrypt0 message
222//! ```
223//! use cose::message::CoseMessage;
224//! use cose::keys;
225//! use cose::algs;
226//! use hex;
227//!
228//! fn main() {
229//!     let expected_msg = b"This is the content.".to_vec();
230//!
231//!     // Prepare the cose-key
232//!     let mut key = keys::CoseKey::new();
233//!     key.kty(keys::SYMMETRIC);
234//!     key.alg(algs::CHACHA20);
235//!     key.k(hex::decode("849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188").unwrap());
236//!     key.key_ops(vec![keys::KEY_OPS_ENCRYPT, keys::KEY_OPS_DECRYPT]);
237//!
238//!
239//!     // Generate CoseEncrypt struct with the cose-encrypt0 message to decode
240//!     let mut dec0 = CoseMessage::new_encrypt();
241//!     dec0.bytes =
242//!     hex::decode("d08352a2011818054c89f52f65a1c580933b5261a7a0582481c32c048134989007b3b5b932811ea410eeab15bd0de5d5ac5be03c84dce8c88871d6e9").unwrap();
243//!
244//!     // Initial decoding of the message
245//!     dec0.init_decoder(None).unwrap();
246//!
247//!     // Add cose-key
248//!     dec0.key(&key).unwrap();
249//!
250//!     // Decrypt the cose-encrypt0 message
251//!     let msg = dec0.decode(None, None).unwrap();
252//!     assert_eq!(msg, expected_msg);
253//! }
254//!
255//! ```
256//!
257//! ## cose-encrypt
258//!
259//! Encode and decode cose-encrypt message with AES-GCM algorithm with 2 recipients, one using [A128KW](../algs/constant.A128KW.html) as the key agreement and the other using the [ECDH-ES +
260//! A128KW](../algs/constant.ECDH_ES_A128KW.html) key agreement.
261//!
262//! ### Encode cose-encrypt message
263//! ```
264//! use cose::message::CoseMessage;
265//! use cose::keys;
266//! use cose::headers;
267//! use cose::algs;
268//! use cose::agent::CoseAgent;
269//! use hex;
270//!
271//! fn main() {
272//!     let msg = b"This is the content.".to_vec();
273//!     let r1_kid = b"11".to_vec();
274//!     let r2_kid = b"22".to_vec();
275//!
276//!     // Prepare recipient 1 cose-key
277//!     let mut r1_key = keys::CoseKey::new();
278//!     r1_key.kty(keys::SYMMETRIC);
279//!     r1_key.alg(algs::A128KW);
280//!     r1_key.k(hex::decode("849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188").unwrap());
281//!     r1_key.key_ops(vec![keys::KEY_OPS_WRAP, keys::KEY_OPS_UNWRAP]);
282//!
283//!     // Prepare recipient 2 cose-key
284//!     let mut r2_key = keys::CoseKey::new();
285//!     r2_key.kty(keys::EC2);
286//!     r2_key.crv(keys::P_256);
287//!     r2_key.x(hex::decode("98F50A4FF6C05861C8860D13A638EA56C3F5AD7590BBFBF054E1C7B4D91D6280").unwrap());
288//!
289//!     // Prepare recipient 2 sender ephermeral ECDH key
290//!     let mut r2_eph_key = keys::CoseKey::new();
291//!     r2_eph_key.kty(keys::EC2);
292//!     r2_eph_key.crv(keys::P_256);
293//!     r2_eph_key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
294//!     r2_eph_key.d(hex::decode("57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3").unwrap());
295//!     r2_eph_key.key_ops(vec![keys::KEY_OPS_DERIVE]);
296//!
297//!     // Prepare cose-encrypt message
298//!     let mut enc = CoseMessage::new_encrypt();
299//!     enc.header.alg(algs::A256GCM, true, false);
300//!     enc.header.iv(hex::decode("89f52f65a1c580933b5261a7").unwrap(), true, false);
301//!     enc.payload(msg);
302//!
303//!     // Add recipient 1 (A128KW)
304//!     let mut recipient1 = CoseAgent::new();
305//!     recipient1.header.alg(algs::A128KW, true, false);
306//!     recipient1.header.kid(r1_kid.clone(), false, false);
307//!     recipient1.key(&r1_key).unwrap();
308//!     enc.add_agent(&mut recipient1).unwrap();
309//!
310//!     // Add recipient 2 (ECDH_ES_A128KW)
311//!     let mut recipient2 = CoseAgent::new();
312//!     recipient2.header.alg(algs::ECDH_ES_A128KW, true, false);
313//!     recipient2.header.kid(r2_kid.clone(), false, false);
314//!     recipient2.key(&r2_key).unwrap();
315//!     recipient2.header.ephemeral_key(r2_eph_key, true, false);
316//!     enc.add_agent(&mut recipient2).unwrap();
317//!
318//!     // Generate ciphertext without AAD
319//!     enc.secure_content(None).unwrap();
320//!
321//!     // Encode the cose-encrypt message
322//!     enc.encode(true).unwrap();
323//!
324//! }
325//! ```
326//!
327//! ### Decode cose-encrypt message
328//! ```
329//! use cose::message::CoseMessage;
330//! use cose::keys;
331//! use cose::headers;
332//! use cose::algs;
333//! use cose::agent::CoseAgent;
334//! use hex;
335//!
336//! fn main() {
337//!     let msg = b"This is the content.".to_vec();
338//!     let r1_kid = b"11".to_vec();
339//!     let r2_kid = b"22".to_vec();
340//!
341//!     // Prepare recipient 1 key
342//!     let mut r1_key = keys::CoseKey::new();
343//!     r1_key.kty(keys::SYMMETRIC);
344//!     r1_key.alg(algs::A128KW);
345//!     r1_key.k(hex::decode("849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188").unwrap());
346//!     r1_key.key_ops(vec![keys::KEY_OPS_WRAP, keys::KEY_OPS_UNWRAP]);
347//!
348//!     // Prepare recipient 2 key
349//!     let mut r2_key = keys::CoseKey::new();
350//!     r2_key.kty(keys::EC2);
351//!     r2_key.crv(keys::P_256);
352//!     r2_key.x(hex::decode("98F50A4FF6C05861C8860D13A638EA56C3F5AD7590BBFBF054E1C7B4D91D6280").unwrap());
353//!     r2_key.y(hex::decode("F01400B089867804B8E9FC96C3932161F1934F4223069170D924B7E03BF822BB").unwrap());
354//!     r2_key.d(hex::decode("02D1F7E6F26C43D4868D87CEB2353161740AACF1F7163647984B522A848DF1C3").unwrap());
355//!     r2_key.key_ops(vec![keys::KEY_OPS_DERIVE]);
356//!
357//!     // Generate CoseEncrypt struct with the cose-encrypt message to decode
358//!     let mut dec = CoseMessage::new_encrypt();
359//!     dec.bytes =
360//!     hex::decode("d8608451a20103054c89f52f65a1c580933b5261a7a058243e102aa2950238585d10e72c9d485352814e3ce00ac7482fb08538225622248e4daa3d06828343a10122a104423131582800e14bb6ac7246738dc6cd8232340fb37623c7a2667e474a0c56cc6f742f2d3f15969b5c58351fea835832a201381c20a5010203262001215820bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff048107a1044232325828f9b936b424c591bd5491916e98e4d6d71a4ea6fdf6a2c193718825787fac8d4c1df2c4f8473243c9").unwrap();
361//!     dec.init_decoder(None).unwrap();
362//!
363//!     // Get recipient 1 and decode message
364//!     let mut r1_i = dec.get_agent(&r1_kid).unwrap()[0];
365//!     dec.agents[r1_i].key(&r1_key).unwrap();
366//!     let resp = dec.decode(None, Some(r1_i)).unwrap();
367//!     assert_eq!(resp, msg);
368//!
369//!     // Get recipient 2 and decode message
370//!     let mut r2_i = dec.get_agent(&r2_kid).unwrap()[0];
371//!     dec.agents[r2_i].key(&r2_key).unwrap();
372//!     let resp2 = dec.decode(None, Some(r2_i)).unwrap();
373//!     assert_eq!(resp2, msg);
374//! }
375//! ```
376//! //! ## cose-mac0
377//!
378//! Encode and decode cose-mac0 message with AES-MAC algorithm
379//!
380//! ### Encode cose-mac0 message
381//! ```
382//! use cose::message::CoseMessage;
383//! use cose::keys;
384//! use cose::algs;
385//! use hex;
386//!
387//! fn main() {
388//!     let msg = b"This is the content.".to_vec();
389//!
390//!     // Prepare the cose-key
391//!     let mut key = keys::CoseKey::new();
392//!     key.kty(keys::SYMMETRIC);
393//!     key.alg(algs::AES_MAC_256_128);
394//!     key.k(hex::decode("849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188").unwrap());
395//!     key.key_ops(vec![keys::KEY_OPS_MAC, keys::KEY_OPS_MAC_VERIFY]);
396//!
397//!     // Prepare the cose-mac0 message
398//!     let mut mac0 = CoseMessage::new_mac();
399//!     mac0.header.alg(algs::AES_MAC_256_128, true, false);
400//!
401//!     // Add the payload
402//!     mac0.payload(msg);
403//!
404//!     // Add cose-key
405//!     mac0.key(&key).unwrap();
406//!
407//!     // Generate MAC tag without AAD
408//!     mac0.secure_content(None).unwrap();
409//!     // Encode the cose-mac0 message with the payload included
410//!     mac0.encode(true).unwrap();
411//!
412//! }
413//! ```
414//!
415//! ### Decode cose-mac0 message
416//! ```
417//! use cose::message::CoseMessage;
418//! use cose::keys;
419//! use cose::algs;
420//! use hex;
421//!
422//! fn main() {
423//!     // Prepare the cose-key
424//!     let mut key = keys::CoseKey::new();
425//!     key.kty(keys::SYMMETRIC);
426//!     key.alg(algs::AES_MAC_256_128);
427//!     key.k(hex::decode("849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188").unwrap());
428//!     key.key_ops(vec![keys::KEY_OPS_MAC, keys::KEY_OPS_MAC_VERIFY]);
429//!
430//!     // Generate CoseMAC struct with the cose-mac0 message to decode
431//!     let mut verify = CoseMessage::new_mac();
432//!     verify.bytes =
433//!     hex::decode("d18444a101181aa054546869732069732074686520636f6e74656e742e50403152cc208c1d501e1dc2a789ae49e4").unwrap();
434//!
435//!     // Initial decoding of the message
436//!     verify.init_decoder(None).unwrap();
437//!
438//!     // Add cose-key
439//!     verify.key(&key).unwrap();
440//!     // Verify the MAC tag of the cose-mac0 message
441//!     verify.decode(None, None).unwrap();
442//! }
443//! ```
444//!
445//! ## MAC
446//!
447//! Encode and decode cose-mac message with AES-MAC algorithm with 2 recipients, one using [A128KW](../algs/constant.A128KW.html) as the key agreement and the other using the [ECDH-ES +
448//! A128KW](../algs/constant.ECDH_ES_A128KW.html) key agreement.
449//!
450//! ### Encode cose-mac message
451//!
452//! ```
453//! use cose::message::CoseMessage;
454//! use cose::keys;
455//! use cose::algs;
456//! use cose::agent::CoseAgent;
457//! use hex;
458//!
459//! fn main() {
460//!     let msg = b"This is the content.".to_vec();
461//!     let r1_kid = b"11".to_vec();
462//!     let r2_kid = b"22".to_vec();
463//!
464//!     // Prepare recipient 1 cose-key
465//!     let mut r1_key = keys::CoseKey::new();
466//!     r1_key.kty(keys::SYMMETRIC);
467//!     r1_key.alg(algs::A128KW);
468//!     r1_key.k(hex::decode("849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188").unwrap());
469//!     r1_key.key_ops(vec![keys::KEY_OPS_WRAP, keys::KEY_OPS_UNWRAP]);
470//!
471//!     // Prepare recipient 2 cose-key
472//!     let mut r2_key = keys::CoseKey::new();
473//!     r2_key.kty(keys::EC2);
474//!     r2_key.crv(keys::P_256);
475//!     r2_key.x(hex::decode("98F50A4FF6C05861C8860D13A638EA56C3F5AD7590BBFBF054E1C7B4D91D6280").unwrap());
476//!
477//!     // Prepare recipient 2 sender ephemeral key
478//!     let mut r2_eph_key = keys::CoseKey::new();
479//!     r2_eph_key.kty(keys::EC2);
480//!     r2_eph_key.crv(keys::P_256);
481//!     r2_eph_key.x(hex::decode("bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff").unwrap());
482//!     r2_eph_key.d(hex::decode("57c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3").unwrap());
483//!     r2_eph_key.key_ops(vec![keys::KEY_OPS_DERIVE]);
484//!
485//!     // Prepare CoseMAC message
486//!     let mut mac = CoseMessage::new_mac();
487//!     mac.header.alg(algs::AES_MAC_256_128, true, false);
488//!     mac.payload(msg);
489//!
490//!     // Add recipient 1 (A128KW)
491//!     let mut recipient1 = CoseAgent::new();
492//!     recipient1.header.alg(algs::A128KW, true, false);
493//!     recipient1.header.kid(r1_kid.clone(), false, false);
494//!     recipient1.key(&r1_key).unwrap();
495//!     mac.add_agent(&mut recipient1).unwrap();
496//!
497//!     // Add recipient 2 (ECDH_ES_A128KW)
498//!     let mut recipient2 = CoseAgent::new();
499//!     recipient2.header.alg(algs::ECDH_ES_A128KW, true, false);
500//!     recipient2.header.kid(r2_kid.clone(), false, false);
501//!     recipient2.header.salt(vec![0; 32], false, false);
502//!     recipient2.key(&r2_key).unwrap();
503//!     recipient2.header.ephemeral_key(r2_eph_key.clone(), true, false);
504//!     mac.add_agent(&mut recipient2).unwrap();
505//!
506//!     // Generate tag without AAD
507//!     mac.secure_content(None).unwrap();
508//!
509//!     // Encode the cose-mac message
510//!     mac.encode(true).unwrap();
511//!
512//! }
513//! ```
514//!
515//! ### Decode cose-mac message
516//!
517//! ```
518//! use cose::message::CoseMessage;
519//! use cose::keys;
520//! use cose::algs;
521//! use cose::agent::CoseAgent;
522//! use hex;
523//!
524//! fn main() {
525//!     let r1_kid = b"11".to_vec();
526//!     let r2_kid = b"22".to_vec();
527//!
528//!     // Prepare recipient 1 cose-key
529//!     let mut r1_key = keys::CoseKey::new();
530//!     r1_key.kty(keys::SYMMETRIC);
531//!     r1_key.alg(algs::A128KW);
532//!     r1_key.k(hex::decode("849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c427188").unwrap());
533//!     r1_key.key_ops(vec![keys::KEY_OPS_WRAP, keys::KEY_OPS_UNWRAP]);
534//!
535//!     // Prepare recipient 2 cose-key
536//!     let mut r2_key = keys::CoseKey::new();
537//!     r2_key.kty(keys::EC2);
538//!     r2_key.crv(keys::P_256);
539//!     r2_key.d(hex::decode("02D1F7E6F26C43D4868D87CEB2353161740AACF1F7163647984B522A848DF1C3").unwrap());
540//!     r2_key.key_ops(vec![keys::KEY_OPS_DERIVE]);
541//!
542//!     // Generate CoseMAC struct with the cose-mac message to decode
543//!     let mut verifier = CoseMessage::new_mac();
544//!     verifier.bytes =
545//!     hex::decode("d8618544a101181aa054546869732069732074686520636f6e74656e742e5064f33e4802d33bceec3fba4333ec5bf3828343a10122a10442313158281d77d288a153ab460c7c5c05e417b91becd26e9b73d2a0733c3b801db4885e51a635a2759801801b835832a201381c20a5010203262001215820bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff048107a20442323233582000000000000000000000000000000000000000000000000000000000000000005828e53a16090a9caf558a6a2d2709cf195ee28ea55ae92c8e0ddddac26fbee3eb76e494ecd7cfbf49c8").unwrap();
546//!     verifier.init_decoder(None).unwrap();
547//!
548//!     // Get recipient 1 and decode message
549//!     let mut index1 = verifier.get_agent(&r1_kid).unwrap()[0];
550//!     verifier.agents[index1].key(&r1_key).unwrap();
551//!     verifier.decode(None, Some(index1)).unwrap();
552//!
553//!     // Get recipient 2 and decode message
554//!     let mut index2 = verifier.get_agent(&r2_kid).unwrap()[0];
555//!     verifier.agents[index2].key(&r2_key).unwrap();
556//!     verifier.decode(None, Some(index2)).unwrap();
557//! }
558//! ```
559
560use crate::agent::CoseAgent;
561use crate::algs;
562use crate::common;
563use crate::cose_struct;
564use crate::errors::{CoseError, CoseResult, CoseResultWithRet};
565use crate::headers::{CoseHeader, COUNTER_SIG};
566use crate::keys;
567use cbor::{decoder::DecodeError, types::Tag, types::Type, Config, Decoder, Encoder};
568use std::io::Cursor;
569
570const SIG: usize = 0;
571const MAC: usize = 1;
572const ENC: usize = 2;
573
574const CONTEXTS: [&str; 3] = [
575    cose_struct::SIGNATURE,
576    cose_struct::MAC_RECIPIENT,
577    cose_struct::ENCRYPT_RECIPIENT,
578];
579const KO: [[i32; 2]; 3] = [
580    [keys::KEY_OPS_SIGN, keys::KEY_OPS_VERIFY],
581    [keys::KEY_OPS_MAC, keys::KEY_OPS_MAC_VERIFY],
582    [keys::KEY_OPS_ENCRYPT, keys::KEY_OPS_DECRYPT],
583];
584
585// COSE tags
586pub const ENC0_TAG: u64 = 16;
587pub const MAC0_TAG: u64 = 17;
588pub const SIG1_TAG: u64 = 18;
589pub const ENC_TAG: u64 = 96;
590pub const MAC_TAG: u64 = 97;
591pub const SIG_TAG: u64 = 98;
592
593// COSE types in string
594pub const ENC0_TYPE: &str = "cose-encrypt0";
595pub const MAC0_TYPE: &str = "cose-mac0";
596pub const SIG1_TYPE: &str = "cose-sign1";
597pub const ENC_TYPE: &str = "cose-encrypt";
598pub const MAC_TYPE: &str = "cose-mac";
599pub const SIG_TYPE: &str = "cose-sign";
600
601const SIZES: [[usize; 2]; 3] = [[4, 4], [4, 5], [3, 4]];
602const TAGS: [[Tag; 2]; 3] = [
603    [Tag::Unassigned(SIG1_TAG), Tag::Unassigned(SIG_TAG)],
604    [Tag::Unassigned(MAC0_TAG), Tag::Unassigned(MAC_TAG)],
605    [Tag::Unassigned(ENC0_TAG), Tag::Unassigned(ENC_TAG)],
606];
607
608/// Structure to encode/decode cose-sign and cose-sign1 messages
609pub struct CoseMessage {
610    /// The header parameters of the message.
611    pub header: CoseHeader,
612    /// The payload of the message.
613    pub payload: Vec<u8>,
614    secured: Vec<u8>,
615    /// The COSE encoded message.
616    pub bytes: Vec<u8>,
617    ph_bstr: Vec<u8>,
618    pub_key: Vec<u8>,
619    priv_key: Vec<u8>,
620    key_encode: bool,
621    key_decode: bool,
622    crv: Option<i32>,
623    base_iv: Option<Vec<u8>>,
624    /// The signers/recipients of the message, empty if cose-sign1, cose-encrypt0 and cose-mac0 message type.
625    pub agents: Vec<CoseAgent>,
626    context: usize,
627}
628
629impl CoseMessage {
630    /// Creates a new empty COSE signature (cose-sign1 and cose-sign) message structure.
631    pub fn new_sign() -> CoseMessage {
632        CoseMessage {
633            bytes: Vec::new(),
634            header: CoseHeader::new(),
635            payload: Vec::new(),
636            secured: Vec::new(),
637            ph_bstr: Vec::new(),
638            pub_key: Vec::new(),
639            priv_key: Vec::new(),
640            key_encode: false,
641            key_decode: false,
642            crv: None,
643            base_iv: None,
644            agents: Vec::new(),
645            context: SIG,
646        }
647    }
648
649    /// Creates a new empty COSE encrypt (cose-encrypt0 and cose-encrypt) message structure.
650    pub fn new_encrypt() -> CoseMessage {
651        CoseMessage {
652            bytes: Vec::new(),
653            header: CoseHeader::new(),
654            payload: Vec::new(),
655            secured: Vec::new(),
656            ph_bstr: Vec::new(),
657            pub_key: Vec::new(),
658            priv_key: Vec::new(),
659            key_encode: false,
660            key_decode: false,
661            crv: None,
662            base_iv: None,
663            agents: Vec::new(),
664            context: ENC,
665        }
666    }
667
668    /// Creates a new empty COSE MAC (cose-mac0 and cose-mac) message structure.
669    pub fn new_mac() -> CoseMessage {
670        CoseMessage {
671            bytes: Vec::new(),
672            header: CoseHeader::new(),
673            payload: Vec::new(),
674            secured: Vec::new(),
675            ph_bstr: Vec::new(),
676            pub_key: Vec::new(),
677            priv_key: Vec::new(),
678            key_encode: false,
679            key_decode: false,
680            crv: None,
681            base_iv: None,
682            agents: Vec::new(),
683            context: MAC,
684        }
685    }
686
687    /// Add an [header](../headers/struct.CoseHeader.html) to the message.
688    pub fn add_header(&mut self, header: CoseHeader) {
689        self.header = header;
690    }
691
692    /// Add the payload to the message.
693    pub fn payload(&mut self, payload: Vec<u8>) {
694        self.payload = payload;
695    }
696
697    /// Adds a signer/recipient ([agent](../agent/struct.CoseAgent.html)) to the message.
698    ///
699    /// Used for cose-sign, cose-mac and cose-encrypt messages.
700    pub fn add_agent(&mut self, agent: &mut CoseAgent) -> CoseResult {
701        if self.context == SIG {
702            agent.context = cose_struct::SIGNATURE.to_string();
703            if !algs::SIGNING_ALGS.contains(&agent.header.alg.ok_or(CoseError::MissingAlg())?) {
704                return Err(CoseError::InvalidAlg());
705            }
706            if !agent.key_ops.contains(&keys::KEY_OPS_SIGN) {
707                return Err(CoseError::KeyOpNotSupported());
708            }
709            self.agents.push(agent.clone());
710            Ok(())
711        } else if self.context == MAC {
712            agent.context = cose_struct::MAC_RECIPIENT.to_string();
713            self.agents.push(agent.clone());
714            Ok(())
715        } else {
716            agent.context = cose_struct::ENCRYPT_RECIPIENT.to_string();
717            if !algs::KEY_DISTRIBUTION_ALGS
718                .contains(&agent.header.alg.ok_or(CoseError::MissingAlg())?)
719            {
720                return Err(CoseError::InvalidAlg());
721            }
722            self.agents.push(agent.clone());
723            Ok(())
724        }
725    }
726
727    /// Returns a signer/recipient ([agent](../agent/struct.CoseAgent.html)) of the message with a given Key ID.
728    pub fn get_agent(&self, kid: &Vec<u8>) -> CoseResultWithRet<Vec<usize>> {
729        let mut keys: Vec<usize> = Vec::new();
730        for i in 0..self.agents.len() {
731            if self.agents[i]
732                .header
733                .kid
734                .as_ref()
735                .ok_or(CoseError::MissingKID())?
736                == kid
737            {
738                keys.push(i);
739            }
740        }
741        Ok(keys)
742    }
743
744    /// Adds a [cose-key](../keys/struct.CoseKey.html) to the message.
745    ///
746    /// This option is only available for the cose-sign1, cose-encrypt0 and cose-mac0 message types, since when using
747    /// this message types, the keys are respective to each signer/recipient.
748    pub fn key(&mut self, cose_key: &keys::CoseKey) -> CoseResult {
749        if self.agents.len() > 0 {
750            return Err(CoseError::InvalidMethodForContext());
751        }
752        cose_key.verify_kty()?;
753        if cose_key.alg.ok_or(CoseError::MissingAlg())?
754            != self.header.alg.ok_or(CoseError::MissingAlg())?
755        {
756            return Err(CoseError::AlgsDontMatch());
757        }
758        if self.context == SIG {
759            self.crv = cose_key.crv;
760            if cose_key.key_ops.contains(&keys::KEY_OPS_SIGN) {
761                let priv_key = cose_key.get_s_key()?;
762                if priv_key.len() > 0 {
763                    self.key_encode = true;
764                    self.priv_key = priv_key;
765                }
766            }
767            if cose_key.key_ops.contains(&keys::KEY_OPS_VERIFY) {
768                let pub_key = cose_key.get_pub_key()?;
769                if pub_key.len() > 0 {
770                    self.key_decode = true;
771                    self.pub_key = pub_key;
772                }
773            }
774        } else {
775            if self.context == ENC {
776                self.base_iv = cose_key.base_iv.clone();
777            }
778            let key = cose_key.get_s_key()?;
779            if key.len() > 0 {
780                if (self.context == ENC && cose_key.key_ops.contains(&keys::KEY_OPS_ENCRYPT))
781                    || (self.context == MAC && cose_key.key_ops.contains(&keys::KEY_OPS_MAC))
782                {
783                    self.key_encode = true;
784                }
785                if (self.context == ENC && cose_key.key_ops.contains(&keys::KEY_OPS_DECRYPT))
786                    || (self.context == MAC && cose_key.key_ops.contains(&keys::KEY_OPS_MAC_VERIFY))
787                {
788                    self.key_decode = true;
789                }
790                self.priv_key = key;
791            }
792        }
793        if !self.key_encode && !self.key_decode {
794            return Err(CoseError::KeyOpNotSupported());
795        }
796        Ok(())
797    }
798
799    /// Adds a counter signature to the message.
800    ///
801    /// The counter signature structure is the same type as the
802    /// [signers/recipients](../agent/struct.CoseAgent.html) structure and it should be used the
803    /// function [new_counter_sig](../agent/struct.CoseAgent.html#method.new_counter_sig) to initiate the structure.
804    pub fn counter_sig(
805        &self,
806        external_aad: Option<Vec<u8>>,
807        counter: &mut CoseAgent,
808    ) -> CoseResult {
809        let to_sig;
810        if self.context != ENC {
811            to_sig = &self.payload;
812        } else {
813            to_sig = &self.secured;
814        }
815        if to_sig.len() == 0 {
816            if self.context == ENC {
817                Err(CoseError::MissingCiphertext())
818            } else {
819                Err(CoseError::MissingPayload())
820            }
821        } else {
822            let aead = match external_aad {
823                None => Vec::new(),
824                Some(v) => v,
825            };
826            counter.sign(to_sig, &aead, &self.ph_bstr)?;
827            Ok(())
828        }
829    }
830
831    /// Function to get the content to sign by the counter signature.
832    ///
833    /// This function is meant to be called if the counter signature process needs to be external
834    /// to this crate, like a timestamp authority.
835    pub fn get_to_sign(
836        &self,
837        external_aad: Option<Vec<u8>>,
838        counter: &mut CoseAgent,
839    ) -> CoseResultWithRet<Vec<u8>> {
840        let to_sig;
841        if self.context != ENC {
842            to_sig = &self.payload;
843        } else {
844            to_sig = &self.secured;
845        }
846        if to_sig.len() == 0 {
847            if self.context == ENC {
848                Err(CoseError::MissingCiphertext())
849            } else {
850                Err(CoseError::MissingPayload())
851            }
852        } else {
853            let aead = match external_aad {
854                None => Vec::new(),
855                Some(v) => v,
856            };
857            counter.get_sign_content(to_sig, &aead, &self.ph_bstr)
858        }
859    }
860
861    /// Function to get the content to verify with the counter signature.
862    ///
863    /// This function is meant to be called if the counter signature process needs to be external
864    /// to this crate, like a timestamp authority.
865    pub fn get_to_verify(
866        &mut self,
867        external_aad: Option<Vec<u8>>,
868        counter: &usize,
869    ) -> CoseResultWithRet<Vec<u8>> {
870        let to_sig;
871        if self.context != ENC {
872            to_sig = &self.payload;
873        } else {
874            to_sig = &self.secured;
875        }
876        if to_sig.len() == 0 {
877            if self.context == ENC {
878                Err(CoseError::MissingCiphertext())
879            } else {
880                Err(CoseError::MissingPayload())
881            }
882        } else {
883            let aead = match external_aad {
884                None => Vec::new(),
885                Some(v) => v,
886            };
887            self.header.counters[*counter].get_sign_content(to_sig, &aead, &self.ph_bstr)
888        }
889    }
890
891    /// Function that verifies a given counter signature on the COSE message.
892    pub fn counters_verify(&mut self, external_aad: Option<Vec<u8>>, counter: usize) -> CoseResult {
893        let to_sig;
894        if self.context != ENC {
895            to_sig = &self.payload;
896        } else {
897            to_sig = &self.secured;
898        }
899        if to_sig.len() == 0 {
900            if self.context == ENC {
901                Err(CoseError::MissingCiphertext())
902            } else {
903                Err(CoseError::MissingPayload())
904            }
905        } else {
906            let aead = match external_aad {
907                None => Vec::new(),
908                Some(v) => v,
909            };
910            if self.header.counters[counter].verify(to_sig, &aead, &self.ph_bstr)? {
911                Ok(())
912            } else {
913                Err(CoseError::InvalidCounterSignature())
914            }
915        }
916    }
917
918    /// Function that adds a counter signature which was signed externally with the use of
919    /// [get_to_sign](#method.get_to_sign)
920    pub fn add_counter_sig(&mut self, counter: CoseAgent) -> CoseResult {
921        if !algs::SIGNING_ALGS.contains(&counter.header.alg.ok_or(CoseError::MissingAlg())?) {
922            return Err(CoseError::InvalidAlg());
923        }
924        if counter.context != cose_struct::COUNTER_SIGNATURE {
925            return Err(CoseError::InvalidContext());
926        }
927        if self.header.unprotected.contains(&COUNTER_SIG) {
928            self.header.counters.push(counter);
929            Ok(())
930        } else {
931            self.header.counters.push(counter);
932            self.header.remove_label(COUNTER_SIG);
933            self.header.unprotected.push(COUNTER_SIG);
934            Ok(())
935        }
936    }
937
938    /// Function to secure the content, sign, encrypt or mac depending on the COSE message type.
939    ///
940    /// `external_aad` parameter is used when it is desired to have an additional authentication
941    /// data to reinforce security of the signature.
942    pub fn secure_content(&mut self, external_aad: Option<Vec<u8>>) -> CoseResult {
943        if self.payload.len() <= 0 {
944            return Err(CoseError::MissingPayload());
945        }
946        self.ph_bstr = self.header.get_protected_bstr(true)?;
947        let aead = match external_aad {
948            None => Vec::new(),
949            Some(v) => v,
950        };
951        if self.agents.len() <= 0 {
952            if !self.key_encode {
953                return Err(CoseError::KeyOpNotSupported());
954            }
955            let alg = self.header.alg.ok_or(CoseError::MissingAlg())?;
956            if self.context == SIG {
957                if !algs::SIGNING_ALGS.contains(&alg) {
958                    Err(CoseError::InvalidAlg())
959                } else {
960                    self.secured = cose_struct::gen_sig(
961                        &self.priv_key,
962                        &alg,
963                        &self.crv,
964                        &aead,
965                        cose_struct::SIGNATURE1,
966                        &self.ph_bstr,
967                        &Vec::new(),
968                        &self.payload,
969                    )?;
970                    Ok(())
971                }
972            } else if self.context == ENC {
973                if !algs::ENCRYPT_ALGS.contains(&alg) {
974                    Err(CoseError::InvalidAlg())
975                } else {
976                    let iv = match self.base_iv.clone() {
977                        Some(v) => algs::gen_iv(
978                            self.header
979                                .partial_iv
980                                .as_ref()
981                                .ok_or(CoseError::MissingPartialIV())?,
982                            &v,
983                            &alg,
984                        )?,
985                        None => self.header.iv.clone().ok_or(CoseError::MissingIV())?,
986                    };
987                    self.secured = cose_struct::gen_cipher(
988                        &self.priv_key,
989                        &alg,
990                        &iv,
991                        &aead,
992                        cose_struct::ENCRYPT0,
993                        &self.ph_bstr,
994                        &self.payload,
995                    )?;
996                    Ok(())
997                }
998            } else {
999                if !algs::MAC_ALGS.contains(&alg) {
1000                    Err(CoseError::InvalidAlg())
1001                } else {
1002                    self.secured = cose_struct::gen_mac(
1003                        &self.priv_key,
1004                        &alg,
1005                        &aead,
1006                        cose_struct::MAC0,
1007                        &self.ph_bstr,
1008                        &self.payload,
1009                    )?;
1010                    Ok(())
1011                }
1012            }
1013        } else {
1014            if self.context == SIG {
1015                for i in 0..self.agents.len() {
1016                    if !algs::SIGNING_ALGS
1017                        .contains(&self.agents[i].header.alg.ok_or(CoseError::MissingAlg())?)
1018                    {
1019                        return Err(CoseError::InvalidAlg());
1020                    } else if !self.agents[i].key_ops.contains(&keys::KEY_OPS_SIGN) {
1021                        return Err(CoseError::KeyOpNotSupported());
1022                    } else {
1023                        self.agents[i].sign(&self.payload, &aead, &self.ph_bstr)?;
1024                        self.agents[i].enc = true;
1025                    }
1026                }
1027                Ok(())
1028            } else {
1029                let alg = self.header.alg.ok_or(CoseError::MissingAlg())?;
1030                let mut cek;
1031                if algs::DIRECT == self.agents[0].header.alg.ok_or(CoseError::MissingAlg())? {
1032                    if self.agents.len() > 1 {
1033                        return Err(CoseError::AlgOnlySupportsOneRecipient());
1034                    }
1035                    if !self.agents[0].key_ops.contains(&KO[self.context][0]) {
1036                        return Err(CoseError::KeyOpNotSupported());
1037                    } else {
1038                        if self.context == ENC {
1039                            self.secured = self.agents[0].enc(
1040                                &self.payload,
1041                                &aead,
1042                                &self.ph_bstr,
1043                                &alg,
1044                                self.header.iv.as_ref().ok_or(CoseError::MissingIV())?,
1045                            )?;
1046                            self.agents[0].enc = true;
1047                            return Ok(());
1048                        } else {
1049                            self.agents[0].mac(&self.payload, &aead, &self.ph_bstr)?;
1050                            self.agents[0].enc = true;
1051                            return Ok(());
1052                        }
1053                    }
1054                } else if algs::ECDH_H.contains(
1055                    self.agents[0]
1056                        .header
1057                        .alg
1058                        .as_ref()
1059                        .ok_or(CoseError::MissingAlg())?,
1060                ) {
1061                    if self.agents.len() > 1 {
1062                        return Err(CoseError::AlgOnlySupportsOneRecipient());
1063                    }
1064                    let size = algs::get_cek_size(&alg)?;
1065                    cek = self.agents[0].derive_key(&Vec::new(), size, true, &alg)?;
1066                    self.agents[0].enc = true;
1067                } else {
1068                    cek = algs::gen_random_key(&alg)?;
1069                    for i in 0..self.agents.len() {
1070                        if algs::DIRECT == self.agents[i].header.alg.unwrap()
1071                            || algs::ECDH_H.contains(self.agents[i].header.alg.as_ref().unwrap())
1072                        {
1073                            return Err(CoseError::AlgOnlySupportsOneRecipient());
1074                        }
1075                        cek = self.agents[i].derive_key(&cek, cek.len(), true, &alg)?;
1076                        self.agents[i].enc = true;
1077                    }
1078                }
1079                if self.context == ENC {
1080                    let iv = match self.agents[0].base_iv.clone() {
1081                        Some(v) => algs::gen_iv(
1082                            self.header
1083                                .partial_iv
1084                                .as_ref()
1085                                .ok_or(CoseError::MissingPartialIV())?,
1086                            &v,
1087                            &alg,
1088                        )?,
1089                        None => self.header.iv.clone().ok_or(CoseError::MissingIV())?,
1090                    };
1091                    self.secured = cose_struct::gen_cipher(
1092                        &cek,
1093                        &alg,
1094                        &iv,
1095                        &aead,
1096                        cose_struct::ENCRYPT,
1097                        &self.ph_bstr,
1098                        &self.payload,
1099                    )?;
1100                    Ok(())
1101                } else {
1102                    self.secured = cose_struct::gen_mac(
1103                        &cek,
1104                        &alg,
1105                        &aead,
1106                        cose_struct::MAC,
1107                        &self.ph_bstr,
1108                        &self.payload,
1109                    )?;
1110                    Ok(())
1111                }
1112            }
1113        }
1114    }
1115
1116    /// Function to encode the COSE message after the content is secured by [gen_signature](#method.gen_signature).
1117    ///
1118    /// The `data` parameter is used to specified if the payload/ciphertext shall be present or not in
1119    /// the message.
1120    pub fn encode(&mut self, data: bool) -> CoseResult {
1121        if self.agents.len() <= 0 {
1122            if self.secured.len() <= 0 {
1123                if self.context == SIG {
1124                    Err(CoseError::MissingSignature())
1125                } else if self.context == MAC {
1126                    Err(CoseError::MissingTag())
1127                } else {
1128                    Err(CoseError::MissingCiphertext())
1129                }
1130            } else {
1131                let mut e = Encoder::new(Vec::new());
1132                e.tag(TAGS[self.context][0])?;
1133                e.array(SIZES[self.context][0])?;
1134                e.bytes(self.ph_bstr.as_slice())?;
1135                self.header.encode_unprotected(&mut e)?;
1136                if data {
1137                    if self.context == ENC {
1138                        e.bytes(self.secured.as_slice())?;
1139                    } else {
1140                        e.bytes(self.payload.as_slice())?;
1141                    }
1142                } else {
1143                    e.null()?;
1144                }
1145                if self.context != ENC {
1146                    e.bytes(self.secured.as_slice())?;
1147                }
1148                self.bytes = e.into_writer().to_vec();
1149                self.header.labels_found = Vec::new();
1150                Ok(())
1151            }
1152        } else {
1153            let mut e = Encoder::new(Vec::new());
1154            e.tag(TAGS[self.context][1])?;
1155            e.array(SIZES[self.context][1])?;
1156            e.bytes(self.ph_bstr.as_slice())?;
1157            self.header.encode_unprotected(&mut e)?;
1158            if data {
1159                if self.context == ENC {
1160                    e.bytes(self.secured.as_slice())?;
1161                } else {
1162                    e.bytes(self.payload.as_slice())?;
1163                }
1164            } else {
1165                e.null()?;
1166            }
1167            if self.context == MAC {
1168                e.bytes(self.secured.as_slice())?;
1169            }
1170            let a_len = self.agents.len();
1171            e.array(a_len)?;
1172            for i in 0..a_len {
1173                self.agents[i].encode(&mut e)?;
1174            }
1175            self.bytes = e.into_writer().to_vec();
1176            self.header.labels_found = Vec::new();
1177            Ok(())
1178        }
1179    }
1180
1181    /// Function to decode the initial parts of the COSE message, in order to access the required
1182    /// parameters to fully decode the message with [decode](#method.decode)
1183    ///
1184    /// This function requires that the attribute bytes is set in the structure with the COSE
1185    /// encoded message beforehand.
1186    ///
1187    /// if the payload/ciphertext is not included in the COSE message, it needs to be provided in
1188    /// the `data` parameter.
1189    pub fn init_decoder(&mut self, data: Option<Vec<u8>>) -> CoseResult {
1190        let input = Cursor::new(self.bytes.clone());
1191        let mut d = Decoder::new(Config::default(), input);
1192        let mut tag: Option<Tag> = None;
1193
1194        match d.tag() {
1195            Ok(v) => {
1196                if !TAGS[self.context].contains(&v) {
1197                    return Err(CoseError::InvalidTag());
1198                } else {
1199                    tag = Some(v);
1200                    d.array()?;
1201                }
1202            }
1203            Err(ref err) => match err {
1204                DecodeError::UnexpectedType { datatype, info } => {
1205                    if *datatype != Type::Array && *info != SIZES[self.context][0] as u8 {
1206                        return Err(CoseError::InvalidCoseStructure());
1207                    }
1208                }
1209                _ => {
1210                    return Err(CoseError::InvalidCoseStructure());
1211                }
1212            },
1213        };
1214        self.ph_bstr = common::ph_bstr(d.bytes())?;
1215        if self.ph_bstr.len() > 0 {
1216            self.header.decode_protected_bstr(&self.ph_bstr)?;
1217        }
1218        self.header.decode_unprotected(&mut d, false)?;
1219        self.header.labels_found = Vec::new();
1220        match data {
1221            None => {
1222                if self.context == ENC {
1223                    self.secured = d.bytes()?.to_vec();
1224                } else {
1225                    self.payload = d.bytes()?.to_vec();
1226                }
1227            }
1228            Some(v) => {
1229                d.skip()?;
1230                if self.context == ENC {
1231                    self.secured = v;
1232                } else {
1233                    self.payload = v;
1234                }
1235            }
1236        };
1237
1238        if (self.context == ENC && self.secured.len() <= 0)
1239            || (self.context != ENC && self.payload.len() <= 0)
1240        {
1241            if self.context == ENC {
1242                return Err(CoseError::MissingCiphertext());
1243            } else {
1244                return Err(CoseError::MissingPayload());
1245            }
1246        }
1247
1248        if self.context != SIG {
1249            if self.header.alg.ok_or(CoseError::MissingAlg())? == algs::DIRECT
1250                && self.ph_bstr.len() > 0
1251            {
1252                return Err(CoseError::InvalidCoseStructure());
1253            } else if algs::A_KW.contains(self.header.alg.as_ref().ok_or(CoseError::MissingAlg())?)
1254                && self.ph_bstr.len() > 0
1255            {
1256                return Err(CoseError::InvalidCoseStructure());
1257            }
1258        }
1259
1260        if self.context == MAC {
1261            self.secured = d.bytes()?.to_vec();
1262            if self.secured.len() <= 0 {
1263                return Err(CoseError::MissingPayload());
1264            }
1265        }
1266
1267        match d.kernel().typeinfo() {
1268            Ok(type_info) => {
1269                if type_info.0 == Type::Array
1270                    && (tag == None || tag.unwrap() == TAGS[self.context][1])
1271                {
1272                    let r_len = type_info.1;
1273                    let mut agent: CoseAgent;
1274                    for _ in 0..r_len {
1275                        agent = CoseAgent::new();
1276                        agent.context = CONTEXTS[self.context].to_string();
1277                        d.array()?;
1278                        agent.ph_bstr = common::ph_bstr(d.bytes())?;
1279                        agent.decode(&mut d)?;
1280                        agent.enc = true;
1281                        self.agents.push(agent);
1282                    }
1283                } else if type_info.0 == Type::Bytes
1284                    && (tag == None || tag.unwrap() == TAGS[self.context][0])
1285                {
1286                    if self.context == SIG {
1287                        self.secured = d.kernel().raw_data(type_info.1, 0x500000)?;
1288                    }
1289                    if self.secured.len() <= 0 {
1290                        if self.context == SIG {
1291                            return Err(CoseError::MissingSignature());
1292                        } else if self.context == MAC {
1293                            return Err(CoseError::MissingTag());
1294                        } else {
1295                            return Err(CoseError::MissingCiphertext());
1296                        }
1297                    }
1298                }
1299            }
1300            Err(_) => {}
1301        }
1302        Ok(())
1303    }
1304
1305    /// Function to verify/decrypt the secured content of the COSE message.
1306    ///
1307    /// `external_add` is used in case of an AAD is included.
1308    ///
1309    /// `agent` parameter must be `None` if the type of the message is cose-sign1, cose-encrypt0 or
1310    /// cose-mac0 and in case of being a cose-sign, cose-mac or cose-encrypt message type, the index of the
1311    /// signer/recipient of the message must be given with the respective key already added to the same
1312    /// signer/recipient.
1313    pub fn decode(
1314        &mut self,
1315        external_aad: Option<Vec<u8>>,
1316        agent: Option<usize>,
1317    ) -> CoseResultWithRet<Vec<u8>> {
1318        let aead = match external_aad {
1319            None => Vec::new(),
1320            Some(v) => v,
1321        };
1322        if self.agents.len() <= 0 {
1323            if !self.key_decode {
1324                return Err(CoseError::KeyOpNotSupported());
1325            } else {
1326                if self.context == SIG {
1327                    if !cose_struct::verify_sig(
1328                        &self.pub_key,
1329                        &self.header.alg.ok_or(CoseError::MissingAlg())?,
1330                        &self.crv,
1331                        &aead,
1332                        cose_struct::SIGNATURE1,
1333                        &self.ph_bstr,
1334                        &Vec::new(),
1335                        &self.payload,
1336                        &self.secured,
1337                    )? {
1338                        Err(CoseError::InvalidSignature())
1339                    } else {
1340                        Ok(self.payload.clone())
1341                    }
1342                } else if self.context == MAC {
1343                    if !cose_struct::verify_mac(
1344                        &self.priv_key,
1345                        &self.header.alg.ok_or(CoseError::MissingAlg())?,
1346                        &aead,
1347                        cose_struct::MAC0,
1348                        &self.ph_bstr,
1349                        &self.secured,
1350                        &self.payload,
1351                    )? {
1352                        return Err(CoseError::InvalidMAC());
1353                    } else {
1354                        Ok(self.payload.clone())
1355                    }
1356                } else {
1357                    let iv = match self.base_iv.clone() {
1358                        Some(v) => algs::gen_iv(
1359                            self.header
1360                                .partial_iv
1361                                .as_ref()
1362                                .ok_or(CoseError::MissingPartialIV())?,
1363                            &v,
1364                            &self.header.alg.ok_or(CoseError::MissingAlg())?,
1365                        )?,
1366                        None => self.header.iv.clone().ok_or(CoseError::MissingIV())?,
1367                    };
1368                    Ok(cose_struct::dec_cipher(
1369                        &self.priv_key,
1370                        &self.header.alg.ok_or(CoseError::MissingAlg())?,
1371                        &iv,
1372                        &aead,
1373                        cose_struct::ENCRYPT0,
1374                        &self.ph_bstr,
1375                        &self.secured,
1376                    )?)
1377                }
1378            }
1379        } else if agent != None {
1380            let index = agent.ok_or(CoseError::MissingSigner())?;
1381            if self.context == SIG {
1382                if self.agents[index].pub_key.len() == 0
1383                    || !self.agents[index].key_ops.contains(&keys::KEY_OPS_VERIFY)
1384                {
1385                    Err(CoseError::KeyOpNotSupported())
1386                } else {
1387                    if !self.agents[index].verify(&self.payload, &aead, &self.ph_bstr)? {
1388                        Err(CoseError::InvalidSignature())
1389                    } else {
1390                        Ok(self.payload.clone())
1391                    }
1392                }
1393            } else {
1394                let alg = self.header.alg.ok_or(CoseError::MissingAlg())?;
1395                let cek;
1396                if algs::DIRECT
1397                    == self.agents[index]
1398                        .header
1399                        .alg
1400                        .ok_or(CoseError::MissingAlg())?
1401                {
1402                    if !self.agents[index].key_ops.contains(&KO[self.context][1]) {
1403                        return Err(CoseError::KeyOpNotSupported());
1404                    } else {
1405                        if self.agents[index].s_key.len() > 0 {
1406                            cek = self.agents[index].s_key.clone();
1407                        } else {
1408                            return Err(CoseError::KeyOpNotSupported());
1409                        }
1410                    }
1411                } else {
1412                    let size = algs::get_cek_size(&alg)?;
1413                    let payload = self.agents[index].payload.clone();
1414                    cek = self.agents[index].derive_key(&payload, size, false, &alg)?;
1415                }
1416                if self.context == ENC {
1417                    let iv = match self.agents[index].base_iv.clone() {
1418                        Some(v) => algs::gen_iv(
1419                            self.header
1420                                .partial_iv
1421                                .as_ref()
1422                                .ok_or(CoseError::MissingPartialIV())?,
1423                            &v,
1424                            &alg,
1425                        )?,
1426                        None => self.header.iv.clone().ok_or(CoseError::MissingIV())?,
1427                    };
1428                    Ok(cose_struct::dec_cipher(
1429                        &cek,
1430                        &alg,
1431                        &iv,
1432                        &aead,
1433                        cose_struct::ENCRYPT,
1434                        &self.ph_bstr,
1435                        &self.secured,
1436                    )?)
1437                } else {
1438                    if !cose_struct::verify_mac(
1439                        &cek,
1440                        &alg,
1441                        &aead,
1442                        cose_struct::MAC,
1443                        &self.ph_bstr,
1444                        &self.secured,
1445                        &self.payload,
1446                    )? {
1447                        Err(CoseError::InvalidMAC())
1448                    } else {
1449                        Ok(self.payload.clone())
1450                    }
1451                }
1452            }
1453        } else {
1454            return Err(CoseError::MissingSigner());
1455        }
1456    }
1457}