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