From adbe249edbf346cdef7ce3721159c4252d791922 Mon Sep 17 00:00:00 2001 From: Andrew Gunnerson Date: Sun, 10 Dec 2023 13:29:45 -0500 Subject: [PATCH] key: Add new decode-avb subcommand This does the reverse of `avbroot key extract-avb`. It's useful for reconstructing a PKCS8-encoded RSA public key when working with the `public_key` fields in `avb.toml`. Signed-off-by: Andrew Gunnerson --- avbroot/src/cli/key.rs | 23 +++++++++++++++++++++++ avbroot/src/crypto.rs | 17 +++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/avbroot/src/cli/key.rs b/avbroot/src/cli/key.rs index 170353f..2adc033 100644 --- a/avbroot/src/cli/key.rs +++ b/avbroot/src/cli/key.rs @@ -71,6 +71,16 @@ pub fn key_main(cli: &KeyCli) -> Result<()> { fs::write(&c.output, encoded) .with_context(|| format!("Failed to write public key: {:?}", c.output))?; } + KeyCommand::DecodeAvb(c) => { + let encoded = fs::read(&c.key) + .with_context(|| format!("Failed to load AVB public key: {:?}", c.key))?; + + let public_key = avb::decode_public_key(&encoded) + .context("Failed to decode public key as AVB format")?; + + crypto::write_pem_public_key_file(&c.output, &public_key) + .with_context(|| format!("Failed to write public key: {:?}", c.output))?; + } } Ok(()) @@ -152,11 +162,24 @@ struct ExtractAvbCli { passphrase: PassphraseGroup, } +/// Convert an AVB-encoded public key to a PKCS8-encoded public key. +#[derive(Debug, Parser)] +struct DecodeAvbCli { + /// Path to output PKCS8-encoded public key. + #[arg(short, long, value_name = "FILE", value_parser)] + output: PathBuf, + + /// Path to AVB-encoded public key. + #[arg(short, long, value_name = "FILE", value_parser)] + key: PathBuf, +} + #[derive(Debug, Subcommand)] enum KeyCommand { GenerateKey(GenerateKeyCli), GenerateCert(GenerateCertCli), ExtractAvb(ExtractAvbCli), + DecodeAvb(DecodeAvbCli), } /// Generate and convert keys. diff --git a/avbroot/src/crypto.rs b/avbroot/src/crypto.rs index 0090604..90bed7a 100644 --- a/avbroot/src/crypto.rs +++ b/avbroot/src/crypto.rs @@ -225,6 +225,23 @@ pub fn write_pem_cert_file(path: &Path, cert: &Certificate) -> Result<()> { write_pem_cert(writer, cert) } +/// Write PEM-encoded PKCS8 public key to a writer. +pub fn write_pem_public_key(mut writer: impl Write, key: &RsaPublicKey) -> Result<()> { + let data = key.to_public_key_pem(LineEnding::LF)?; + + writer.write_all(data.as_bytes())?; + + Ok(()) +} + +/// Write PEM-encoded PKCS8 public key to a file. +pub fn write_pem_public_key_file(path: &Path, key: &RsaPublicKey) -> Result<()> { + let file = File::create(path)?; + let writer = BufWriter::new(file); + + write_pem_public_key(writer, key) +} + /// Read PEM-encoded PKCS8 private key from a reader. pub fn read_pem_key(mut reader: impl Read, source: &PassphraseSource) -> Result { let mut data = String::new();