pub mod utils; struct BuildArgs<'a> { api_major: &'a str, api_minor: &'a str, build_id: &'a str, policy: &'a str, tik: &'a str, nonce: Option<&'a str>, launch_measure_blob: Option<&'a str>, launch_digest: Option<&'a str>, firmware: Option<&'a str>, kernel: Option<&'a str>, initrd: Option<&'a str>, cmdline: Option<&'a str>, num_cpus: Option<&'a str>, vmsa_cpu0: Option<&'a str>, vmsa_cpu1: Option<&'a str>, outfile: Option<&'a str>, } fn run_build(args: &BuildArgs) -> String { let tik = utils::cargo_root_path(&args.tik); let mut sevctl_args = vec![ "measurement", "build", "--api-major", args.api_major, "--api-minor", args.api_minor, "--build-id", args.build_id, "--policy", args.policy, "--tik", &tik, ]; if let Some(nonce) = args.nonce { sevctl_args.push("--nonce"); sevctl_args.push(nonce); } if let Some(lmb) = args.launch_measure_blob { sevctl_args.push("--launch-measure-blob"); sevctl_args.push(lmb); } if let Some(ld) = args.launch_digest { sevctl_args.push("--launch-digest"); sevctl_args.push(ld); } if let Some(firmware) = args.firmware { sevctl_args.push("--firmware"); sevctl_args.push(firmware); } if let Some(kernel) = args.kernel { sevctl_args.push("--kernel"); sevctl_args.push(kernel); } if let Some(initrd) = args.initrd { sevctl_args.push("--initrd"); sevctl_args.push(initrd); } if let Some(cmdline) = args.cmdline { sevctl_args.push("--cmdline"); sevctl_args.push(cmdline); } if let Some(num_cpus) = args.num_cpus { sevctl_args.push("--num-cpus"); sevctl_args.push(num_cpus); sevctl_args.push("--vmsa-cpu0"); sevctl_args.push(args.vmsa_cpu0.unwrap()); sevctl_args.push("--vmsa-cpu1"); sevctl_args.push(args.vmsa_cpu1.unwrap()); } if let Some(val) = &args.outfile { sevctl_args.push("--outfile"); sevctl_args.push(val); } utils::run_sevctl(&sevctl_args[..]).trim().to_string() } fn test_build(expected: &str, args: BuildArgs) { let mut output = run_build(&args); if let Some(val) = args.outfile { output = base64::encode(std::fs::read(val).unwrap()); } assert_eq!(expected, output); } #[test] fn measurement_build() { let stdargs = BuildArgs { api_major: "0x01", api_minor: "40", build_id: "40", policy: "0x03", tik: "tests/data/measurement/tik1.bin", nonce: Some("wxP6tRHCFrFQWxsuqZA8QA=="), launch_measure_blob: None, launch_digest: None, firmware: None, kernel: None, initrd: None, cmdline: None, num_cpus: None, vmsa_cpu0: None, vmsa_cpu1: None, outfile: None, }; // Test manually passed in --launch-digest let args1 = BuildArgs { launch_digest: Some("xkvRAfyaSizgonxAjZIAkR8TmolUabBKQKb6KJCDDSM="), ..stdargs }; let expected = "lswbxWxI9gckya16JQvdFtpYmNO4b+3inAPpqsgoBI7DE/q1EcIWsVBbGy6pkDxA"; test_build(expected, args1); // Same as args1 test, but with --outfile. let file = tempfile::NamedTempFile::new().unwrap(); let args_outfile = BuildArgs { launch_digest: Some("xkvRAfyaSizgonxAjZIAkR8TmolUabBKQKb6KJCDDSM="), outfile: Some(file.path().to_str().unwrap()), ..stdargs }; test_build(expected, args_outfile); // Test --firmware PATH let args_firmware = BuildArgs { firmware: Some("tests/data/OVMF.amdsev.fd_trimmed_edk2-ovmf-20220126gitbb1bba3d77-4.el9"), ..stdargs }; let expected = "oMDewIouJSpbpNRHj7Mk3p08H2dPZQdsZMU14qIymBnDE/q1EcIWsVBbGy6pkDxA"; test_build(expected, BuildArgs { ..args_firmware }); // Test --firmware + --kernel everything let args_kernel = BuildArgs { kernel: Some("tests/data/measurement/vmlinuz-fake"), initrd: Some("tests/data/measurement/initrd-fake"), cmdline: Some("foo bar baz fake kernel=cmdline"), ..args_firmware }; let expected = "h3auYbWQnVW7EGLWN4Hf9SN0oEYMPU2sK4bLnefWPwvDE/q1EcIWsVBbGy6pkDxA"; test_build(expected, args_kernel); // Test SEV-ES VMSA bits let expected = "/o0nzDKE5XgtVnUZWPhUea/WZYrTKLExR7KCwuMdbActvpWfXTFk21KMZIAAhQny"; let args_vmsa = BuildArgs { policy: "0x05", num_cpus: Some("4"), vmsa_cpu0: Some("tests/data/vmsa0.bin"), vmsa_cpu1: Some("tests/data/vmsa1.bin"), api_major: "1", api_minor: "49", build_id: "6", nonce: None, launch_measure_blob: Some(&expected), ..args_firmware }; test_build(expected, args_vmsa); }