use crate::algs;
use crate::errors::{CoseError, CoseResultWithRet};
use cbor::Encoder;
pub(crate) const SIGNATURE: &str = "Signature";
pub(crate) const SIGNATURE1: &str = "Signature1";
pub(crate) const COUNTER_SIGNATURE: &str = "CounterSignature";
const SIGNATURE1_LEN: usize = 4;
const SIGNATURE_LEN: usize = 5;
const COUNTER_SIGNATURE_LEN: usize = 5;
pub(crate) const MAC: &str = "MAC";
pub(crate) const MAC0: &str = "MAC0";
const MAC_ALL: [&str; 2] = [MAC, MAC0];
const MAC_STRUCT_LEN: usize = 4;
pub(crate) const ENCRYPT: &str = "Encrypt";
pub(crate) const ENCRYPT0: &str = "Encrypt0";
pub(crate) const ENCRYPT_RECIPIENT: &str = "Enc_Recipient";
pub(crate) const MAC_RECIPIENT: &str = "Mac_Recipient";
pub(crate) const REC_RECIPIENT: &str = "Rec_Recipient";
const ENC_ALL: [&str; 5] = [
ENCRYPT,
ENCRYPT0,
ENCRYPT_RECIPIENT,
MAC_RECIPIENT,
REC_RECIPIENT,
];
const ENC_STRUCT_LEN: usize = 3;
const STRUCT_LEN: usize = 5;
const PARTY_STRUCT_LEN: usize = 3;
const SUPP_PUB_STRUCT_LEN: usize = 3;
pub(crate) fn gen_sig(
key: &Vec<u8>,
alg: &i32,
crv: &Option<i32>,
external_aad: &Vec<u8>,
context: &str,
body_protected: &Vec<u8>,
sign_protected: &Vec<u8>,
payload: &Vec<u8>,
) -> CoseResultWithRet<Vec<u8>> {
let mut e = Encoder::new(Vec::new());
if context == SIGNATURE {
e.array(SIGNATURE_LEN)?;
e.text(SIGNATURE)?;
e.bytes(body_protected.as_slice())?;
e.bytes(sign_protected.as_slice())?;
} else if context == SIGNATURE1 {
e.array(SIGNATURE1_LEN)?;
e.text(SIGNATURE1)?;
e.bytes(body_protected.as_slice())?;
} else if context == COUNTER_SIGNATURE {
e.array(COUNTER_SIGNATURE_LEN)?;
e.text(COUNTER_SIGNATURE)?;
e.bytes(body_protected.as_slice())?;
e.bytes(sign_protected.as_slice())?;
} else {
return Err(CoseError::InvalidContext());
}
e.bytes(external_aad.as_slice())?;
e.bytes(payload.as_slice())?;
algs::sign(*alg, *crv, &key, &e.into_writer().to_vec())
}
pub(crate) fn get_to_sign(
external_aad: &Vec<u8>,
context: &str,
body_protected: &Vec<u8>,
sign_protected: &Vec<u8>,
payload: &Vec<u8>,
) -> CoseResultWithRet<Vec<u8>> {
let mut e = Encoder::new(Vec::new());
if context == SIGNATURE {
e.array(SIGNATURE_LEN)?;
e.text(SIGNATURE)?;
e.bytes(body_protected.as_slice())?;
e.bytes(sign_protected.as_slice())?;
} else if context == SIGNATURE1 {
e.array(SIGNATURE1_LEN)?;
e.text(SIGNATURE1)?;
e.bytes(body_protected.as_slice())?;
} else if context == COUNTER_SIGNATURE {
e.array(COUNTER_SIGNATURE_LEN)?;
e.text(COUNTER_SIGNATURE)?;
e.bytes(body_protected.as_slice())?;
e.bytes(sign_protected.as_slice())?;
} else {
return Err(CoseError::InvalidContext());
}
e.bytes(external_aad.as_slice())?;
e.bytes(payload.as_slice())?;
Ok(e.into_writer().to_vec())
}
pub(crate) fn verify_sig(
key: &Vec<u8>,
alg: &i32,
crv: &Option<i32>,
external_aad: &Vec<u8>,
context: &str,
body_protected: &Vec<u8>,
sign_protected: &Vec<u8>,
payload: &Vec<u8>,
signature: &Vec<u8>,
) -> CoseResultWithRet<bool> {
let mut e = Encoder::new(Vec::new());
if context == SIGNATURE {
e.array(SIGNATURE_LEN)?;
e.text(SIGNATURE)?;
e.bytes(body_protected.as_slice())?;
e.bytes(sign_protected.as_slice())?;
} else if context == SIGNATURE1 {
e.array(SIGNATURE1_LEN)?;
e.text(SIGNATURE1)?;
e.bytes(body_protected.as_slice())?;
} else if context == COUNTER_SIGNATURE {
e.array(COUNTER_SIGNATURE_LEN)?;
e.text(COUNTER_SIGNATURE)?;
e.bytes(body_protected.as_slice())?;
e.bytes(sign_protected.as_slice())?;
} else {
return Err(CoseError::InvalidContext());
}
e.bytes(external_aad.as_slice())?;
e.bytes(payload.as_slice())?;
Ok(algs::verify(
*alg,
*crv,
&key,
&e.into_writer().to_vec(),
&signature,
)?)
}
pub(crate) fn gen_mac(
key: &Vec<u8>,
alg: &i32,
aead: &Vec<u8>,
context: &str,
body_protected: &Vec<u8>,
payload: &Vec<u8>,
) -> CoseResultWithRet<Vec<u8>> {
let mut e = Encoder::new(Vec::new());
if MAC_ALL.contains(&context) {
e.array(MAC_STRUCT_LEN)?;
e.text(context)?;
e.bytes(body_protected.as_slice())?;
e.bytes(aead.as_slice())?;
e.bytes(payload.as_slice())?;
algs::mac(*alg, &key, &e.into_writer().to_vec())
} else {
Err(CoseError::InvalidContext())
}
}
pub(crate) fn verify_mac(
key: &Vec<u8>,
alg: &i32,
aead: &Vec<u8>,
context: &str,
body_protected: &Vec<u8>,
tag: &Vec<u8>,
payload: &Vec<u8>,
) -> CoseResultWithRet<bool> {
let mut e = Encoder::new(Vec::new());
if MAC_ALL.contains(&context) {
e.array(MAC_STRUCT_LEN)?;
e.text(context)?;
e.bytes(body_protected.as_slice())?;
e.bytes(aead.as_slice())?;
e.bytes(payload.as_slice())?;
algs::mac_verify(*alg, &key, &e.into_writer().to_vec(), &tag)
} else {
Err(CoseError::InvalidContext())
}
}
pub(crate) fn gen_cipher(
key: &Vec<u8>,
alg: &i32,
iv: &Vec<u8>,
aead: &Vec<u8>,
context: &str,
body_protected: &Vec<u8>,
payload: &Vec<u8>,
) -> CoseResultWithRet<Vec<u8>> {
let mut e = Encoder::new(Vec::new());
if ENC_ALL.contains(&context) {
e.array(ENC_STRUCT_LEN)?;
e.text(context)?;
e.bytes(body_protected.as_slice())?;
e.bytes(aead.as_slice())?;
algs::encrypt(*alg, &key, &iv, &payload, &e.into_writer().to_vec())
} else {
Err(CoseError::InvalidContext())
}
}
pub(crate) fn dec_cipher(
key: &Vec<u8>,
alg: &i32,
iv: &Vec<u8>,
aead: &Vec<u8>,
context: &str,
body_protected: &Vec<u8>,
ciphertext: &Vec<u8>,
) -> CoseResultWithRet<Vec<u8>> {
let mut e = Encoder::new(Vec::new());
if ENC_ALL.contains(&context) {
e.array(ENC_STRUCT_LEN)?;
e.text(context)?;
e.bytes(body_protected.as_slice())?;
e.bytes(aead.as_slice())?;
algs::decrypt(*alg, &key, &iv, &ciphertext, &e.into_writer().to_vec())
} else {
Err(CoseError::InvalidContext())
}
}
pub(crate) fn gen_kdf(
alg: &i32,
party_u_identity: &Option<Vec<u8>>,
party_u_nonce: &Option<Vec<u8>>,
party_u_other: &Option<Vec<u8>>,
party_v_identity: &Option<Vec<u8>>,
party_v_nonce: &Option<Vec<u8>>,
party_v_other: &Option<Vec<u8>>,
key_data_len: u16,
protected: &Vec<u8>,
other: &Option<Vec<u8>>,
supp_priv_info: &Option<Vec<u8>>,
) -> CoseResultWithRet<Vec<u8>> {
let mut e = Encoder::new(Vec::new());
if *supp_priv_info == None {
e.array(STRUCT_LEN - 1)?;
} else {
e.array(STRUCT_LEN)?;
}
e.i32(*alg)?;
e.array(PARTY_STRUCT_LEN)?;
if *party_u_identity == None {
e.null()?;
} else {
e.bytes(&party_u_identity.as_ref().unwrap())?;
}
if *party_u_nonce == None {
e.null()?;
} else {
e.bytes(&party_u_nonce.as_ref().unwrap())?;
}
if *party_u_other == None {
e.null()?;
} else {
e.bytes(&party_u_other.as_ref().unwrap())?;
}
e.array(PARTY_STRUCT_LEN)?;
if *party_v_identity == None {
e.null()?;
} else {
e.bytes(&party_v_identity.as_ref().unwrap())?;
}
if *party_v_nonce == None {
e.null()?;
} else {
e.bytes(&party_v_nonce.as_ref().unwrap())?;
}
if *party_v_other == None {
e.null()?;
} else {
e.bytes(&party_v_other.as_ref().unwrap())?;
}
if *other == None {
e.array(SUPP_PUB_STRUCT_LEN - 1)?;
} else {
e.array(SUPP_PUB_STRUCT_LEN)?;
}
e.u16(key_data_len)?;
e.bytes(&protected)?;
if *other != None {
e.bytes(other.as_ref().unwrap())?;
}
if *supp_priv_info != None {
e.bytes(supp_priv_info.as_ref().unwrap())?;
}
Ok(e.into_writer().to_vec())
}