cose/
algs.rs

1//! A collection of COSE algorithm identifiers.
2use crate::errors::{CoseError, CoseResult, CoseResultWithRet};
3use crate::keys;
4use openssl::aes::{unwrap_key, wrap_key, AesKey};
5use openssl::bn::{BigNum, BigNumContext};
6use openssl::cipher;
7use openssl::cipher_ctx::CipherCtx;
8use openssl::derive::Deriver;
9use openssl::ec::{EcGroup, EcKey, EcPoint};
10use openssl::ecdsa::EcdsaSig;
11use openssl::hash::{hash, MessageDigest};
12use openssl::md::Md;
13use openssl::nid::Nid;
14use openssl::pkey::{Id, PKey, Private, Public};
15use openssl::pkey_ctx::{HkdfMode, PkeyCtx};
16use openssl::rsa::{Padding, Rsa};
17use openssl::sign::{RsaPssSaltlen, Signer, Verifier};
18use openssl::stack::Stack;
19use openssl::symm::{decrypt_aead, encrypt as encr, encrypt_aead, Cipher};
20use openssl::x509::{store::X509StoreBuilder, X509StoreContext, X509};
21use rand::Rng;
22
23// Signing algotihtms
24pub const ES256: i32 = -7;
25pub const ES256K: i32 = -47;
26pub const ES384: i32 = -35;
27pub const ES512: i32 = -36;
28pub const EDDSA: i32 = -8;
29pub const PS512: i32 = -39;
30pub const PS384: i32 = -38;
31pub const PS256: i32 = -37;
32pub(crate) const SIGNING_ALGS: [i32; 8] = [ES256, ES384, ES512, EDDSA, PS256, PS384, PS512, ES256K];
33pub(crate) const SIGNING_ALGS_NAMES: [&str; 8] = [
34    "ES256", "ES384", "ES512", "EDDSA", "PS256", "PS384", "PS512", "ES256K",
35];
36
37// Encryption algorithms
38pub const A128GCM: i32 = 1;
39pub const A192GCM: i32 = 2;
40pub const A256GCM: i32 = 3;
41pub const CHACHA20: i32 = 24;
42pub const AES_CCM_16_64_128: i32 = 10;
43pub const AES_CCM_16_64_256: i32 = 11;
44pub const AES_CCM_64_64_128: i32 = 12;
45pub const AES_CCM_64_64_256: i32 = 13;
46pub const AES_CCM_16_128_128: i32 = 30;
47pub const AES_CCM_16_128_256: i32 = 31;
48pub const AES_CCM_64_128_128: i32 = 32;
49pub const AES_CCM_64_128_256: i32 = 33;
50pub(crate) const ENCRYPT_ALGS: [i32; 12] = [
51    A128GCM,
52    A192GCM,
53    A256GCM,
54    CHACHA20,
55    AES_CCM_16_64_128,
56    AES_CCM_16_64_256,
57    AES_CCM_64_64_128,
58    AES_CCM_64_64_256,
59    AES_CCM_16_128_128,
60    AES_CCM_16_128_256,
61    AES_CCM_64_128_128,
62    AES_CCM_64_128_256,
63];
64pub(crate) const ENCRYPT_ALGS_NAMES: [&str; 12] = [
65    "A128GCM",
66    "A192GCM",
67    "A256GCM",
68    "ChaCha20/Poly1305",
69    "AES-CCM-16-64-128",
70    "AES-CCM-16-64-256",
71    "AES-CCM-64-64-128",
72    "AES-CCM-64-64-256",
73    "AES-CCM-16-128-128",
74    "AES-CCM-16-128-256",
75    "AES-CCM-64-128-128",
76    "AES-CCM-64-128-256",
77];
78
79// MAC algorithms
80pub const HMAC_256_64: i32 = 4;
81pub const HMAC_256_256: i32 = 5;
82pub const HMAC_384_384: i32 = 6;
83pub const HMAC_512_512: i32 = 7;
84pub const AES_MAC_128_64: i32 = 14;
85pub const AES_MAC_256_64: i32 = 15;
86pub const AES_MAC_128_128: i32 = 25;
87pub const AES_MAC_256_128: i32 = 26;
88pub(crate) const MAC_ALGS_NAMES: [&str; 8] = [
89    "HMAC 256/64",
90    "HMAC 256/256",
91    "HMAC 384/384",
92    "HMAC 512/512",
93    "AES-MAC 128/64",
94    "AES-MAC 256/64",
95    "AES-MAC 128/128",
96    "AES-MAC 256/128",
97];
98pub(crate) const MAC_ALGS: [i32; 8] = [
99    HMAC_256_64,
100    HMAC_256_256,
101    HMAC_384_384,
102    HMAC_512_512,
103    AES_MAC_128_64,
104    AES_MAC_256_64,
105    AES_MAC_128_128,
106    AES_MAC_256_128,
107];
108
109// HASH Algorithms
110pub const SHA_256: i32 = -16;
111pub const HASH_ALGS: [i32; 1] = [SHA_256];
112pub const HASH_ALGS_NAMES: [&str; 1] = ["SHA-256"];
113
114// Content Key Distribution
115
116//Direct
117pub const DIRECT: i32 = -6;
118//KDFs
119pub const DIRECT_HKDF_SHA_256: i32 = -10;
120pub const DIRECT_HKDF_SHA_512: i32 = -11;
121pub const DIRECT_HKDF_AES_128: i32 = -12;
122pub const DIRECT_HKDF_AES_256: i32 = -13;
123//Key Wrap
124pub const A128KW: i32 = -3;
125pub const A192KW: i32 = -4;
126pub const A256KW: i32 = -5;
127//RSA OAEP
128pub const RSA_OAEP_1: i32 = -40;
129pub const RSA_OAEP_256: i32 = -41;
130pub const RSA_OAEP_512: i32 = -42;
131//Direct Key Agreement
132pub const ECDH_ES_HKDF_256: i32 = -25;
133pub const ECDH_ES_HKDF_512: i32 = -26;
134pub const ECDH_SS_HKDF_256: i32 = -27;
135pub const ECDH_SS_HKDF_512: i32 = -28;
136//Key Agreement with Key Wrap
137pub const ECDH_ES_A128KW: i32 = -29;
138pub const ECDH_ES_A192KW: i32 = -30;
139pub const ECDH_ES_A256KW: i32 = -31;
140pub const ECDH_SS_A128KW: i32 = -32;
141pub const ECDH_SS_A192KW: i32 = -33;
142pub const ECDH_SS_A256KW: i32 = -34;
143pub(crate) const KEY_DISTRIBUTION_ALGS: [i32; 21] = [
144    DIRECT,
145    DIRECT_HKDF_SHA_256,
146    DIRECT_HKDF_SHA_512,
147    DIRECT_HKDF_AES_128,
148    DIRECT_HKDF_AES_256,
149    A128KW,
150    A192KW,
151    A256KW,
152    RSA_OAEP_1,
153    RSA_OAEP_256,
154    RSA_OAEP_512,
155    ECDH_ES_HKDF_256,
156    ECDH_ES_HKDF_512,
157    ECDH_SS_HKDF_256,
158    ECDH_SS_HKDF_512,
159    ECDH_ES_A128KW,
160    ECDH_ES_A192KW,
161    ECDH_ES_A256KW,
162    ECDH_SS_A128KW,
163    ECDH_SS_A192KW,
164    ECDH_SS_A256KW,
165];
166
167pub(crate) const KEY_DISTRIBUTION_NAMES: [&str; 21] = [
168    "direct",
169    "direct+HKDF-SHA-256",
170    "direct+HKDF-SHA-512",
171    "direct+HKDF-AES-128",
172    "direct+HKDF-AES-256",
173    "A128KW",
174    "A192KW",
175    "A256KW",
176    "RSAES-OAEP w/ RFC 8017 default parameters",
177    "RSAES-OAEP w/ SHA-256",
178    "RSAES-OAEP w/ SHA-512",
179    "ECDH-ES + HKDF-256",
180    "ECDH-ES + HKDF-512",
181    "ECDH-SS + HKDF-256",
182    "ECDH-SS + HKDF-512",
183    "ECDH-ES + A128KW",
184    "ECDH-ES + A192KW",
185    "ECDH-ES + A256KW",
186    "ECDH-SS + A128KW",
187    "ECDH-SS + A192KW",
188    "ECDH-SS + A256KW",
189];
190pub(crate) const ECDH_ALGS: [i32; 10] = [
191    ECDH_ES_HKDF_256,
192    ECDH_ES_HKDF_512,
193    ECDH_SS_HKDF_256,
194    ECDH_SS_HKDF_512,
195    ECDH_ES_A128KW,
196    ECDH_ES_A192KW,
197    ECDH_ES_A256KW,
198    ECDH_SS_A128KW,
199    ECDH_SS_A192KW,
200    ECDH_SS_A256KW,
201];
202const K16_ALGS: [i32; 11] = [
203    A128GCM,
204    CHACHA20,
205    AES_CCM_16_64_128,
206    AES_CCM_64_64_128,
207    AES_CCM_16_128_128,
208    AES_CCM_64_128_128,
209    AES_MAC_128_64,
210    AES_MAC_128_128,
211    ECDH_ES_A128KW,
212    ECDH_SS_A128KW,
213    A128KW,
214];
215const K24_ALGS: [i32; 4] = [A192KW, ECDH_ES_A192KW, ECDH_SS_A192KW, A192GCM];
216const K32_ALGS: [i32; 12] = [
217    A256GCM,
218    AES_CCM_16_64_256,
219    AES_CCM_64_64_256,
220    AES_CCM_16_128_256,
221    AES_CCM_64_128_256,
222    AES_MAC_256_128,
223    AES_MAC_256_64,
224    HMAC_256_64,
225    HMAC_256_256,
226    ECDH_ES_A256KW,
227    ECDH_SS_A256KW,
228    A256KW,
229];
230
231pub(crate) const OKP_ALGS: [i32; 1] = [EDDSA];
232pub(crate) const EC2_ALGS: [i32; 4] = [ES256, ES384, ES512, ES256K];
233pub(crate) const RSA_ALGS: [i32; 3] = [PS256, PS384, PS512];
234pub(crate) const SYMMETRIC_ALGS: [i32; 28] = [
235    A128GCM,
236    A192GCM,
237    A256GCM,
238    CHACHA20,
239    AES_CCM_16_64_128,
240    AES_CCM_16_64_256,
241    AES_CCM_64_64_128,
242    AES_CCM_64_64_256,
243    AES_CCM_16_128_128,
244    AES_CCM_16_128_256,
245    AES_CCM_64_128_128,
246    AES_CCM_64_128_256,
247    HMAC_256_64,
248    HMAC_256_256,
249    HMAC_384_384,
250    HMAC_512_512,
251    AES_MAC_128_64,
252    AES_MAC_256_64,
253    AES_MAC_128_128,
254    AES_MAC_256_128,
255    DIRECT,
256    DIRECT_HKDF_SHA_256,
257    DIRECT_HKDF_SHA_512,
258    DIRECT_HKDF_AES_128,
259    DIRECT_HKDF_AES_256,
260    A128KW,
261    A192KW,
262    A256KW,
263];
264
265pub(crate) const RSA_OAEP: [i32; 3] = [RSA_OAEP_1, RSA_OAEP_256, RSA_OAEP_512];
266pub(crate) const A_KW: [i32; 3] = [A128KW, A192KW, A256KW];
267pub(crate) const D_HA: [i32; 2] = [DIRECT_HKDF_AES_128, DIRECT_HKDF_AES_256];
268pub(crate) const D_HS: [i32; 2] = [DIRECT_HKDF_SHA_256, DIRECT_HKDF_SHA_512];
269pub(crate) const ECDH_H: [i32; 4] = [
270    ECDH_ES_HKDF_256,
271    ECDH_ES_HKDF_512,
272    ECDH_SS_HKDF_256,
273    ECDH_SS_HKDF_512,
274];
275pub(crate) const ECDH_A: [i32; 6] = [
276    ECDH_ES_A128KW,
277    ECDH_ES_A192KW,
278    ECDH_ES_A256KW,
279    ECDH_SS_A128KW,
280    ECDH_SS_A192KW,
281    ECDH_SS_A256KW,
282];
283
284const DER_S2: [u8; 16] = [48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32];
285const DER_S4: [u8; 16] = [48, 71, 2, 1, 0, 48, 5, 6, 3, 43, 101, 113, 4, 59, 4, 57];
286const DER_P2: [u8; 12] = [48, 42, 48, 5, 6, 3, 43, 101, 112, 3, 33, 0];
287const DER_P4: [u8; 12] = [48, 67, 48, 5, 6, 3, 43, 101, 113, 3, 58, 0];
288
289/// Function to sign content with a given key and algorithm.
290pub fn sign(
291    alg: i32,
292    crv: Option<i32>,
293    key: &Vec<u8>,
294    content: &Vec<u8>,
295) -> CoseResultWithRet<Vec<u8>> {
296    let number = BigNum::from_slice(key.as_slice())?;
297    let group;
298    let message_digest;
299    if [ES256, ES384, ES512].contains(&alg) {
300        if alg == ES256 {
301            message_digest = MessageDigest::sha256();
302        } else if alg == ES384 {
303            message_digest = MessageDigest::sha384();
304        } else {
305            message_digest = MessageDigest::sha512();
306        }
307        let crv = crv.ok_or(CoseError::InvalidCRV())?;
308        if crv == keys::P_256 {
309            group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
310        } else if crv == keys::P_384 {
311            group = EcGroup::from_curve_name(Nid::SECP384R1)?;
312        } else if crv == keys::P_521 {
313            group = EcGroup::from_curve_name(Nid::SECP521R1)?;
314        } else {
315            return Err(CoseError::InvalidCRV());
316        }
317    } else if alg == ES256K {
318        group = EcGroup::from_curve_name(Nid::SECP256K1)?;
319        message_digest = MessageDigest::sha256();
320    } else if alg == EDDSA {
321        let mut ed_key;
322        let crv = crv.ok_or(CoseError::InvalidCRV())?;
323        if crv == keys::ED25519 {
324            ed_key = DER_S2.to_vec();
325            ed_key.append(&mut key.clone());
326        } else if crv == keys::ED448 {
327            ed_key = DER_S4.to_vec();
328            ed_key.append(&mut key.clone());
329        } else {
330            return Err(CoseError::InvalidCRV());
331        }
332        let key = PKey::private_key_from_der(ed_key.as_slice())?;
333        let mut signer = Signer::new(MessageDigest::null(), &key)?;
334        let size = signer.len()?;
335        let mut s = vec![0; size];
336        signer.sign_oneshot(&mut s, content.as_slice())?;
337        return Ok(s);
338    } else if alg == PS256 {
339        let rsa_key = Rsa::private_key_from_der(key)?;
340        let key = PKey::from_rsa(rsa_key)?;
341        let mut signer = Signer::new(MessageDigest::sha256(), &key)?;
342        signer.set_rsa_padding(Padding::PKCS1_PSS)?;
343        signer.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)?;
344        signer.update(&content)?;
345        return Ok(signer.sign_to_vec()?);
346    } else if alg == PS384 {
347        let rsa_key = Rsa::private_key_from_der(key)?;
348        let key = PKey::from_rsa(rsa_key)?;
349        let mut signer = Signer::new(MessageDigest::sha384(), &key)?;
350        signer.set_rsa_padding(Padding::PKCS1_PSS)?;
351        signer.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)?;
352        signer.update(&content)?;
353        return Ok(signer.sign_to_vec()?);
354    } else if alg == PS512 {
355        let rsa_key = Rsa::private_key_from_der(key)?;
356        let key = PKey::from_rsa(rsa_key)?;
357        let mut signer = Signer::new(MessageDigest::sha512(), &key)?;
358        signer.set_rsa_padding(Padding::PKCS1_PSS)?;
359        signer.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)?;
360        signer.update(&content)?;
361        return Ok(signer.sign_to_vec()?);
362    } else {
363        return Err(CoseError::InvalidAlg());
364    }
365    let size: i32 = key.len() as i32;
366    let ec_key = EcKey::from_private_components(&group, &number, &EcPoint::new(&group).unwrap())?;
367    let final_key = PKey::from_ec_key(ec_key)?;
368    let mut signer = Signer::new(message_digest, &final_key)?;
369    signer.update(content.as_slice())?;
370    let der_sig = signer.sign_to_vec()?;
371    let priv_comp = EcdsaSig::from_der(&der_sig)?;
372    let mut s = priv_comp.r().to_vec_padded(size)?;
373    s.append(&mut priv_comp.s().to_vec_padded(size)?);
374    Ok(s)
375}
376
377/// Function to verify a signature with a given key, algorithm and content that was signed.
378pub fn verify(
379    alg: i32,
380    crv: Option<i32>,
381    key: &Vec<u8>,
382    content: &Vec<u8>,
383    signature: &Vec<u8>,
384) -> CoseResultWithRet<bool> {
385    let group;
386    let message_digest;
387    let mut ctx = BigNumContext::new()?;
388    let size: usize;
389    if key[0] == 3 {
390        size = key.len() - 1;
391    } else {
392        size = (key.len() - 1) / 2;
393    }
394    if [ES256, ES384, ES512].contains(&alg) {
395        if alg == ES256 {
396            message_digest = MessageDigest::sha256();
397        } else if alg == ES384 {
398            message_digest = MessageDigest::sha384();
399        } else {
400            message_digest = MessageDigest::sha512();
401        }
402        let crv = crv.ok_or(CoseError::InvalidCRV())?;
403        if crv == keys::P_256 {
404            group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
405        } else if crv == keys::P_384 {
406            group = EcGroup::from_curve_name(Nid::SECP384R1)?;
407        } else if crv == keys::P_521 {
408            group = EcGroup::from_curve_name(Nid::SECP521R1)?;
409        } else {
410            return Err(CoseError::InvalidCRV());
411        }
412    } else if alg == ES256K {
413        group = EcGroup::from_curve_name(Nid::SECP256K1)?;
414        message_digest = MessageDigest::sha256();
415    } else if alg == EDDSA {
416        let mut ed_key;
417        let crv = crv.ok_or(CoseError::InvalidCRV())?;
418        if crv == keys::ED25519 {
419            ed_key = DER_P2.to_vec();
420            ed_key.append(&mut key.clone());
421        } else if crv == keys::ED448 {
422            ed_key = DER_P4.to_vec();
423            ed_key.append(&mut key.clone());
424        } else {
425            return Err(CoseError::InvalidCRV());
426        }
427        let ec_public_key = PKey::public_key_from_der(ed_key.as_slice())?;
428        let mut verifier = Verifier::new(MessageDigest::null(), &ec_public_key)?;
429        return Ok(verifier.verify_oneshot(&signature, &content)?);
430    } else if alg == PS256 {
431        let rsa_key = Rsa::public_key_from_der(key)?;
432        let key = PKey::from_rsa(rsa_key)?;
433        let mut verifier = Verifier::new(MessageDigest::sha256(), &key)?;
434        verifier.set_rsa_padding(Padding::PKCS1_PSS)?;
435        verifier.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)?;
436        verifier.update(&content)?;
437        return Ok(verifier.verify(&signature)?);
438    } else if alg == PS384 {
439        let rsa_key = Rsa::public_key_from_der(key)?;
440        let key = PKey::from_rsa(rsa_key)?;
441        let mut verifier = Verifier::new(MessageDigest::sha384(), &key)?;
442        verifier.set_rsa_padding(Padding::PKCS1_PSS)?;
443        verifier.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)?;
444        verifier.update(&content)?;
445        return Ok(verifier.verify(&signature)?);
446    } else if alg == PS512 {
447        let rsa_key = Rsa::public_key_from_der(key)?;
448        let key = PKey::from_rsa(rsa_key)?;
449        let mut verifier = Verifier::new(MessageDigest::sha512(), &key)?;
450        verifier.set_rsa_padding(Padding::PKCS1_PSS)?;
451        verifier.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)?;
452        verifier.update(&content)?;
453        return Ok(verifier.verify(&signature)?);
454    } else {
455        return Err(CoseError::InvalidAlg());
456    }
457    let point = EcPoint::from_bytes(&group, &key, &mut ctx)?;
458    let ec_key = EcKey::from_public_key(&group, &point)?;
459    let final_key = PKey::from_ec_key(ec_key)?;
460    let mut verifier = Verifier::new(message_digest, &final_key)?;
461    verifier.update(&content)?;
462    let s = EcdsaSig::from_private_components(
463        BigNum::from_slice(&signature[..size])?,
464        BigNum::from_slice(&signature[size..])?,
465    )?;
466    Ok(verifier.verify(&s.to_der()?)?)
467}
468
469pub(crate) fn mac(alg: i32, key: &Vec<u8>, content: &Vec<u8>) -> CoseResultWithRet<Vec<u8>> {
470    let size;
471    if [
472        AES_MAC_128_64,
473        AES_MAC_256_64,
474        AES_MAC_128_128,
475        AES_MAC_256_128,
476    ]
477    .contains(&alg)
478    {
479        let mut padded: Vec<u8> = content.to_vec();
480        if padded.len() % 16 != 0 {
481            padded.append(&mut vec![0; 16 - (padded.len() % 16)]);
482        }
483        let cipher;
484        let index = padded.len() - 16;
485        if alg == AES_MAC_128_64 {
486            size = 8;
487            cipher = Cipher::aes_128_cbc()
488        } else if alg == AES_MAC_256_64 {
489            size = 8;
490            cipher = Cipher::aes_256_cbc()
491        } else if alg == AES_MAC_128_128 {
492            size = 16;
493            cipher = Cipher::aes_128_cbc()
494        } else {
495            size = 16;
496            cipher = Cipher::aes_256_cbc()
497        }
498        let s = encr(cipher, key, Some(&[0; 16]), &padded)?;
499        Ok(s[index..index + size].to_vec())
500    } else {
501        let k;
502        let message_digest;
503
504        if alg == HMAC_256_64 {
505            k = PKey::hmac(key.as_slice())?;
506            message_digest = MessageDigest::sha256();
507            size = 8;
508        } else if alg == HMAC_256_256 {
509            k = PKey::hmac(key.as_slice())?;
510            message_digest = MessageDigest::sha256();
511            size = 32;
512        } else if alg == HMAC_384_384 {
513            k = PKey::hmac(key.as_slice())?;
514            message_digest = MessageDigest::sha384();
515            size = 48;
516        } else if alg == HMAC_512_512 {
517            k = PKey::hmac(key.as_slice())?;
518            message_digest = MessageDigest::sha512();
519            size = 64;
520        } else {
521            return Err(CoseError::InvalidAlg());
522        }
523        let mut signer = Signer::new(message_digest, &k)?;
524        signer.update(content.as_slice())?;
525        let mut s = signer.sign_to_vec()?;
526        s.truncate(size);
527        Ok(s)
528    }
529}
530
531pub(crate) fn mac_verify(
532    alg: i32,
533    key: &Vec<u8>,
534    content: &Vec<u8>,
535    signature: &Vec<u8>,
536) -> CoseResultWithRet<bool> {
537    let size;
538    if [
539        AES_MAC_128_64,
540        AES_MAC_256_64,
541        AES_MAC_128_128,
542        AES_MAC_256_128,
543    ]
544    .contains(&alg)
545    {
546        let mut padded: Vec<u8> = content.to_vec();
547        if padded.len() % 16 != 0 {
548            padded.append(&mut vec![0; 16 - (padded.len() % 16)]);
549        }
550        let cipher;
551        let index = padded.len() - 16;
552        if alg == AES_MAC_128_64 {
553            size = 8;
554            cipher = Cipher::aes_128_cbc()
555        } else if alg == AES_MAC_256_64 {
556            size = 8;
557            cipher = Cipher::aes_256_cbc()
558        } else if alg == AES_MAC_128_128 {
559            size = 16;
560            cipher = Cipher::aes_128_cbc()
561        } else {
562            size = 16;
563            cipher = Cipher::aes_256_cbc()
564        }
565        let s = encr(cipher, key, Some(&[0; 16]), &padded)?;
566        Ok(s[index..index + size].to_vec() == *signature)
567    } else {
568        let k;
569        let message_digest;
570
571        if alg == HMAC_256_64 {
572            k = PKey::hmac(key.as_slice())?;
573            message_digest = MessageDigest::sha256();
574            size = 8;
575        } else if alg == HMAC_256_256 {
576            k = PKey::hmac(key.as_slice())?;
577            message_digest = MessageDigest::sha256();
578            size = 32;
579        } else if alg == HMAC_384_384 {
580            k = PKey::hmac(key.as_slice())?;
581            message_digest = MessageDigest::sha384();
582            size = 48;
583        } else if alg == HMAC_512_512 {
584            k = PKey::hmac(key.as_slice())?;
585            message_digest = MessageDigest::sha512();
586            size = 64;
587        } else {
588            return Err(CoseError::InvalidAlg());
589        }
590        let mut verifier = Signer::new(message_digest, &k)?;
591        verifier.update(content.as_slice())?;
592        let s = verifier.sign_to_vec()?;
593        Ok(s[..size].to_vec() == *signature)
594    }
595}
596pub(crate) fn encrypt(
597    alg: i32,
598    key: &Vec<u8>,
599    iv: &Vec<u8>,
600    payload: &Vec<u8>,
601    aead: &Vec<u8>,
602) -> CoseResultWithRet<Vec<u8>> {
603    if [
604        AES_CCM_16_64_128,
605        AES_CCM_16_64_256,
606        AES_CCM_64_64_128,
607        AES_CCM_64_64_256,
608        AES_CCM_16_128_128,
609        AES_CCM_16_128_256,
610        AES_CCM_64_128_128,
611        AES_CCM_64_128_256,
612    ]
613    .contains(&alg)
614    {
615        let cipher;
616        let tag_len;
617        if alg == AES_CCM_16_64_128 {
618            tag_len = 8;
619            cipher = cipher::Cipher::aes_128_ccm();
620        } else if alg == AES_CCM_16_64_256 {
621            tag_len = 8;
622            cipher = cipher::Cipher::aes_256_ccm();
623        } else if alg == AES_CCM_64_64_128 {
624            tag_len = 8;
625            cipher = cipher::Cipher::aes_128_ccm();
626        } else if alg == AES_CCM_64_64_256 {
627            tag_len = 8;
628            cipher = cipher::Cipher::aes_256_ccm();
629        } else if alg == AES_CCM_16_128_128 {
630            tag_len = 16;
631            cipher = cipher::Cipher::aes_128_ccm();
632        } else if alg == AES_CCM_16_128_256 {
633            tag_len = 16;
634            cipher = cipher::Cipher::aes_256_ccm();
635        } else if alg == AES_CCM_64_128_128 {
636            tag_len = 16;
637            cipher = cipher::Cipher::aes_128_ccm();
638        } else {
639            tag_len = 16;
640            cipher = cipher::Cipher::aes_256_ccm();
641        }
642        let mut ctx = CipherCtx::new()?;
643        ctx.encrypt_init(Some(cipher), None, None)?;
644
645        ctx.set_tag_length(tag_len)?;
646        ctx.set_key_length(key.len())?;
647        ctx.set_iv_length(iv.len())?;
648        ctx.encrypt_init(None, Some(&key), Some(&iv))?;
649
650        let mut out = vec![0; payload.len() + cipher.block_size()];
651
652        ctx.set_data_len(payload.len())?;
653
654        ctx.cipher_update(&aead, None)?;
655        let count = ctx.cipher_update(&payload, Some(&mut out))?;
656        let rest = ctx.cipher_final(&mut out[count..])?;
657        out.truncate(count + rest);
658        Ok(out)
659    } else {
660        let mut tag: [u8; 16] = [0; 16];
661        let cipher;
662        if alg == A128GCM {
663            cipher = Cipher::aes_128_gcm();
664        } else if alg == A192GCM {
665            cipher = Cipher::aes_192_gcm();
666        } else if alg == A256GCM {
667            cipher = Cipher::aes_256_gcm();
668        } else if alg == CHACHA20 {
669            cipher = Cipher::chacha20_poly1305();
670        } else {
671            return Err(CoseError::InvalidAlg());
672        }
673        let mut ciphertext = encrypt_aead(cipher, key, Some(iv), aead, payload, &mut tag)?;
674        ciphertext.append(&mut tag.to_vec());
675        Ok(ciphertext)
676    }
677}
678
679pub(crate) fn decrypt(
680    alg: i32,
681    key: &Vec<u8>,
682    iv: &Vec<u8>,
683    ciphertext: &Vec<u8>,
684    aead: &Vec<u8>,
685) -> CoseResultWithRet<Vec<u8>> {
686    if [
687        AES_CCM_16_64_128,
688        AES_CCM_16_64_256,
689        AES_CCM_64_64_128,
690        AES_CCM_64_64_256,
691        AES_CCM_16_128_128,
692        AES_CCM_16_128_256,
693        AES_CCM_64_128_128,
694        AES_CCM_64_128_256,
695    ]
696    .contains(&alg)
697    {
698        let cipher;
699        let tag_len;
700        if alg == AES_CCM_16_64_128 {
701            tag_len = 8;
702            cipher = cipher::Cipher::aes_128_ccm();
703        } else if alg == AES_CCM_16_64_256 {
704            tag_len = 8;
705            cipher = cipher::Cipher::aes_256_ccm();
706        } else if alg == AES_CCM_64_64_128 {
707            tag_len = 8;
708            cipher = cipher::Cipher::aes_128_ccm();
709        } else if alg == AES_CCM_64_64_256 {
710            tag_len = 8;
711            cipher = cipher::Cipher::aes_256_ccm();
712        } else if alg == AES_CCM_16_128_128 {
713            tag_len = 16;
714            cipher = cipher::Cipher::aes_128_ccm();
715        } else if alg == AES_CCM_16_128_256 {
716            tag_len = 16;
717            cipher = cipher::Cipher::aes_256_ccm();
718        } else if alg == AES_CCM_64_128_128 {
719            tag_len = 16;
720            cipher = cipher::Cipher::aes_128_ccm();
721        } else {
722            tag_len = 16;
723            cipher = cipher::Cipher::aes_256_ccm();
724        }
725        let offset = ciphertext.len() - tag_len;
726        let data = ciphertext[..offset].to_vec();
727        let tag = ciphertext[offset..].to_vec();
728        let mut ctx = CipherCtx::new()?;
729        ctx.decrypt_init(Some(cipher), None, None)?;
730
731        ctx.set_tag_length(tag_len)?;
732        ctx.set_key_length(key.len())?;
733        ctx.set_iv_length(iv.len())?;
734        ctx.decrypt_init(None, Some(&key), Some(&iv))?;
735
736        let mut out = vec![0; data.len() + cipher.block_size()];
737
738        ctx.set_tag(&tag)?;
739        ctx.set_data_len(data.len())?;
740
741        ctx.cipher_update(&aead, None)?;
742        let count = ctx.cipher_update(&data, Some(&mut out))?;
743        out.truncate(count);
744        Ok(out)
745    } else {
746        let offset = ciphertext.len() - 16;
747        let cipher;
748        if alg == A128GCM {
749            cipher = Cipher::aes_128_gcm();
750        } else if alg == A192GCM {
751            cipher = Cipher::aes_192_gcm();
752        } else if alg == A256GCM {
753            cipher = Cipher::aes_256_gcm();
754        } else if alg == CHACHA20 {
755            cipher = Cipher::chacha20_poly1305();
756        } else {
757            return Err(CoseError::InvalidAlg());
758        }
759        Ok(decrypt_aead(
760            cipher,
761            key,
762            Some(iv),
763            aead,
764            &ciphertext[..offset],
765            &ciphertext[offset..],
766        )?)
767    }
768}
769
770pub(crate) fn aes_key_wrap(
771    key: &Vec<u8>,
772    size: usize,
773    cek: &Vec<u8>,
774) -> CoseResultWithRet<Vec<u8>> {
775    let aes_key = AesKey::new_encrypt(&key)?;
776    let mut ciphertext = vec![0u8; (size + 8).into()];
777    wrap_key(&aes_key, None, &mut ciphertext, cek)?;
778    Ok(ciphertext)
779}
780
781pub(crate) fn aes_key_unwrap(
782    key: &Vec<u8>,
783    size: usize,
784    cek: &Vec<u8>,
785) -> CoseResultWithRet<Vec<u8>> {
786    let aes_key = AesKey::new_decrypt(&key)?;
787    let mut orig_key = vec![0u8; size];
788    unwrap_key(&aes_key, None, &mut orig_key, cek)?;
789    Ok(orig_key)
790}
791pub(crate) fn rsa_oaep_enc(
792    key: &Vec<u8>,
793    size: usize,
794    cek: &Vec<u8>,
795    alg: &i32,
796) -> CoseResultWithRet<Vec<u8>> {
797    let rsa_key = PKey::public_key_from_der(key)?;
798    let mut enc = PkeyCtx::new(&rsa_key)?;
799    enc.encrypt_init()?;
800    enc.set_rsa_padding(Padding::PKCS1_OAEP)?;
801    if *alg == RSA_OAEP_1 {
802        enc.set_rsa_oaep_md(Md::sha1())?;
803    } else if *alg == RSA_OAEP_256 {
804        enc.set_rsa_oaep_md(Md::sha256())?;
805    } else if *alg == RSA_OAEP_512 {
806        enc.set_rsa_oaep_md(Md::sha512())?;
807    }
808    let mut out: Vec<u8> = Vec::new();
809    enc.encrypt_to_vec(cek, &mut out)?;
810    Ok(out[..size].to_vec())
811}
812
813pub(crate) fn rsa_oaep_dec(
814    key: &Vec<u8>,
815    size: usize,
816    cek: &Vec<u8>,
817    alg: &i32,
818) -> CoseResultWithRet<Vec<u8>> {
819    let rsa_key = PKey::private_key_from_der(key)?;
820    let mut enc = PkeyCtx::new(&rsa_key)?;
821    enc.decrypt_init()?;
822    enc.set_rsa_padding(Padding::PKCS1_OAEP)?;
823    if *alg == RSA_OAEP_1 {
824        enc.set_rsa_oaep_md(Md::sha1())?;
825    } else if *alg == RSA_OAEP_256 {
826        enc.set_rsa_oaep_md(Md::sha256())?;
827    } else if *alg == RSA_OAEP_512 {
828        enc.set_rsa_oaep_md(Md::sha512())?;
829    }
830    let mut out: Vec<u8> = Vec::new();
831    enc.decrypt_to_vec(cek, &mut out)?;
832    Ok(out[..size].to_vec())
833}
834
835pub(crate) fn thumbprint(cert: &Vec<u8>, alg: &i32) -> CoseResultWithRet<Vec<u8>> {
836    if *alg == SHA_256 {
837        let digest = hash(MessageDigest::sha256(), cert)?;
838        Ok(digest.to_vec())
839    } else {
840        Err(CoseError::InvalidAlg())
841    }
842}
843
844pub(crate) fn verify_thumbprint(cert: &Vec<u8>, thumbprint: &Vec<u8>, alg: &i32) -> CoseResult {
845    if *alg == SHA_256 {
846        let digest = hash(MessageDigest::sha256(), &cert)?;
847        assert_eq!(digest.to_vec(), *thumbprint);
848    } else {
849        return Err(CoseError::InvalidAlg());
850    }
851    Ok(())
852}
853
854pub(crate) fn verify_chain(chain: &Vec<Vec<u8>>) -> CoseResult {
855    let stack = Stack::new()?;
856    for i in (1..chain.len()).rev() {
857        let cert = X509::from_der(&chain[i])?;
858        let to_ver = X509::from_der(&chain[i - 1])?;
859        let mut store_bldr = X509StoreBuilder::new()?;
860        store_bldr.add_cert(cert)?;
861        let store = store_bldr.build();
862        let mut context = X509StoreContext::new()?;
863
864        if !context.init(&store, &to_ver, &stack, |c| c.verify_cert())? {
865            return Err(CoseError::InvalidKeyChain());
866        }
867    }
868    Ok(())
869}
870
871pub(crate) fn ecdh_derive_key(
872    crv_rec: Option<i32>,
873    crv_send: Option<i32>,
874    receiver_key: &Vec<u8>,
875    sender_key: &Vec<u8>,
876) -> CoseResultWithRet<Vec<u8>> {
877    let pkey_rec: PKey<Public>;
878    let pkey_send: PKey<Private>;
879    if crv_rec != None {
880        let crv = crv_rec.unwrap();
881        if [keys::X448, keys::X25519].contains(&crv) {
882            let id_pkey;
883            if crv == keys::X448 {
884                id_pkey = Id::X448;
885            } else {
886                id_pkey = Id::X25519;
887            }
888            pkey_rec = PKey::public_key_from_raw_bytes(receiver_key, id_pkey)?;
889        } else {
890            let mut group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
891            if crv == keys::P_256 {
892                group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
893            } else if crv == keys::P_384 {
894                group = EcGroup::from_curve_name(Nid::SECP384R1)?;
895            } else if crv == keys::P_521 {
896                group = EcGroup::from_curve_name(Nid::SECP521R1)?;
897            }
898            let mut ctx = BigNumContext::new()?;
899            let point = EcPoint::from_bytes(&group, receiver_key, &mut ctx)?;
900            pkey_rec = PKey::from_ec_key(EcKey::from_public_key(&group, &point)?)?;
901        }
902    } else {
903        let x5 = X509::from_der(&receiver_key)?;
904        pkey_rec = x5.public_key()?;
905    }
906
907    if crv_send != None {
908        let crv = crv_send.unwrap();
909        if [keys::X448, keys::X25519].contains(&crv) {
910            let id_pkey;
911            if crv == keys::X448 {
912                id_pkey = Id::X448;
913            } else {
914                id_pkey = Id::X25519;
915            }
916            pkey_send = PKey::private_key_from_raw_bytes(sender_key, id_pkey)?;
917        } else {
918            let number = BigNum::from_slice(&sender_key)?;
919            let mut group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
920            if crv == keys::P_256 {
921                group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
922            } else if crv == keys::P_384 {
923                group = EcGroup::from_curve_name(Nid::SECP384R1)?;
924            } else if crv == keys::P_521 {
925                group = EcGroup::from_curve_name(Nid::SECP521R1)?;
926            }
927            pkey_send = PKey::from_ec_key(EcKey::from_private_components(
928                &group,
929                &number,
930                &EcPoint::new(&group).unwrap(),
931            )?)?;
932        }
933    } else {
934        pkey_send = PKey::private_key_from_der(sender_key)?;
935    }
936    let mut deriver = Deriver::new(&pkey_send)?;
937    deriver.set_peer(&pkey_rec)?;
938    Ok(deriver.derive_to_vec()?)
939}
940
941pub(crate) fn hkdf(
942    length: usize,
943    ikm: &Vec<u8>,
944    salt_input: Option<&Vec<u8>>,
945    info_input: &mut Vec<u8>,
946    alg: i32,
947) -> CoseResultWithRet<Vec<u8>> {
948    if [DIRECT_HKDF_AES_128, DIRECT_HKDF_AES_256].contains(&alg) {
949        let mut t = Vec::new();
950        let mut okm = Vec::new();
951        let mut i = 0;
952        while okm.len() < length {
953            i += 1;
954            let mut info_tmp = info_input.clone();
955            t.append(&mut info_tmp);
956            t.append(&mut vec![i]);
957            let mut padded: Vec<u8> = t;
958            if padded.len() % 16 != 0 {
959                padded.append(&mut vec![0; 16 - (padded.len() % 16)]);
960            }
961            let cipher;
962            let cipher_size;
963            if alg == DIRECT_HKDF_AES_128 {
964                cipher = Cipher::aes_128_cbc();
965                cipher_size = 16;
966            } else {
967                cipher = Cipher::aes_256_cbc();
968                cipher_size = 32;
969            }
970            let index = padded.len() - 16;
971            let s = encr(cipher, &ikm, None, &padded).unwrap();
972            t = s[index..index + 16].to_vec();
973            let mut temp = t.clone();
974            okm.append(&mut temp);
975        }
976        return Ok(okm[..length].to_vec());
977    }
978
979    let mut digest = Md::sha256();
980    if [DIRECT_HKDF_SHA_512, ECDH_ES_HKDF_512, ECDH_SS_HKDF_512].contains(&alg) {
981        digest = Md::sha512();
982    }
983    let salt = match salt_input {
984        Some(v) => v.to_vec(),
985        None => vec![0; length],
986    };
987    let mut ctx = PkeyCtx::new_id(Id::HKDF)?;
988    ctx.derive_init()?;
989    ctx.set_hkdf_md(&digest)?;
990    ctx.set_hkdf_key(ikm)?;
991    ctx.set_hkdf_salt(&salt)?;
992    ctx.add_hkdf_info(info_input)?;
993    let mut out = vec![0; length];
994    ctx.derive(Some(&mut out))?;
995    Ok(out)
996}
997
998pub(crate) fn get_cek_size(alg: &i32) -> CoseResultWithRet<usize> {
999    if K16_ALGS.contains(alg) {
1000        Ok(16)
1001    } else if K32_ALGS.contains(alg) {
1002        Ok(32)
1003    } else if K24_ALGS.contains(alg) {
1004        Ok(24)
1005    } else if HMAC_384_384 == *alg {
1006        Ok(48)
1007    } else if HMAC_512_512 == *alg {
1008        Ok(64)
1009    } else {
1010        Err(CoseError::InvalidAlg())
1011    }
1012}
1013pub(crate) fn gen_random_key(alg: &i32) -> CoseResultWithRet<Vec<u8>> {
1014    if K16_ALGS.contains(alg) {
1015        Ok(rand::thread_rng().gen::<[u8; 16]>().to_vec())
1016    } else if K32_ALGS.contains(alg) {
1017        Ok(rand::thread_rng().gen::<[u8; 32]>().to_vec())
1018    } else if K24_ALGS.contains(alg) {
1019        Ok(rand::thread_rng().gen::<[u8; 24]>().to_vec())
1020    } else if HMAC_384_384 == *alg {
1021        let mut out = rand::thread_rng().gen::<[u8; 32]>().to_vec();
1022        out.append(&mut rand::thread_rng().gen::<[u8; 16]>().to_vec());
1023        Ok(out)
1024    } else if HMAC_512_512 == *alg {
1025        let mut out = rand::thread_rng().gen::<[u8; 32]>().to_vec();
1026        out.append(&mut rand::thread_rng().gen::<[u8; 32]>().to_vec());
1027        Ok(out)
1028    } else {
1029        Err(CoseError::InvalidAlg())
1030    }
1031}
1032
1033pub(crate) fn get_iv_size(alg: &i32) -> CoseResultWithRet<usize> {
1034    if [A128GCM, A192GCM, A256GCM, CHACHA20].contains(alg) {
1035        Ok(12)
1036    } else if [
1037        AES_CCM_16_64_128,
1038        AES_CCM_16_64_256,
1039        AES_CCM_16_128_256,
1040        AES_CCM_16_128_256,
1041    ]
1042    .contains(alg)
1043    {
1044        Ok(13)
1045    } else if [
1046        AES_CCM_64_64_128,
1047        AES_CCM_64_64_256,
1048        AES_CCM_64_128_256,
1049        AES_CCM_64_128_256,
1050    ]
1051    .contains(alg)
1052    {
1053        Ok(7)
1054    } else {
1055        Err(CoseError::InvalidAlg())
1056    }
1057}
1058
1059pub(crate) fn gen_iv(
1060    partial_iv: &Vec<u8>,
1061    base_iv: &Vec<u8>,
1062    alg: &i32,
1063) -> CoseResultWithRet<Vec<u8>> {
1064    let size = get_iv_size(alg)?;
1065    let mut pv = partial_iv.clone();
1066    let mut padded = vec![0; size - pv.len()];
1067    padded.append(&mut pv);
1068    let mut iv = Vec::new();
1069    for i in 0..padded.len() {
1070        if i < base_iv.len() {
1071            iv.push(padded[i] ^ base_iv[i]);
1072        } else {
1073            iv.push(padded[i]);
1074        }
1075    }
1076    Ok(iv)
1077}