From 1ebe7520481de7361beb786b69f195f218aed85c Mon Sep 17 00:00:00 2001 From: Mark Kirichenko <mkirich@amazon.de> Date: Tue, 21 Jan 2025 10:35:34 +0000 Subject: [PATCH] Add tests for EIF signing This commit adds tests cases to validate the signing functionality. Signed-off-by: Mark Kirichenko <mkirich@amazon.de> --- tests/test_nitro_cli_args.rs | 47 ++++++ tests/tests.rs | 285 ++++++++++++++++++++++++++++++++++- 2 files changed, 330 insertions(+), 2 deletions(-) diff --git a/tests/test_nitro_cli_args.rs b/tests/test_nitro_cli_args.rs index 2e306138..c414ea2c 100644 --- a/tests/test_nitro_cli_args.rs +++ b/tests/test_nitro_cli_args.rs @@ -337,6 +337,53 @@ mod test_nitro_cli_args { assert!(app.try_get_matches_from(args).is_err()) } + #[test] + fn sign_enclave_correct_command() { + let app = create_app!(); + let args = vec![ + "nitro cli", + "sign-eif", + "--eif-path", + "image.eif", + "--signing-certificate", + "cert.pem", + "--private-key", + "key.pem", + ]; + + assert!(app.try_get_matches_from(args).is_ok()) + } + + #[test] + fn sign_enclave_missing_certificate() { + let app = create_app!(); + let args = vec![ + "nitro cli", + "sign-eif", + "--eif-path", + "image.eif", + "--private-key", + "key.pem", + ]; + + assert!(app.try_get_matches_from(args).is_err()) + } + + #[test] + fn sign_enclave_missing_key() { + let app = create_app!(); + let args = vec![ + "nitro cli", + "sign-eif", + "--eif-path", + "image.eif", + "--signing-certificate", + "cert.pem", + ]; + + assert!(app.try_get_matches_from(args).is_err()) + } + #[test] fn build_enclave_with_metadata_correct_command() { let app = create_app!(); diff --git a/tests/tests.rs b/tests/tests.rs index 380ea20d..55ac89df 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -6,7 +6,7 @@ #[cfg(test)] mod tests { use nitro_cli::common::commands_parser::{ - BuildEnclavesArgs, RunEnclavesArgs, TerminateEnclavesArgs, + BuildEnclavesArgs, RunEnclavesArgs, SignEifArgs, TerminateEnclavesArgs, }; use nitro_cli::common::json_output::EnclaveDescribeInfo; use nitro_cli::enclave_proc::commands::{describe_enclaves, run_enclaves, terminate_enclaves}; @@ -17,7 +17,7 @@ mod tests { use nitro_cli::utils::{Console, PcrType}; use nitro_cli::{ build_enclaves, build_from_docker, describe_eif, enclave_console, get_file_pcr, - new_enclave_name, + new_enclave_name, sign_eif, }; use nitro_cli::{CID_TO_CONSOLE_PORT_OFFSET, VMADDR_CID_HYPERVISOR}; use serde_json::json; @@ -365,6 +365,59 @@ mod tests { run_describe_terminate(args); } + #[test] + fn run_describe_terminate_separately_signed_enclave_image() { + let dir = tempdir().unwrap(); + let dir_path = dir.path().to_str().unwrap(); + let eif_path = format!("{}/test.eif", dir_path); + let cert_path = format!("{}/cert.pem", dir_path); + let key_path = format!("{}/key.pem", dir_path); + generate_signing_cert_and_key(&cert_path, &key_path); + + setup_env(); + let build_args = BuildEnclavesArgs { + docker_uri: SAMPLE_DOCKER.to_string(), + docker_dir: None, + output: eif_path, + signing_certificate: None, + private_key: None, + img_name: None, + img_version: None, + metadata: None, + }; + + build_from_docker( + &build_args.docker_uri, + &build_args.docker_dir, + &build_args.output, + &build_args.signing_certificate, + &build_args.private_key, + &build_args.img_name, + &build_args.img_version, + &build_args.metadata, + ) + .expect("Docker build failed"); + + let sign_args = SignEifArgs { + eif_path: build_args.output.clone(), + signing_certificate: Some(cert_path), + private_key: Some(key_path), + }; + sign_eif(sign_args).expect("Sign EIF failed"); + + let args = RunEnclavesArgs { + enclave_cid: None, + eif_path: build_args.output, + cpu_ids: None, + cpu_count: Some(2), + memory_mib: 256, + debug_mode: true, + attach_console: false, + enclave_name: Some("testName".to_string()), + }; + run_describe_terminate(args); + } + #[test] fn run_describe_terminate_command_executer_docker_image() { let dir = tempdir().unwrap(); @@ -1029,6 +1082,121 @@ mod tests { assert!(eif_info.sign_check.unwrap()); } + #[test] + fn build_sign_decribe_simple_eif() { + let dir = tempdir().unwrap(); + let dir_path = dir.path().to_str().unwrap(); + let eif_path = format!("{}/test.eif", dir_path); + let cert_path = format!("{}/cert.pem", dir_path); + let key_path = format!("{}/key.pem", dir_path); + generate_signing_cert_and_key(&cert_path, &key_path); + + setup_env(); + let args = BuildEnclavesArgs { + docker_uri: SAMPLE_DOCKER.to_string(), + docker_dir: None, + output: eif_path, + signing_certificate: None, + private_key: None, + img_name: None, + img_version: None, + metadata: None, + }; + + build_from_docker( + &args.docker_uri, + &args.docker_dir, + &args.output, + &args.signing_certificate, + &args.private_key, + &args.img_name, + &args.img_version, + &args.metadata, + ) + .expect("Docker build failed"); + + let eif_info = describe_eif(args.output.clone()).unwrap(); + + assert_eq!(eif_info.version, 4); + assert!(!eif_info.is_signed); + assert!(eif_info.cert_info.is_none()); + assert!(eif_info.crc_check); + assert!(eif_info.sign_check.is_none()); + + let sign_args = SignEifArgs { + eif_path: args.output.clone(), + signing_certificate: Some(cert_path), + private_key: Some(key_path), + }; + sign_eif(sign_args).expect("Sign EIF failed"); + let signed_eif_info = describe_eif(args.output).unwrap(); + + assert_eq!(signed_eif_info.version, 4); + assert!(signed_eif_info.is_signed); + assert!(signed_eif_info.cert_info.is_some()); + assert!(signed_eif_info.crc_check); + assert!(signed_eif_info.sign_check.unwrap()); + } + + #[test] + fn build_describe_signed_simple_eif_with_updated_signature() { + let dir = tempdir().unwrap(); + let dir_path = dir.path().to_str().unwrap(); + let eif_path = format!("{}/test.eif", dir_path); + let cert_path = format!("{}/cert.pem", dir_path); + let key_path = format!("{}/key.pem", dir_path); + let cert_path2 = format!("{}/cert2.pem", dir_path); + let key_path2 = format!("{}/key2.pem", dir_path); + generate_signing_cert_and_key(&cert_path, &key_path); + generate_signing_cert_and_key(&cert_path2, &key_path2); + + setup_env(); + let args = BuildEnclavesArgs { + docker_uri: SAMPLE_DOCKER.to_string(), + docker_dir: None, + output: eif_path, + signing_certificate: Some(cert_path), + private_key: Some(key_path), + img_name: None, + img_version: None, + metadata: None, + }; + + build_from_docker( + &args.docker_uri, + &args.docker_dir, + &args.output, + &args.signing_certificate, + &args.private_key, + &args.img_name, + &args.img_version, + &args.metadata, + ) + .expect("Docker build failed"); + + let eif_info = describe_eif(args.output.clone()).unwrap(); + + assert_eq!(eif_info.version, 4); + assert!(eif_info.is_signed); + assert!(eif_info.cert_info.is_some()); + assert!(eif_info.crc_check); + assert!(eif_info.sign_check.unwrap()); + + let sign_args = SignEifArgs { + eif_path: args.output.clone(), + signing_certificate: Some(cert_path2), + private_key: Some(key_path2), + }; + sign_eif(sign_args).expect("Sign EIF failed"); + let signed_eif_info = describe_eif(args.output).unwrap(); + + assert_eq!(signed_eif_info.version, 4); + assert!(signed_eif_info.is_signed); + assert!(signed_eif_info.cert_info.is_some()); + assert!(signed_eif_info.crc_check); + assert!(signed_eif_info.sign_check.unwrap()); + } + #[test] fn get_certificate_pcr() { let dir = tempdir().unwrap(); @@ -1076,4 +1244,117 @@ mod tests { pcr.get(&"PCR8".to_string()).unwrap(), ); } + + #[test] + fn get_certificate_pcr_after_separate_signing() { + let dir = tempdir().unwrap(); + let dir_path = dir.path().to_str().unwrap(); + let eif_path = format!("{}/test.eif", dir_path); + let cert_path = format!("{}/cert.pem", dir_path); + let key_path = format!("{}/key.pem", dir_path); + generate_signing_cert_and_key(&cert_path, &key_path); + + setup_env(); + let args = BuildEnclavesArgs { + docker_uri: SAMPLE_DOCKER.to_string(), + docker_dir: None, + output: eif_path, + signing_certificate: None, + private_key: None, + img_name: None, + img_version: None, + metadata: None, + }; + + build_from_docker( + &args.docker_uri, + &args.docker_dir, + &args.output, + &args.signing_certificate, + &args.private_key, + &args.img_name, + &args.img_version, + &args.metadata, + ) + .expect("Docker build failed"); + + let sign_args = SignEifArgs { + eif_path: args.output.clone(), + signing_certificate: Some(cert_path.clone()), + private_key: Some(key_path), + }; + sign_eif(sign_args).expect("Sign EIF failed"); + + // Describe EIF and get PCR8 + let eif_info = describe_eif(args.output).unwrap(); + // Hash signing certificate and verify that PCR8 is the same (identifying the certificate) + let pcr = get_file_pcr(cert_path, PcrType::SigningCertificate).unwrap(); + + assert_eq!( + eif_info + .build_info + .measurements + .get(&"PCR8".to_string()) + .unwrap(), + pcr.get(&"PCR8".to_string()).unwrap(), + ); + } + + #[test] + fn get_certificate_pcr_after_signature_update() { + let dir = tempdir().unwrap(); + let dir_path = dir.path().to_str().unwrap(); + let eif_path = format!("{}/test.eif", dir_path); + let cert_path = format!("{}/cert.pem", dir_path); + let key_path = format!("{}/key.pem", dir_path); + let cert_path2 = format!("{}/cert2.pem", dir_path); + let key_path2 = format!("{}/key2.pem", dir_path); + generate_signing_cert_and_key(&cert_path, &key_path); + generate_signing_cert_and_key(&cert_path2, &key_path2); + + setup_env(); + let args = BuildEnclavesArgs { + docker_uri: SAMPLE_DOCKER.to_string(), + docker_dir: None, + output: eif_path, + signing_certificate: Some(cert_path), + private_key: Some(key_path), + img_name: None, + img_version: None, + metadata: None, + }; + + build_from_docker( + &args.docker_uri, + &args.docker_dir, + &args.output, + &args.signing_certificate, + &args.private_key, + &args.img_name, + &args.img_version, + &args.metadata, + ) + .expect("Docker build failed"); + + let sign_args = SignEifArgs { + eif_path: args.output.clone(), + signing_certificate: Some(cert_path2.clone()), + private_key: Some(key_path2), + }; + sign_eif(sign_args).expect("Sign EIF failed"); + + // Describe EIF and get PCR8 + let eif_info = describe_eif(args.output).unwrap(); + // Hash signing certificate and verify that PCR8 is the same (identifying the certificate) + let pcr = get_file_pcr(cert_path2, PcrType::SigningCertificate).unwrap(); + + assert_eq!( + eif_info + .build_info + .measurements + .get(&"PCR8".to_string()) + .unwrap(), + pcr.get(&"PCR8".to_string()).unwrap(), + ); + } }