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 KeyPair([u8; ED25519_PKCS8_V2_LEN]);
pub struct Signature(signature::Signature);

View File

@ -1,6 +1,6 @@
use std::path::{Path,PathBuf};
use std::fs;
use {CommandLine,Result,ImageHeader,MetaInfo,Mount};
use {Result,ImageHeader,MetaInfo,Mount,PublicKey,public_key_for_channel};
#[derive(Clone)]
pub struct Partition {
@ -13,6 +13,8 @@ pub struct Partition {
struct HeaderInfo {
header: ImageHeader,
metainfo: MetaInfo,
// None if no public key available for channel named in metainfo
pubkey: Option<PublicKey>,
}
impl Partition {
@ -44,8 +46,17 @@ impl Partition {
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 {
header, metainfo
header, metainfo, pubkey,
}))
}
@ -95,34 +106,63 @@ impl Partition {
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<()> {
self.header_mut().set_status(status);
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
/// update the status field to an error state.
///
/// Mark `STATUS_TRY_BOOT` partition as `STATUS_FAILED`.
///
/// If metainfo cannot be parsed, mark as `STATUS_BAD_META`.
///
/// Verify metainfo signature and mark `STATUS_BAD_SIG` if
/// signature verification fails.
/// If a partition that had prior signature failure now
/// has a valid signature set to STATUS_NEW
///
pub fn boot_scan(&mut self) -> Result<()> {
if !self.is_initialized() {
return Ok(())
}
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)?;
}
if !CommandLine::nosignatures() {
if let Err(e) = self.header().verify_signature() {
warn!("Signature verification failed on partition: {}", e);
self.write_status(ImageHeader::STATUS_BAD_SIG)?;
}
if self.is_sig_failed() && self.is_signature_valid() {
self.write_status(ImageHeader::STATUS_NEW)?;
}
Ok(())
}