48 lines
2 KiB
Rust
48 lines
2 KiB
Rust
use base64::{engine::general_purpose::STANDARD, Engine as _};
|
|
use minisign_verify::{PublicKey, Signature};
|
|
use serde_json::Value;
|
|
use std::{env, fs, path::Path};
|
|
|
|
fn decode_outer_base64(value: &str, label: &str) -> Result<String, String> {
|
|
let bytes = STANDARD
|
|
.decode(value.trim())
|
|
.map_err(|error| format!("{label}_BASE64_INVALID: {error}"))?;
|
|
String::from_utf8(bytes).map_err(|error| format!("{label}_UTF8_INVALID: {error}"))
|
|
}
|
|
|
|
fn main() -> Result<(), String> {
|
|
let arguments: Vec<String> = env::args().collect();
|
|
let [_, trust_path, updater_path, signature_path] = arguments.as_slice() else {
|
|
return Err(
|
|
"USAGE: verify_updater_signature <release-trust.json> <updater> <signature>"
|
|
.to_string(),
|
|
);
|
|
};
|
|
let trust: Value = serde_json::from_str(
|
|
&fs::read_to_string(trust_path)
|
|
.map_err(|error| format!("RELEASE_TRUST_READ_FAILED: {error}"))?,
|
|
)
|
|
.map_err(|error| format!("RELEASE_TRUST_JSON_INVALID: {error}"))?;
|
|
let encoded_public_key = trust
|
|
.get("publicKey")
|
|
.and_then(Value::as_str)
|
|
.ok_or_else(|| "RELEASE_TRUST_PUBLIC_KEY_MISSING".to_string())?;
|
|
let public_key = PublicKey::decode(&decode_outer_base64(
|
|
encoded_public_key,
|
|
"RELEASE_TRUST_PUBLIC_KEY",
|
|
)?)
|
|
.map_err(|error| format!("RELEASE_TRUST_PUBLIC_KEY_INVALID: {error}"))?;
|
|
let signature = Signature::decode(&decode_outer_base64(
|
|
&fs::read_to_string(signature_path)
|
|
.map_err(|error| format!("UPDATER_SIGNATURE_READ_FAILED: {error}"))?,
|
|
"UPDATER_SIGNATURE",
|
|
)?)
|
|
.map_err(|error| format!("UPDATER_SIGNATURE_INVALID: {error}"))?;
|
|
let updater = fs::read(Path::new(updater_path))
|
|
.map_err(|error| format!("UPDATER_ARTIFACT_READ_FAILED: {error}"))?;
|
|
public_key
|
|
.verify(&updater, &signature, true)
|
|
.map_err(|error| format!("UPDATER_SIGNATURE_VERIFICATION_FAILED: {error}"))?;
|
|
println!("HOLOLAKE_UPDATER_SIGNATURE_VERIFIED");
|
|
Ok(())
|
|
}
|