blob: c4ad1943157f1a4e6eeb7396c918c82086929bfb [file] [log] [blame]
//! The cert validator library provides validation functions for the CBOR-CDDL
//! based certificate request, allowing validation of BCC certificate chain,
//! deviceinfo among other things.
pub mod bcc;
pub mod deviceinfo;
pub mod dice;
pub mod publickey;
pub mod valueas;
use anyhow::{Context, Result};
use ciborium::{de::from_reader, value::Value};
/// Reads the provided binary cbor-encoded file and returns a
/// ciborium::Value struct wrapped in Result.
pub fn file_value(fname: &str) -> Result<Value> {
let f = std::fs::File::open(fname)?;
from_reader(f).with_context(|| format!("Decoding {}", fname))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::valueas::ValueAs;
use coset::{iana, Header, Label, RegisteredLabel};
#[test]
fn test_bcc_payload_check() {
let payload = bcc::entry::Payload::from_sign1(
&bcc::entry::read("testdata/open-dice/_CBOR_Ed25519_cert_full_cert_chain_0.cert")
.unwrap(),
);
assert!(payload.is_ok());
let payload = payload.unwrap();
assert!(payload.check().is_ok());
}
#[test]
fn test_bcc_payload_check_sign1() {
let payload = bcc::entry::Payload::from_sign1(
&bcc::entry::read("testdata/open-dice/_CBOR_Ed25519_cert_full_cert_chain_0.cert")
.unwrap(),
);
assert!(payload.is_ok());
let payload = payload.unwrap().check_sign1(
&bcc::entry::read("testdata/open-dice/_CBOR_Ed25519_cert_full_cert_chain_1.cert")
.unwrap(),
);
assert!(payload.is_ok());
let payload = payload.unwrap().check_sign1(
&bcc::entry::read("testdata/open-dice/_CBOR_Ed25519_cert_full_cert_chain_2.cert")
.unwrap(),
);
assert!(payload.is_ok());
}
#[test]
fn test_check_sign1_cert_chain() {
let arr: Vec<String> = vec![
String::from("testdata/open-dice/_CBOR_Ed25519_cert_full_cert_chain_0.cert"),
String::from("testdata/open-dice/_CBOR_Ed25519_cert_full_cert_chain_1.cert"),
String::from("testdata/open-dice/_CBOR_Ed25519_cert_full_cert_chain_2.cert"),
];
assert!(bcc::entry::check_sign1_cert_chain(&arr).is_ok());
}
#[test]
fn test_check_sign1_chain_array() {
let cbor_file = &file_value("testdata/open-dice/_CBOR_bcc_entry_cert_array.cert").unwrap();
let cbor_arr = ValueAs::as_array(cbor_file).unwrap();
assert!(cbor_arr.len() == 3);
assert!(bcc::entry::check_sign1_chain_array(cbor_arr).is_ok());
}
#[test]
fn deviceinfo_validation() {
let val = &file_value("testdata/device-info/_CBOR_device_info_0.cert").unwrap();
let deviceinfo = deviceinfo::extract(val);
assert!(deviceinfo.is_ok());
assert!(deviceinfo::check(deviceinfo.unwrap()).is_ok());
}
#[test]
fn test_check_bcc_entry_protected_header() -> Result<()> {
let eddsa = Some(coset::Algorithm::Assigned(iana::Algorithm::EdDSA));
let header = Header { alg: (&eddsa).clone(), ..Default::default() };
bcc::entry::check_protected_header(&eddsa, &header).context("Only alg allowed")?;
let header = Header { alg: Some(coset::Algorithm::PrivateUse(1000)), ..Default::default() };
assert!(bcc::entry::check_protected_header(&eddsa, &header).is_err());
let mut header = Header { alg: (&eddsa).clone(), ..Default::default() };
header.rest.push((Label::Int(1000), Value::from(2000u16)));
bcc::entry::check_protected_header(&eddsa, &header).context("non-crit header allowed")?;
let mut header = Header { alg: (&eddsa).clone(), ..Default::default() };
header.crit.push(RegisteredLabel::Assigned(iana::HeaderParameter::Alg));
bcc::entry::check_protected_header(&eddsa, &header).context("OK to say alg is critical")?;
let mut header = Header { alg: (&eddsa).clone(), ..Default::default() };
header.crit.push(RegisteredLabel::Assigned(iana::HeaderParameter::CounterSignature));
assert!(bcc::entry::check_protected_header(&eddsa, &header).is_err());
Ok(())
}
}