259 lines
8.3 KiB
Rust
259 lines
8.3 KiB
Rust
extern crate moz_cbor as cbor;
|
|
extern crate cose;
|
|
|
|
#[macro_use(defer)]
|
|
extern crate scopeguard;
|
|
|
|
mod nss;
|
|
mod test_nss;
|
|
mod test_setup;
|
|
mod util_test;
|
|
|
|
use util_test::{sign, verify_signature};
|
|
use test_setup as test;
|
|
use std::str::FromStr;
|
|
use cose::{CoseError, SignatureAlgorithm};
|
|
|
|
// All keys here are from pykey.py/pycert.py from mozilla-central.
|
|
// Certificates can be generated with tools/certs/certs.sh and mozilla-central.
|
|
|
|
#[derive(Debug)]
|
|
pub struct SignatureParameters<'a> {
|
|
certificate: &'a [u8],
|
|
algorithm: SignatureAlgorithm,
|
|
pkcs8: &'a [u8],
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Signature<'a> {
|
|
parameter: &'a SignatureParameters<'a>,
|
|
signature_bytes: Vec<u8>,
|
|
}
|
|
|
|
const P256_PARAMS: SignatureParameters = SignatureParameters {
|
|
certificate: &test::P256_EE,
|
|
algorithm: SignatureAlgorithm::ES256,
|
|
pkcs8: &test::PKCS8_P256_EE,
|
|
};
|
|
const P384_PARAMS: SignatureParameters = SignatureParameters {
|
|
certificate: &test::P384_EE,
|
|
algorithm: SignatureAlgorithm::ES384,
|
|
pkcs8: &test::PKCS8_P384_EE,
|
|
};
|
|
const P521_PARAMS: SignatureParameters = SignatureParameters {
|
|
certificate: &test::P521_EE,
|
|
algorithm: SignatureAlgorithm::ES512,
|
|
pkcs8: &test::PKCS8_P521_EE,
|
|
};
|
|
|
|
fn test_verify(payload: &[u8], cert_chain: &[&[u8]], params_vec: Vec<SignatureParameters>) {
|
|
test::setup();
|
|
let cose_signature = sign(payload, cert_chain, ¶ms_vec);
|
|
assert!(cose_signature.is_ok());
|
|
let cose_signature = cose_signature.unwrap();
|
|
|
|
// Verify signature.
|
|
assert!(verify_signature(payload, cose_signature).is_ok());
|
|
}
|
|
|
|
fn test_verify_modified_payload(
|
|
payload: &mut [u8],
|
|
cert_chain: &[&[u8]],
|
|
params_vec: Vec<SignatureParameters>,
|
|
) {
|
|
test::setup();
|
|
let cose_signature = sign(payload, cert_chain, ¶ms_vec);
|
|
assert!(cose_signature.is_ok());
|
|
let cose_signature = cose_signature.unwrap();
|
|
|
|
// Verify signature.
|
|
payload[0] = !payload[0];
|
|
let verify_result = verify_signature(payload, cose_signature);
|
|
assert!(verify_result.is_err());
|
|
assert_eq!(verify_result, Err(CoseError::VerificationFailed));
|
|
}
|
|
|
|
fn test_verify_modified_signature(
|
|
payload: &[u8],
|
|
cert_chain: &[&[u8]],
|
|
params_vec: Vec<SignatureParameters>,
|
|
) {
|
|
test::setup();
|
|
let cose_signature = sign(payload, cert_chain, ¶ms_vec);
|
|
assert!(cose_signature.is_ok());
|
|
let mut cose_signature = cose_signature.unwrap();
|
|
|
|
// Tamper with the cose signature.
|
|
let len = cose_signature.len();
|
|
cose_signature[len - 15] = !cose_signature[len - 15];
|
|
|
|
// Verify signature.
|
|
let verify_result = verify_signature(payload, cose_signature);
|
|
assert!(verify_result.is_err());
|
|
assert_eq!(verify_result, Err(CoseError::VerificationFailed));
|
|
}
|
|
|
|
// This can be used with inconsistent parameters that make the verification fail.
|
|
// In particular, the signing key does not match the certificate used to verify.
|
|
fn test_verify_verification_fails(
|
|
payload: &[u8],
|
|
cert_chain: &[&[u8]],
|
|
params_vec: Vec<SignatureParameters>,
|
|
) {
|
|
test::setup();
|
|
let cose_signature = sign(payload, cert_chain, ¶ms_vec);
|
|
assert!(cose_signature.is_ok());
|
|
let cose_signature = cose_signature.unwrap();
|
|
|
|
// Verify signature.
|
|
let verify_result = verify_signature(payload, cose_signature);
|
|
assert!(verify_result.is_err());
|
|
assert_eq!(verify_result, Err(CoseError::VerificationFailed));
|
|
}
|
|
|
|
fn test_cose_sign_verify() {
|
|
let payload = b"This is the content.";
|
|
|
|
// P256
|
|
let certs: [&[u8]; 2] = [&test::P256_ROOT,
|
|
&test::P256_INT];
|
|
let params_vec = vec![P256_PARAMS];
|
|
test_verify(payload, &certs, params_vec);
|
|
|
|
// P256, no other certs.
|
|
let certs: [&[u8]; 0] = [];
|
|
let params_vec = vec![P256_PARAMS];
|
|
test_verify(payload, &certs, params_vec);
|
|
|
|
// P384
|
|
let params_vec = vec![P384_PARAMS];
|
|
test_verify(payload, &certs, params_vec);
|
|
|
|
// P521
|
|
let params_vec = vec![P521_PARAMS];
|
|
test_verify(payload, &certs, params_vec);
|
|
}
|
|
|
|
fn test_cose_verify_xpi_signature() {
|
|
// This signature was created with sign_app.py from m-c.
|
|
test::setup();
|
|
assert!(verify_signature(&test::XPI_PAYLOAD, test::XPI_SIGNATURE.to_vec()).is_ok());
|
|
}
|
|
|
|
fn test_cose_sign_verify_modified_payload() {
|
|
let mut payload = String::from_str("This is the content.")
|
|
.unwrap()
|
|
.into_bytes();
|
|
let certs: [&[u8]; 2] = [&test::P256_ROOT,
|
|
&test::P256_INT];
|
|
let params_vec = vec![P256_PARAMS];
|
|
test_verify_modified_payload(&mut payload, &certs, params_vec);
|
|
}
|
|
|
|
fn test_cose_sign_verify_wrong_cert() {
|
|
let payload = b"This is the content.";
|
|
let certs: [&[u8]; 2] = [&test::P256_ROOT,
|
|
&test::P256_INT];
|
|
let params = SignatureParameters {
|
|
certificate: &test::P384_EE,
|
|
algorithm: SignatureAlgorithm::ES256,
|
|
pkcs8: &test::PKCS8_P256_EE,
|
|
};
|
|
let params_vec = vec![params];
|
|
test_verify_verification_fails(payload, &certs, params_vec);
|
|
}
|
|
|
|
fn test_cose_sign_verify_tampered_signature() {
|
|
let payload = b"This is the content.";
|
|
let certs: [&[u8]; 2] = [&test::P256_ROOT,
|
|
&test::P256_INT];
|
|
let params_vec = vec![P256_PARAMS];
|
|
test_verify_modified_signature(payload, &certs, params_vec);
|
|
}
|
|
|
|
const RSA_PARAMS: SignatureParameters = SignatureParameters {
|
|
certificate: &test::RSA_EE,
|
|
algorithm: SignatureAlgorithm::PS256,
|
|
pkcs8: &test::PKCS8_RSA_EE,
|
|
};
|
|
|
|
fn test_cose_sign_verify_rsa() {
|
|
let payload = b"This is the RSA-signed content.";
|
|
let certs: [&[u8]; 2] = [&test::RSA_ROOT,
|
|
&test::RSA_INT];
|
|
let params_vec = vec![RSA_PARAMS];
|
|
test_verify(payload, &certs, params_vec);
|
|
}
|
|
|
|
fn test_cose_sign_verify_rsa_modified_payload() {
|
|
let mut payload = String::from_str("This is the RSA-signed content.")
|
|
.unwrap()
|
|
.into_bytes();
|
|
let certs: [&[u8]; 2] = [&test::RSA_ROOT,
|
|
&test::RSA_INT];
|
|
let params_vec = vec![RSA_PARAMS];
|
|
test_verify_modified_payload(&mut payload, &certs, params_vec);
|
|
}
|
|
|
|
fn test_cose_sign_verify_rsa_tampered_signature() {
|
|
let payload = b"This is the RSA-signed content.";
|
|
let certs: [&[u8]; 2] = [&test::RSA_ROOT,
|
|
&test::RSA_INT];
|
|
let params_vec = vec![RSA_PARAMS];
|
|
test_verify_modified_signature(payload, &certs, params_vec);
|
|
}
|
|
|
|
fn test_cose_sign_verify_two_signatures() {
|
|
let payload = b"This is the content.";
|
|
let certs: [&[u8]; 4] = [&test::P256_ROOT,
|
|
&test::P256_INT,
|
|
&test::RSA_ROOT,
|
|
&test::RSA_INT];
|
|
let params_vec = vec![P256_PARAMS,
|
|
RSA_PARAMS];
|
|
test_verify(payload, &certs, params_vec);
|
|
}
|
|
|
|
fn test_cose_sign_verify_two_signatures_tampered_payload() {
|
|
let mut payload = String::from_str("This is the content.")
|
|
.unwrap()
|
|
.into_bytes();
|
|
let certs: [&[u8]; 4] = [&test::P256_ROOT,
|
|
&test::P256_INT,
|
|
&test::RSA_ROOT,
|
|
&test::RSA_INT];
|
|
let params_vec = vec![P256_PARAMS,
|
|
RSA_PARAMS];
|
|
test_verify_modified_payload(&mut payload, &certs, params_vec);
|
|
}
|
|
|
|
fn test_cose_sign_verify_two_signatures_tampered_signature() {
|
|
let payload = b"This is the content.";
|
|
let certs: [&[u8]; 4] = [&test::P256_ROOT,
|
|
&test::P256_INT,
|
|
&test::RSA_ROOT,
|
|
&test::RSA_INT];
|
|
let params_vec = vec![P256_PARAMS,
|
|
RSA_PARAMS];
|
|
test_verify_modified_signature(payload, &certs, params_vec);
|
|
}
|
|
|
|
fn main() {
|
|
// Basic NSS exmaple usage.
|
|
test_nss::test_nss_sign_verify();
|
|
test_nss::test_nss_sign_verify_different_payload();
|
|
test_nss::test_nss_sign_verify_wrong_cert();
|
|
|
|
// COSE sign/verify example usages.
|
|
test_cose_sign_verify_two_signatures_tampered_signature();
|
|
test_cose_sign_verify_two_signatures_tampered_payload();
|
|
test_cose_sign_verify_two_signatures();
|
|
test_cose_sign_verify_rsa_tampered_signature();
|
|
test_cose_sign_verify_rsa_modified_payload();
|
|
test_cose_sign_verify_rsa();
|
|
test_cose_sign_verify_tampered_signature();
|
|
test_cose_sign_verify_wrong_cert();
|
|
test_cose_sign_verify_modified_payload();
|
|
test_cose_verify_xpi_signature();
|
|
test_cose_sign_verify();
|
|
}
|