tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

digest.rs (4099B)


      1 // Copyright 2023 Cryspen Sarl
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 //! This module provides common interface traits for digest/hashing functionality.
     10 
     11 pub mod arrayref;
     12 pub mod owned;
     13 pub mod slice;
     14 
     15 #[cfg(feature = "generic-tests")]
     16 pub mod tests;
     17 
     18 /// Error indicating that updating the digest state failed.
     19 #[derive(Debug, PartialEq)]
     20 pub enum UpdateError {
     21    /// The length of the provided payload is invalid.
     22    InvalidPayloadLength,
     23    ///The maximum input length is exceeded.
     24    MaximumLengthExceeded,
     25    /// Unknown error.
     26    Unknown,
     27 }
     28 
     29 impl core::fmt::Display for UpdateError {
     30    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
     31        let text = match self {
     32            UpdateError::InvalidPayloadLength => "the length of the provided payload is invalid",
     33            UpdateError::MaximumLengthExceeded => "the maximum input length is exceeded",
     34            UpdateError::Unknown => "indicates an unknown error",
     35        };
     36 
     37        f.write_str(text)
     38    }
     39 }
     40 
     41 #[cfg(feature = "error-in-core")]
     42 mod error_in_core {
     43 
     44    impl core::error::Error for super::UpdateError {}
     45 }
     46 
     47 /// Base trait for incremental functionality.
     48 ///
     49 /// Traits that are built on top of this trait:
     50 /// - [`slice::DigestIncremental`]
     51 /// - [`arrayref::DigestIncremental`]
     52 /// - [`owned::DigestIncremental`]
     53 pub trait DigestIncrementalBase {
     54    /// The digest state.
     55    type IncrementalState;
     56    /// Reset the digest state.
     57    fn reset(state: &mut Self::IncrementalState);
     58    /// Update the digest state with the `payload`.
     59    fn update(state: &mut Self::IncrementalState, payload: &[u8]) -> Result<(), UpdateError>;
     60 }
     61 
     62 #[derive(Clone)]
     63 /// A hasher that maintains the incremental digest state.
     64 pub struct Hasher<const N: usize, D: DigestIncrementalBase> {
     65    /// The digest state.
     66    pub state: D::IncrementalState,
     67 }
     68 
     69 impl<const N: usize, D: arrayref::DigestIncremental<N>> Default for Hasher<N, D>
     70 where
     71    D::IncrementalState: Default,
     72 {
     73    fn default() -> Self {
     74        Self {
     75            state: Default::default(),
     76        }
     77    }
     78 }
     79 
     80 impl<const N: usize, D: DigestIncrementalBase + slice::Hash> Hasher<N, D> {
     81    /// Oneshot API. Hash into a digest buffer, provided as a `&mut [u8]` slice.
     82    pub fn hash_slice(digest: &mut [u8], payload: &[u8]) -> Result<usize, slice::HashError> {
     83        D::hash(digest, payload)
     84    }
     85 }
     86 
     87 impl<const N: usize, D: slice::DigestIncremental> Hasher<N, D> {
     88    /// Finalize and write into a digest buffer, provided as a `&mut [u8]` slice.
     89    pub fn finish_slice(&mut self, digest: &mut [u8]) -> Result<usize, slice::FinishError> {
     90        D::finish(&mut self.state, digest)
     91    }
     92 }
     93 
     94 impl<const N: usize, D: DigestIncrementalBase> Hasher<N, D> {
     95    /// Update the digest state with the `payload`.
     96    pub fn update(&mut self, payload: &[u8]) -> Result<(), UpdateError> {
     97        D::update(&mut self.state, payload)
     98    }
     99    /// Reset the digest state.
    100    pub fn reset(&mut self) {
    101        D::reset(&mut self.state)
    102    }
    103 }
    104 
    105 impl<const N: usize, D: arrayref::DigestIncremental<N>> Hasher<N, D> {
    106    /// Finalize and write into a digest buffer, provided as a `&mut [u8; N]` array reference.
    107    pub fn finish(&mut self, digest: &mut [u8; N]) {
    108        D::finish(&mut self.state, digest)
    109    }
    110    /// owned version of `finish()`
    111    pub fn finish_to_owned(&mut self) -> [u8; N] {
    112        <D as owned::DigestIncremental<N>>::finish(&mut self.state)
    113    }
    114 }
    115 
    116 impl<const N: usize, D: DigestIncrementalBase + arrayref::Hash<N>> Hasher<N, D> {
    117    /// Oneshot API. Hash into a digest buffer, provided as a `&mut [u8; N]` array reference.
    118    pub fn hash(digest: &mut [u8; N], payload: &[u8]) -> Result<(), arrayref::HashError> {
    119        D::hash(digest, payload)
    120    }
    121    /// owned version of `hash()`
    122    pub fn hash_to_owned(payload: &[u8]) -> Result<[u8; N], arrayref::HashError> {
    123        <D as owned::Hash<N>>::hash(payload)
    124    }
    125 }