use der::{referenced::OwnedToRef, Decode, Encode}; use image4::{ manifest::{CertChain, UnsignedManifestRef}, ManifestRef, }; use rsa::{ pkcs1::DecodeRsaPrivateKey, pkcs1v15::{Signature, SigningKey, VerifyingKey}, sha2::Sha384, RsaPrivateKey, RsaPublicKey, }; use signature::Verifier; use std::error::Error; const TEST_KEY: &[u8] = include_bytes!("data/test-key.der"); const TEST_CERT: &[u8] = include_bytes!("data/test-cert.der"); const SIGNED_MANIFEST: &[u8] = include_bytes!("data/apticket.der"); const UNSIGNED_MANIFEST: &[u8] = include_bytes!("data/apticket_unsigned.der"); #[test] fn test_decode_shallow_signed() -> der::Result<()> { ManifestRef::from_der(SIGNED_MANIFEST)?; Ok(()) } #[test] fn test_decode_shallow_unsigned() -> der::Result<()> { UnsignedManifestRef::from_der(UNSIGNED_MANIFEST)?; Ok(()) } #[test] fn test_decode_body_signed() -> der::Result<()> { let manifest = ManifestRef::from_der(SIGNED_MANIFEST)?; manifest.decode_body()?; Ok(()) } #[test] fn test_decode_body_unsigned() -> der::Result<()> { let manifest = UnsignedManifestRef::from_der(UNSIGNED_MANIFEST)?; manifest.decode_body()?; Ok(()) } #[test] fn test_decode_cert_chain() -> der::Result<()> { let manifest = ManifestRef::from_der(SIGNED_MANIFEST)?; manifest.cert_chain().decode_body()?; Ok(()) } #[test] fn test_decode_encode_signed() -> der::Result<()> { let manifest = ManifestRef::from_der(SIGNED_MANIFEST)?; let mut encoded = Vec::new(); manifest.encode_to_vec(&mut encoded).unwrap(); assert_eq!(encoded, SIGNED_MANIFEST); Ok(()) } #[test] fn test_decode_encode_unsigned() -> der::Result<()> { let manifest = UnsignedManifestRef::from_der(UNSIGNED_MANIFEST)?; let mut encoded = Vec::new(); manifest.encode_to_vec(&mut encoded)?; assert_eq!(encoded, UNSIGNED_MANIFEST); Ok(()) } /// This signs a manifest using RSA and checks if the signature passes validation. #[test] fn test_signing() -> Result<(), Box> { let unsigned_manifest = UnsignedManifestRef::from_der(UNSIGNED_MANIFEST)?; let private_key = RsaPrivateKey::from_pkcs1_der(TEST_KEY)?; let public_key = private_key.to_public_key(); let signing_key = SigningKey::::new(private_key); let cert_chain = CertChain::new(TEST_CERT)?; let signed_manifest = unsigned_manifest.sign(&signing_key, cert_chain)?; let verifying_key = VerifyingKey::::new(public_key); let signature = Signature::try_from(signed_manifest.signature())?; verifying_key.verify(signed_manifest.body().as_bytes(), &signature)?; Ok(()) } /// This tests for the ability of the [`rsa`] crate to validate a signature on a manifest signed by /// a TSS server. #[test] fn test_validation_real_manifest_rsa3k_sha384() -> Result<(), Box> { let manifest = ManifestRef::from_der(SIGNED_MANIFEST)?; let cert = manifest .cert_chain() .iter() .next() .unwrap()? .decode_body()?; let spki = cert.tbs_certificate.subject_public_key_info.owned_to_ref(); let public_key = RsaPublicKey::try_from(spki)?; let verifying_key = VerifyingKey::::new(public_key); let signature = Signature::try_from(manifest.signature())?; verifying_key.verify(manifest.body().as_bytes(), &signature)?; Ok(()) }