From 68b8cc82820b11c851fb6ccde363a7459a82f200 Mon Sep 17 00:00:00 2001 From: Trevor Jones Date: Thu, 30 Jan 2025 16:20:30 -0800 Subject: [PATCH 1/2] vmgstool encryption scheme detection --- vm/vmgs/vmgstool/src/main.rs | 42 ++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/vm/vmgs/vmgstool/src/main.rs b/vm/vmgs/vmgstool/src/main.rs index 3019479db2..b56eddfbab 100644 --- a/vm/vmgs/vmgstool/src/main.rs +++ b/vm/vmgs/vmgstool/src/main.rs @@ -100,6 +100,13 @@ enum ExitCode { ErrorV1 = 5, } +#[derive(Debug, Clone, Copy)] +enum VmgsEncryptionScheme { + Gsp, + GspById, + None, +} + #[derive(Args)] struct FilePathArg { /// VMGS file path @@ -973,7 +980,7 @@ async fn vmgs_file_query_file_size( ) -> Result<(), Error> { let vmgs = vmgs_file_open(file_path, None as Option, OpenMode::ReadOnly, true).await?; - let file_size = vmgs_query_file_size(&vmgs, file_id).await?; + let file_size = vmgs_query_file_size(&vmgs, file_id)?; println!( "File ID {} ({:?}) has a size of {}", @@ -983,7 +990,7 @@ async fn vmgs_file_query_file_size( Ok(()) } -async fn vmgs_query_file_size(vmgs: &Vmgs, file_id: FileId) -> Result { +fn vmgs_query_file_size(vmgs: &Vmgs, file_id: FileId) -> Result { Ok(vmgs.get_file_info(file_id)?.valid_bytes) } @@ -992,23 +999,40 @@ async fn vmgs_file_query_encryption(file_path: impl AsRef) -> Result<(), E let vmgs = vmgs_file_open(file_path, None as Option, OpenMode::ReadOnly, true).await?; - match vmgs.get_encryption_algorithm() { - EncryptionAlgorithm::NONE => { + match ( + vmgs.get_encryption_algorithm(), + vmgs_get_encryption_scheme(&vmgs), + ) { + (EncryptionAlgorithm::NONE, VmgsEncryptionScheme::None) => { println!("not encrypted"); // Returning an error for HA to easily parse return Err(Error::NotEncrypted); } - EncryptionAlgorithm::AES_GCM => { - println!("encrypted with AES GCM encryption algorithm"); + (EncryptionAlgorithm::AES_GCM, VmgsEncryptionScheme::Gsp) => { + println!("encrypted with AES GCM encryption algorithm using Gsp"); + } + (EncryptionAlgorithm::AES_GCM, VmgsEncryptionScheme::GspById) => { + println!("encrypted with AES GCM encryption algorithm using GspById"); } - _ => { - unreachable!("Invalid encryption algorithm"); + (alg, scheme) => { + unreachable!("Invalid encryption algorithm ({alg:?}) / scheme ({scheme:?})"); } } Ok(()) } +fn vmgs_get_encryption_scheme(vmgs: &Vmgs) -> VmgsEncryptionScheme { + // TODO: validate that the files are the expected size + if vmgs_query_file_size(vmgs, FileId::KEY_PROTECTOR).is_ok() { + VmgsEncryptionScheme::Gsp + } else if vmgs_query_file_size(vmgs, FileId::VM_UNIQUE_ID).is_ok() { + VmgsEncryptionScheme::GspById + } else { + VmgsEncryptionScheme::None + } +} + fn vmgs_file_validate(file: &File) -> Result<(), Error> { vmgs_file_validate_not_empty(file)?; vmgs_file_validate_not_v1(file)?; @@ -1137,7 +1161,7 @@ mod tests { let vmgs = vmgs_file_open(file_path, None as Option, OpenMode::ReadOnly, true).await?; - vmgs_query_file_size(&vmgs, file_id).await + vmgs_query_file_size(&vmgs, file_id) } #[cfg(with_encryption)] From 3e7526c9544a6cc36fdb2540663c0b87043cef8c Mon Sep 17 00:00:00 2001 From: Trevor Jones Date: Fri, 7 Feb 2025 15:43:28 -0800 Subject: [PATCH 2/2] return 6 for gspbyid --- vm/vmgs/vmgstool/src/main.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/vm/vmgs/vmgstool/src/main.rs b/vm/vmgs/vmgstool/src/main.rs index b56eddfbab..bcf99162b5 100644 --- a/vm/vmgs/vmgstool/src/main.rs +++ b/vm/vmgs/vmgstool/src/main.rs @@ -81,6 +81,8 @@ enum Error { Json(String), #[error("File ID {0:?} already exists. Use `--allow-overwrite` to ignore.")] FileIdExists(FileId), + #[error("VMGS file is encrypted using GspById")] + GspByIdEncryption, } /// Automation requires certain exit codes to be guaranteed @@ -98,11 +100,12 @@ enum ExitCode { ErrorEmpty = 3, ErrorNotFound = 4, ErrorV1 = 5, + ErrorGspById = 6, } #[derive(Debug, Clone, Copy)] enum VmgsEncryptionScheme { - Gsp, + GspKey, GspById, None, } @@ -334,6 +337,7 @@ fn main() { Error::ZeroSize => ExitCode::ErrorEmpty, Error::Vmgs(VmgsError::FileInfoAllocated) => ExitCode::ErrorNotFound, Error::V1Format => ExitCode::ErrorV1, + Error::GspByIdEncryption => ExitCode::ErrorGspById, _ => ExitCode::Error, }; @@ -1006,26 +1010,26 @@ async fn vmgs_file_query_encryption(file_path: impl AsRef) -> Result<(), E (EncryptionAlgorithm::NONE, VmgsEncryptionScheme::None) => { println!("not encrypted"); // Returning an error for HA to easily parse - return Err(Error::NotEncrypted); + Err(Error::NotEncrypted) } - (EncryptionAlgorithm::AES_GCM, VmgsEncryptionScheme::Gsp) => { - println!("encrypted with AES GCM encryption algorithm using Gsp"); + (EncryptionAlgorithm::AES_GCM, VmgsEncryptionScheme::GspKey) => { + println!("encrypted with AES GCM encryption algorithm using GspKey"); + Ok(()) } (EncryptionAlgorithm::AES_GCM, VmgsEncryptionScheme::GspById) => { println!("encrypted with AES GCM encryption algorithm using GspById"); + Err(Error::GspByIdEncryption) } (alg, scheme) => { unreachable!("Invalid encryption algorithm ({alg:?}) / scheme ({scheme:?})"); } } - - Ok(()) } fn vmgs_get_encryption_scheme(vmgs: &Vmgs) -> VmgsEncryptionScheme { // TODO: validate that the files are the expected size if vmgs_query_file_size(vmgs, FileId::KEY_PROTECTOR).is_ok() { - VmgsEncryptionScheme::Gsp + VmgsEncryptionScheme::GspKey } else if vmgs_query_file_size(vmgs, FileId::VM_UNIQUE_ID).is_ok() { VmgsEncryptionScheme::GspById } else {