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}