Skip to content

Commit

Permalink
hmac internals: Make it clearer that Context::try_sign doesn't panic.
Browse files Browse the repository at this point in the history
Use `Digest::try_finish()` instead of `Digest::finish()`.

Calculate `num_pending` directly from the inner digest, so that the
compiler can use `OutputLen` range analysis to prove that the buffer
is large enough.
  • Loading branch information
briansmith committed Dec 19, 2024
1 parent b4d1334 commit a8619bc
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 10 deletions.
9 changes: 5 additions & 4 deletions src/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,15 @@ impl Context {
/// `finish` consumes the context so it cannot be (mis-)used after `finish`
/// has been called.
pub fn finish(self) -> Digest {
self.try_finish().unwrap()
let cpu = cpu::features();
self.try_finish(cpu)
.map_err(error::Unspecified::from)
.unwrap()
}

fn try_finish(mut self) -> Result<Digest, error::Unspecified> {
let cpu_features = cpu::features();
pub(crate) fn try_finish(mut self, cpu_features: cpu::Features) -> Result<Digest, FinishError> {
self.block
.try_finish(&mut self.pending, self.num_pending, cpu_features)
.map_err(error::Unspecified::from)
}

/// The algorithm that this context is using.
Expand Down
14 changes: 8 additions & 6 deletions src/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,19 +312,21 @@ impl Context {
/// the return value of `sign` to a tag. Use `verify` for verification
/// instead.
pub fn sign(self) -> Tag {
self.try_sign().unwrap()
self.try_sign().map_err(error::Unspecified::from).unwrap()
}

fn try_sign(self) -> Result<Tag, error::Unspecified> {
fn try_sign(self) -> Result<Tag, digest::FinishError> {
let cpu_features = cpu::features();
let algorithm = self.inner.algorithm();
let inner = self.inner.try_finish(cpu_features)?;
let inner = inner.as_ref();
let num_pending = inner.len();
let buffer = &mut [0u8; digest::MAX_BLOCK_LEN];
let num_pending = algorithm.output_len();
buffer[..num_pending].copy_from_slice(self.inner.finish().as_ref());
const _BUFFER_IS_LARGE_ENOUGH_TO_HOLD_INNER: () =
assert!(digest::MAX_OUTPUT_LEN < digest::MAX_BLOCK_LEN);
buffer[..num_pending].copy_from_slice(inner);
self.outer
.try_finish(buffer, num_pending, cpu_features)
.map(Tag)
.map_err(error::Unspecified::from)
}
}

Expand Down

0 comments on commit a8619bc

Please sign in to comment.