mod common;
use common::*;
use cose2::{
cwt::{Claims, Validator, ValidatorOptions},
iana, tag, CoseMap, Encrypt0Message, EncryptMessage, Header, KdfContext, Key, Label,
Mac0Message, MacMessage, PartyInfo, Recipient, Sign1Message, SignMessage, SuppPubInfo, Value,
};
fn direct_recipient() -> Recipient {
let mut r = Recipient::new();
r.unprotected.set_alg(iana::AlgorithmDirect);
r.ciphertext = Some(vec![]);
r
}
#[test]
fn minimal_sign_uses_trait_defaults() {
let mut msg = SignMessage::new(Some(b"x".to_vec()));
let signers: [&dyn cose2::Signer; 1] = [&MinimalSigner];
let encoded = msg.sign_and_encode(&signers, None).unwrap();
assert!(msg.signatures[0].protected.is_empty());
assert!(msg.signatures[0].unprotected.is_empty());
let verifiers: [&dyn cose2::Verifier; 1] = [&MinimalVerifier];
assert!(SignMessage::verify_and_decode(&verifiers, &encoded, None).is_ok());
let mut s1 = Sign1Message::new(Some(b"y".to_vec()));
let enc = s1.sign_and_encode(&MinimalSigner, None).unwrap();
assert!(Sign1Message::verify_and_decode(&MinimalVerifier, &enc, None).is_ok());
}
#[test]
fn minimal_mac_and_encrypt_use_trait_defaults() {
let mut mac = Mac0Message::new(Some(b"x".to_vec()));
let enc = mac.compute_and_encode(&MinimalMacer, None).unwrap();
assert!(Mac0Message::verify_and_decode(&MinimalMacer, &enc, None).is_ok());
let mut e = Encrypt0Message::new(Some(b"hello".to_vec()));
e.unprotected
.insert(iana::HeaderParameterIV, vec![1u8, 2, 3, 4]);
let encoded = e.encrypt_and_encode(&MinimalEncryptor, None).unwrap();
let dec = Encrypt0Message::decrypt_and_decode(&MinimalEncryptor, &encoded, None).unwrap();
assert_eq!(dec.payload.as_deref(), Some(&b"hello"[..]));
}
#[test]
fn sign1_alg_already_present_and_matching() {
let signer = MockSigner::new(iana::AlgorithmES256, b"k");
let verifier = MockVerifier::new(iana::AlgorithmES256, b"k");
let mut msg = Sign1Message::new(Some(b"x".to_vec()));
msg.protected
.insert(iana::HeaderParameterAlg, iana::AlgorithmES256);
let encoded = msg.sign_and_encode(&signer, None).unwrap();
assert!(Sign1Message::verify_and_decode(&verifier, &encoded, None).is_ok());
}
#[test]
fn label_visit_string_from_indefinite_text() {
let indef = [0x7f, 0x61, 0x61, 0xff];
let label: Label = cbor2::from_slice(&indef).unwrap();
assert_eq!(label, Label::Text("a".into()));
}
#[test]
fn cosemap_duplicate_key_detected_by_visitor() {
let dup = [0xa2u8, 0x01, 0x01, 0x01, 0x02];
let err = CoseMap::from_slice(&dup).unwrap_err();
assert!(format!("{err}").contains("duplicate"));
}
#[test]
fn cosemap_expecting_on_wrong_type() {
assert!(CoseMap::from_slice(&[0x01]).is_err());
}
#[test]
fn key_ops_integer_out_of_range() {
let mut key = Key::new();
key.insert(iana::KeyParameterKeyOps, vec![Value::from(u64::MAX)]);
assert!(key.ops().is_err());
}
#[test]
fn recipient_expecting_on_wrong_type() {
assert!(Recipient::from_slice(&[0x01]).is_err());
}
#[test]
fn recipient_invalid_protected_bytes() {
let body = cbor2::to_vec(&(
serde_bytes::Bytes::new(&[0xff]),
Header::new(),
Some(serde_bytes::Bytes::new(&[])),
))
.unwrap();
assert!(Recipient::from_slice(&body).is_err());
}
#[test]
fn recipient_rejects_null_or_extra_nested_recipients_slot() {
let null_nested = cbor2::to_vec(&(
serde_bytes::Bytes::new(&[]),
Header::new(),
Option::<&serde_bytes::Bytes>::None,
Option::<Vec<Recipient>>::None,
))
.unwrap();
assert!(Recipient::from_slice(&null_nested).is_err());
let extra = cbor2::to_vec(&(
serde_bytes::Bytes::new(&[]),
Header::new(),
Option::<&serde_bytes::Bytes>::None,
Vec::<Recipient>::new(),
true,
))
.unwrap();
assert!(Recipient::from_slice(&extra).is_err());
}
#[test]
fn supp_pub_info_expecting_on_wrong_type() {
assert!(cbor2::from_slice::<SuppPubInfo>(&[0x01]).is_err());
}
#[test]
fn supp_pub_info_invalid_protected_bytes() {
let body = cbor2::to_vec(&(128u64, serde_bytes::Bytes::new(&[0xff]))).unwrap();
assert!(cbor2::from_slice::<SuppPubInfo>(&body).is_err());
}
#[test]
fn supp_pub_info_rejects_null_other_or_extra_elements() {
let null_other = cbor2::to_vec(&(
128u64,
serde_bytes::Bytes::new(&[]),
Option::<&serde_bytes::Bytes>::None,
))
.unwrap();
assert!(cbor2::from_slice::<SuppPubInfo>(&null_other).is_err());
let extra = cbor2::to_vec(&(
128u64,
serde_bytes::Bytes::new(&[]),
serde_bytes::Bytes::new(b"other"),
true,
))
.unwrap();
assert!(cbor2::from_slice::<SuppPubInfo>(&extra).is_err());
}
#[test]
fn kdf_context_expecting_on_wrong_type() {
assert!(KdfContext::from_slice(&[0x01]).is_err());
}
#[test]
fn kdf_context_rejects_null_supp_priv_or_extra_elements() {
let null_priv = cbor2::to_vec(&(
1i64,
PartyInfo::default(),
PartyInfo::default(),
SuppPubInfo::default(),
Option::<&serde_bytes::Bytes>::None,
))
.unwrap();
assert!(KdfContext::from_slice(&null_priv).is_err());
let extra = cbor2::to_vec(&(
1i64,
PartyInfo::default(),
PartyInfo::default(),
SuppPubInfo::default(),
serde_bytes::Bytes::new(b"private"),
true,
))
.unwrap();
assert!(KdfContext::from_slice(&extra).is_err());
}
#[test]
fn encrypt_iv_size_mismatch() {
let enc = MockEncryptor::new(iana::AlgorithmA128GCM, b"", 12);
let mut msg = EncryptMessage::new(Some(b"x".to_vec()));
msg.unprotected
.insert(iana::HeaderParameterIV, vec![0u8; 4]); msg.recipients.push(direct_recipient());
assert!(msg.encrypt(&enc, None).is_err());
}
#[test]
fn encrypt_decode_without_recipients_and_with_detached_ciphertext() {
let no_recip = cbor2::to_vec(&(
serde_bytes::Bytes::new(&[]),
Header::new(),
Some(serde_bytes::Bytes::new(b"ct")),
Vec::<Value>::new(),
))
.unwrap();
let tagged = tag::with_tag(tag::ENCRYPT_PREFIX, &no_recip);
assert!(EncryptMessage::from_slice(&tagged).is_err());
let recip = direct_recipient();
let no_ct = cbor2::to_canonical_vec(&(
serde_bytes::Bytes::new(&[]),
Header::new(),
Option::<&serde_bytes::Bytes>::None,
vec![recip],
))
.unwrap();
let tagged = tag::with_tag(tag::ENCRYPT_PREFIX, &no_ct);
let msg = EncryptMessage::from_slice(&tagged).unwrap();
assert!(msg.is_ciphertext_detached());
}
#[test]
fn encrypt_ciphertext_accessor() {
let enc = MockEncryptor::new(iana::AlgorithmA128GCM, b"", 12);
let mut msg = EncryptMessage::new(Some(b"data".to_vec()));
msg.unprotected
.insert(iana::HeaderParameterIV, vec![5u8; 12]);
msg.recipients.push(direct_recipient());
msg.encrypt(&enc, None).unwrap();
assert!(!msg.ciphertext().is_empty());
}
#[test]
fn mac_decode_without_recipients() {
let body = cbor2::to_vec(&(
serde_bytes::Bytes::new(&[]),
Header::new(),
Some(serde_bytes::Bytes::new(b"p")),
serde_bytes::Bytes::new(b"t"),
Vec::<Value>::new(),
))
.unwrap();
let tagged = tag::with_tag(tag::MAC_PREFIX, &body);
assert!(MacMessage::from_slice(&tagged).is_err());
}
#[test]
fn mac_tag_accessor() {
let macer = MockMacer::new(iana::AlgorithmHMAC_256_256, b"m");
let mut msg = MacMessage::new(Some(b"x".to_vec()));
msg.recipients.push(direct_recipient());
msg.compute(&macer, None).unwrap();
assert!(!msg.tag().is_empty());
}
#[test]
fn sign_cleared_signatures_branches() {
let s1 = MockSigner::new(iana::AlgorithmES256, b"a");
let v1 = MockVerifier::new(iana::AlgorithmES256, b"a");
let mut msg = SignMessage::new(Some(b"x".to_vec()));
let signers: [&dyn cose2::Signer; 1] = [&s1];
let encoded = msg.sign_and_encode(&signers, None).unwrap();
let mut decoded = SignMessage::from_slice(&encoded).unwrap();
decoded.signatures.clear();
assert!(decoded.to_vec().is_err());
let verifiers: [&dyn cose2::Verifier; 1] = [&v1];
assert!(decoded.verify(&verifiers, None).is_err());
}
#[test]
fn validator_iat_in_past_is_accepted() {
let v = Validator::new(ValidatorOptions {
expect_issued_in_the_past: true,
clock_skew_secs: 0,
fixed_now: Some(1_000),
..Default::default()
})
.unwrap();
let claims = Claims {
expiration: Some(2_000),
issued_at: Some(900), ..Default::default()
};
assert!(v.validate(&claims).is_ok());
let no_iat = Claims {
expiration: Some(2_000),
..Default::default()
};
assert!(v.validate(&no_iat).is_ok());
}
#[test]
fn verify_with_alg_but_no_alg_in_protected() {
let signer = MockSigner::new(0, b"k");
let verifier = MockVerifier::new(iana::AlgorithmES256, b"k");
let mut msg = Sign1Message::new(Some(b"x".to_vec()));
let encoded = msg.sign_and_encode(&signer, None).unwrap();
assert!(msg.protected.is_empty());
assert!(Sign1Message::verify_and_decode(&verifier, &encoded, None).is_ok());
}
#[test]
fn recipient_missing_elements() {
assert!(Recipient::from_slice(&[0x80]).is_err());
assert!(Recipient::from_slice(&[0x81, 0x40]).is_err());
assert!(Recipient::from_slice(&[0x82, 0x40, 0xa0]).is_err());
}
#[test]
fn supp_pub_info_missing_elements() {
assert!(cbor2::from_slice::<SuppPubInfo>(&[0x80]).is_err());
assert!(cbor2::from_slice::<SuppPubInfo>(&[0x81, 0x18, 0x80]).is_err());
}
#[test]
fn kdf_context_missing_elements() {
use cose2::PartyInfo;
let b = cbor2::to_vec(&(1i64,)).unwrap();
assert!(KdfContext::from_slice(&b).is_err());
let b = cbor2::to_vec(&(1i64, PartyInfo::default())).unwrap();
assert!(KdfContext::from_slice(&b).is_err());
let b = cbor2::to_vec(&(1i64, PartyInfo::default(), PartyInfo::default())).unwrap();
assert!(KdfContext::from_slice(&b).is_err());
}
#[test]
fn encrypt_missing_iv() {
let enc = MockEncryptor::new(iana::AlgorithmA128GCM, b"", 12);
let mut msg = EncryptMessage::new(Some(b"x".to_vec()));
msg.recipients.push(direct_recipient());
assert!(msg.encrypt(&enc, None).is_err());
}
#[test]
fn visitor_expecting_messages() {
use serde::de::value::{Error as VErr, I32Deserializer};
use serde::de::IntoDeserializer;
use serde::Deserialize;
let de: I32Deserializer<VErr> = 7i32.into_deserializer();
assert!(CoseMap::deserialize(de).is_err());
let de: I32Deserializer<VErr> = 7i32.into_deserializer();
assert!(Recipient::deserialize(de).is_err());
let de: I32Deserializer<VErr> = 7i32.into_deserializer();
assert!(SuppPubInfo::deserialize(de).is_err());
let de: I32Deserializer<VErr> = 7i32.into_deserializer();
assert!(KdfContext::deserialize(de).is_err());
}