refactor partition signature verification

This commit is contained in:
Bruce Leidl 2019-01-17 09:05:53 -05:00
parent 72b7af4f2d
commit 8f8cbab72f
2 changed files with 53 additions and 12 deletions

View File

@ -11,6 +11,7 @@ use rustc_serialize::hex::{FromHex,ToHex};
/// ///
/// ///
#[derive(Clone)]
pub struct PublicKey([u8; ED25519_PUBLIC_KEY_LEN]); pub struct PublicKey([u8; ED25519_PUBLIC_KEY_LEN]);
pub struct KeyPair([u8; ED25519_PKCS8_V2_LEN]); pub struct KeyPair([u8; ED25519_PKCS8_V2_LEN]);
pub struct Signature(signature::Signature); pub struct Signature(signature::Signature);

View File

@ -1,6 +1,6 @@
use std::path::{Path,PathBuf}; use std::path::{Path,PathBuf};
use std::fs; use std::fs;
use {CommandLine,Result,ImageHeader,MetaInfo,Mount}; use {Result,ImageHeader,MetaInfo,Mount,PublicKey,public_key_for_channel};
#[derive(Clone)] #[derive(Clone)]
pub struct Partition { pub struct Partition {
@ -13,6 +13,8 @@ pub struct Partition {
struct HeaderInfo { struct HeaderInfo {
header: ImageHeader, header: ImageHeader,
metainfo: MetaInfo, metainfo: MetaInfo,
// None if no public key available for channel named in metainfo
pubkey: Option<PublicKey>,
} }
impl Partition { impl Partition {
@ -44,8 +46,17 @@ impl Partition {
return Ok(None); return Ok(None);
}, },
}; };
let pubkey = match public_key_for_channel(metainfo.channel()) {
Ok(result) => result,
Err(err) => {
warn!("Error parsing pubkey for channel '{}': {}", metainfo.channel(), err);
None
}
};
Ok(Some(HeaderInfo { Ok(Some(HeaderInfo {
header, metainfo header, metainfo, pubkey,
})) }))
} }
@ -95,34 +106,63 @@ impl Partition {
self.header().has_flag(ImageHeader::FLAG_PREFER_BOOT) self.header().has_flag(ImageHeader::FLAG_PREFER_BOOT)
} }
pub fn is_sig_failed(&self) -> bool {
self.header().status() == ImageHeader::STATUS_BAD_SIG
}
pub fn is_signature_valid(&self) -> bool {
if let Some(ref hinfo) = self.hinfo {
if let Some(ref pubkey) = hinfo.pubkey {
return pubkey.verify(
&self.header().metainfo_bytes(),
&self.header().signature())
}
}
false
}
pub fn has_public_key(&self) -> bool {
if let Some(ref h) = self.hinfo {
h.pubkey.is_some()
} else {
false
}
}
pub fn write_status(&mut self, status: u8) -> Result<()> { pub fn write_status(&mut self, status: u8) -> Result<()> {
self.header_mut().set_status(status); self.header_mut().set_status(status);
self.header().write_partition(&self.path) self.header().write_partition(&self.path)
} }
pub fn set_flag_and_write(&mut self, flag: u8) -> Result<()> {
self.header_mut().set_flag(flag);
self.header().write_partition(&self.path)
}
pub fn clear_flag_and_write(&mut self, flag: u8) -> Result<()> {
self.header_mut().clear_flag(flag);
self.header().write_partition(&self.path)
}
/// Called at boot to perform various checks and possibly /// Called at boot to perform various checks and possibly
/// update the status field to an error state. /// update the status field to an error state.
/// ///
/// Mark `STATUS_TRY_BOOT` partition as `STATUS_FAILED`. /// Mark `STATUS_TRY_BOOT` partition as `STATUS_FAILED`.
/// ///
/// If metainfo cannot be parsed, mark as `STATUS_BAD_META`. /// If a partition that had prior signature failure now
/// /// has a valid signature set to STATUS_NEW
/// Verify metainfo signature and mark `STATUS_BAD_SIG` if
/// signature verification fails.
/// ///
pub fn boot_scan(&mut self) -> Result<()> { pub fn boot_scan(&mut self) -> Result<()> {
if !self.is_initialized() { if !self.is_initialized() {
return Ok(()) return Ok(())
} }
if self.header().status() == ImageHeader::STATUS_TRY_BOOT { if self.header().status() == ImageHeader::STATUS_TRY_BOOT {
warn!("Partition {} has STATUS_TRY_BOOT, assuming it failed boot attempt and marking STATUS_FAILED", self.path().display());
self.write_status(ImageHeader::STATUS_FAILED)?; self.write_status(ImageHeader::STATUS_FAILED)?;
} }
if self.is_sig_failed() && self.is_signature_valid() {
if !CommandLine::nosignatures() { self.write_status(ImageHeader::STATUS_NEW)?;
if let Err(e) = self.header().verify_signature() {
warn!("Signature verification failed on partition: {}", e);
self.write_status(ImageHeader::STATUS_BAD_SIG)?;
}
} }
Ok(()) Ok(())
} }