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