Skip to content

Commit

Permalink
Hide error details
Browse files Browse the repository at this point in the history
  • Loading branch information
Kijewski committed Sep 16, 2023
1 parent a0815ef commit c3d407b
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 228 deletions.
57 changes: 57 additions & 0 deletions api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#![warn(unused_extern_crates)]
#![warn(unused_lifetimes)]
#![warn(unused_results)]
#![allow(clippy::enum_variant_names)]
#![doc = include_str!("../README.md")]

mod constants;
Expand Down Expand Up @@ -78,3 +79,59 @@ pub enum ZipsignError {
/// An I/O occurred
Io(#[from] std::io::Error),
}

macro_rules! Error {
(
$(#[$meta:meta])+
$vis:vis struct $outer:ident($inner:ident) { $(
$(#[$field_meta:meta])+
$field:ident $(( $(
$(#[$ty_meta:meta])*
$field_type:ty
),+ $(,)? ))?
),+ $(,)? }
) => {
$(#[$meta])+
$vis struct $outer($inner);

#[derive(Debug, thiserror::Error)]
enum $inner { $(
$(#[$field_meta])+
$field $(( $(
$(#[$ty_meta])* $field_type,
)+ ))?,
)+ }

const _: () = {
impl std::fmt::Debug for $outer {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.0, f)
}
}

impl std::fmt::Display for $outer {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}

impl From<$inner> for $outer {
#[inline]
fn from(value: $inner) -> Self {
Self(value)
}
}

impl std::error::Error for $outer {
#[inline]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.0.source()
}
}
};
};
}

pub(crate) use Error;
57 changes: 26 additions & 31 deletions api/src/sign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@ pub use self::zip::{copy_and_sign_zip, SignZipError};
use crate::constants::{SignatureCountLeInt, BUF_LIMIT, HEADER_SIZE, MAGIC_HEADER};
use crate::{Sha512, SignatureError, SigningKey, KEYPAIR_LENGTH, SIGNATURE_LENGTH};

/// An error returned by [`read_signing_keys()`]
#[derive(Debug, thiserror::Error)]
pub enum ReadSigningKeysError {
/// Input did not contain a valid key
#[error("input #{1} did not contain a valid key")]
Construct(#[source] ed25519_dalek::ed25519::Error, usize),
/// No signing keys provided
#[error("no signing keys provided")]
Empty,
/// Could not read keys
#[error("could not read key in file #{1}")]
Read(#[source] std::io::Error, usize),
crate::Error! {
/// An error returned by [`read_signing_keys()`]
pub struct ReadSigningKeysError(KeysError) {
#[error("input #{1} did not contain a valid key")]
Construct(#[source] ed25519_dalek::ed25519::Error, usize),
#[error("no signing keys provided")]
Empty,
#[error("could not read key in file #{1}")]
Read(#[source] std::io::Error, usize),
}
}

/// Read signing keys from an [`Iterator`] of [readable][Read] inputs
Expand All @@ -42,13 +40,12 @@ where
let mut key = [0; KEYPAIR_LENGTH];
input
.and_then(|mut input| input.read_exact(&mut key))
.map_err(|err| ReadSigningKeysError::Read(err, key_index))?;
SigningKey::from_keypair_bytes(&key)
.map_err(|err| ReadSigningKeysError::Construct(err, key_index))
.map_err(|err| KeysError::Read(err, key_index))?;
SigningKey::from_keypair_bytes(&key).map_err(|err| KeysError::Construct(err, key_index))
})
.collect::<Result<Vec<_>, _>>()?;
if keys.is_empty() {
return Err(ReadSigningKeysError::Empty);
return Err(KeysError::Empty.into());
}
keys.sort_by(|l, r| {
l.verifying_key()
Expand All @@ -58,18 +55,16 @@ where
Ok(keys)
}

/// An error returned by [`gather_signature_data()`]
#[derive(Debug, thiserror::Error)]
pub enum GatherSignatureDataError {
/// No signing keys provided
#[error("no signing keys provided")]
Empty,
/// could not sign data
#[error("could not sign data with key #{1}")]
Signature(#[source] SignatureError, usize),
/// Too many signing keys provided
#[error("too many signing keys provided")]
TooManyKeys,
crate::Error! {
/// An error returned by [`gather_signature_data()`]
pub struct GatherSignatureDataError(SignaturesError) {
#[error("no signing keys provided")]
Empty,
#[error("could not sign data with key #{1}")]
Signature(#[source] SignatureError, usize),
#[error("too many signing keys provided")]
TooManyKeys,
}
}

/// Sign a pre-hashed message with all provided signing keys, and return a signature block incl.
Expand All @@ -80,12 +75,12 @@ pub fn gather_signature_data(
context: Option<&[u8]>,
) -> Result<Vec<u8>, GatherSignatureDataError> {
if keys.is_empty() {
return Err(GatherSignatureDataError::Empty);
return Err(SignaturesError::Empty.into());
}

let signature_bytes = HEADER_SIZE + keys.len() * SIGNATURE_LENGTH;
if signature_bytes > BUF_LIMIT {
return Err(GatherSignatureDataError::TooManyKeys);
return Err(SignaturesError::TooManyKeys.into());
}

let mut header = [0; HEADER_SIZE];
Expand All @@ -98,7 +93,7 @@ pub fn gather_signature_data(
for (idx, key) in keys.iter().enumerate() {
let signature = key
.sign_prehashed(prehashed_message.clone(), context)
.map_err(|err| GatherSignatureDataError::Signature(err, idx))?;
.map_err(|err| SignaturesError::Signature(err, idx))?;
buf.extend(signature.to_bytes());
}
Ok(buf)
Expand Down
61 changes: 27 additions & 34 deletions api/src/sign/tar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,24 @@ use crate::constants::{
};
use crate::{prehash, SigningKey};

/// An error returned by [`copy_and_sign_tar()`]
#[derive(Debug, thiserror::Error)]
pub enum SignTarError {
/// Could not copy input to output
#[error("could not copy input to output")]
Copy(#[source] std::io::Error),
/// Could not read input
#[error("could not read input")]
InputRead(#[source] std::io::Error),
/// Could not seek in input
#[error("could not seek in input")]
InputSeek(#[source] std::io::Error),
/// Could not seek in output
#[error("could not seek in output")]
OutputSeek(#[source] std::io::Error),
/// Could not write output
#[error("could not write output")]
OutputWrite(#[source] std::io::Error),
/// Could not sign pre-hashed message
#[error("could not sign pre-hashed message")]
Sign(#[source] GatherSignatureDataError),
/// Too many keys
#[error("too many keys")]
TooManyKeys,
crate::Error! {
/// An error returned by [`copy_and_sign_tar()`]
pub struct SignTarError(Error) {
#[error("could not copy input to output")]
Copy(#[source] std::io::Error),
#[error("could not read input")]
InputRead(#[source] std::io::Error),
#[error("could not seek in input")]
InputSeek(#[source] std::io::Error),
#[error("could not seek in output")]
OutputSeek(#[source] std::io::Error),
#[error("could not write output")]
OutputWrite(#[source] std::io::Error),
#[error("could not sign pre-hashed message")]
Sign(#[source] GatherSignatureDataError),
#[error("too many keys")]
TooManyKeys,
}
}

/// Copy a `.tar.gz` file and sign its content
Expand All @@ -50,28 +44,27 @@ where
O: ?Sized + Read + Seek + Write,
{
if keys.len() > SignatureCountLeInt::MAX as usize {
return Err(SignTarError::TooManyKeys);
return Err(Error::TooManyKeys.into());
}
let signature_bytes = SIGNATURE_LENGTH * keys.len() + HEADER_SIZE;
if (signature_bytes.saturating_add(2) / 3).saturating_mul(4) > BUF_LIMIT {
return Err(SignTarError::TooManyKeys);
return Err(Error::TooManyKeys.into());
}

// gather signature
let prehashed_message = prehash(input).map_err(SignTarError::InputRead)?;
let buf =
gather_signature_data(keys, &prehashed_message, context).map_err(SignTarError::Sign)?;
let prehashed_message = prehash(input).map_err(Error::InputRead)?;
let buf = gather_signature_data(keys, &prehashed_message, context).map_err(Error::Sign)?;
let buf = BASE64_STANDARD.encode(buf);
if buf.len() > BUF_LIMIT {
return Err(SignTarError::TooManyKeys);
return Err(Error::TooManyKeys.into());
}

// copy input
input.rewind().map_err(SignTarError::InputSeek)?;
let _: u64 = copy(input, output).map_err(SignTarError::Copy)?;
input.rewind().map_err(Error::InputSeek)?;
let _: u64 = copy(input, output).map_err(Error::Copy)?;

// write signature
let start = output.stream_position().map_err(SignTarError::OutputSeek)?;
let start = output.stream_position().map_err(Error::OutputSeek)?;
let mut start_buf = [0u8; 16];
write!(&mut start_buf[..], "{start:016x}").unwrap();

Expand All @@ -80,7 +73,7 @@ where
tail.extend(buf.into_bytes()); // GZIP comment
tail.extend(start_buf); // GZIP comment
tail.extend(GZIP_END);
output.write_all(&tail).map_err(SignTarError::OutputWrite)?;
output.write_all(&tail).map_err(Error::OutputWrite)?;

Ok(())
}
Loading

0 comments on commit c3d407b

Please sign in to comment.