forked from brl/citadel-tools
refactor partition signature verification
This commit is contained in:
parent
72b7af4f2d
commit
8f8cbab72f
@ -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);
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user