diff --git a/src/blake2b.rs b/src/blake2b.rs index 4db2d57..6b975e8 100644 --- a/src/blake2b.rs +++ b/src/blake2b.rs @@ -35,6 +35,7 @@ use crate::mac::{Mac, MacResult}; use alloc::vec::Vec; use core::iter::repeat; +/// Blake2b Context (Dynamic output size) pub type Context = blake2b::ContextDyn; /// Blake2b Context @@ -84,11 +85,13 @@ impl Blake2b { self.computed = false; } + /// Reset the blake2 context with a key pub fn reset_with_key(&mut self, key: &[u8]) { self.ctx.reset_with_key(key); self.computed = false; } + /// Compute the blake2 function as one call pub fn blake2b(out: &mut [u8], input: &[u8], key: &[u8]) { let mut hasher: Blake2b = if !key.is_empty() { Blake2b::new_keyed(out.len(), key) diff --git a/src/blake2s.rs b/src/blake2s.rs index 4ba0f4e..f88e6f0 100644 --- a/src/blake2s.rs +++ b/src/blake2s.rs @@ -35,6 +35,7 @@ use crate::mac::{Mac, MacResult}; use alloc::vec::Vec; use core::iter::repeat; +/// Blake2s Context (Dynamic output size) pub type Context = blake2s::ContextDyn; /// Blake2s Context @@ -84,11 +85,13 @@ impl Blake2s { self.computed = false; } + /// Reset the blake2 context with a key pub fn reset_with_key(&mut self, key: &[u8]) { self.ctx.reset_with_key(key); self.computed = false; } + /// Compute the blake2 function as one call pub fn blake2s(out: &mut [u8], input: &[u8], key: &[u8]) { let mut hasher: Blake2s = if !key.is_empty() { Blake2s::new_keyed(out.len(), key) diff --git a/src/chacha/mod.rs b/src/chacha/mod.rs index 44c5b80..b0c33d6 100644 --- a/src/chacha/mod.rs +++ b/src/chacha/mod.rs @@ -1,3 +1,21 @@ +//! ChaCha Stream Cipher -- Engine implementation +//! +//! Implementation of [ChaCha spec](https://www.rfc-editor.org/info/rfc7539) +//! which is a fast and lean stream cipher. +//! +//! The maximum amount of data to be processed by a single instance of a ChaCha +//! Context, is 256Gb (due to the 32 bits counter). Note that this is not +//! enforced by the context, and using a context to process more than 256Gb of +//! data would be insecure. +//! +//! The Engine is parametrized with the number of rounds to execute, which is +//! enforced by assertion to be either 8, 12 or 20. +//! +//! Note that with stream cipher, there's only one operation [`ChaChaEngine::::process`] +//! and its variant [`ChaChaEngine::::process_mut`] instead of the typical +//! cipher operation encrypt and decrypt. +//! + #[cfg(not(all( any(target_arch = "x86", target_arch = "x86_64"), any(target_feature = "sse2", target_feature = "avx2") diff --git a/src/chacha20.rs b/src/chacha20.rs index 3d9c923..9b34a4c 100644 --- a/src/chacha20.rs +++ b/src/chacha20.rs @@ -60,6 +60,7 @@ pub struct ChaCha { offset: usize, } +/// Alias to usual ChaCha context with 20 rounds pub type ChaCha20 = ChaCha<20>; impl ChaCha { diff --git a/src/chacha20poly1305.rs b/src/chacha20poly1305.rs index 7f4adff..96b322b 100644 --- a/src/chacha20poly1305.rs +++ b/src/chacha20poly1305.rs @@ -232,7 +232,9 @@ impl ContextEncryption { /// Whether or not, the decryption was succesful related to the expected tag #[derive(Debug, Clone, PartialEq, Eq)] pub enum DecryptionResult { + /// The tag matched, the data has been verified as not tempered Match, + /// The tag mismatched, which imply that some data is incorrect or has been tempered MisMatch, } @@ -281,6 +283,7 @@ fn pad16(mac: &mut Poly1305, len: u64) { } } +/// Type alias to the common ChaChaPoly1305 with 20 rounds ChaCha pub type ChaCha20Poly1305 = ChaChaPoly1305<20>; impl ChaChaPoly1305 { diff --git a/src/constant_time.rs b/src/constant_time.rs index cd152ac..945e7c3 100644 --- a/src/constant_time.rs +++ b/src/constant_time.rs @@ -46,12 +46,17 @@ pub struct CtOption { } impl Choice { + /// Return true if the Choice represent true pub fn is_true(self) -> bool { self.0 == 1 } + /// return true if the Choice represent false pub fn is_false(self) -> bool { self.0 == 0 } + /// Toggle the value represented by the Choice in constant time + /// + /// true become false, false become true pub fn negate(self) -> Self { Choice(1 ^ self.0) } @@ -94,6 +99,7 @@ impl From<(Choice, T)> for CtOption { } impl CtOption { + /// Transform a `CtOption` into a non constant `Option` pub fn into_option(self) -> Option { if self.present.is_true() { Some(self.t) @@ -108,7 +114,12 @@ impl CtOption { /// Note that zero means 0 with integer primitive, or for array of integer /// it means all elements are 0 pub trait CtZero { + /// Check that the element is 'zero' in constant time and return the associated `Choice` fn ct_zero(self) -> Choice; + + /// Check that the element is 'non-zero' in constant time and return the associated `Choice` + /// + /// The following call `ct_nonzero(t)` is equivalent to `ct_zero(t).negate()` fn ct_nonzero(self) -> Choice; } @@ -116,7 +127,14 @@ pub trait CtZero { /// /// This equivalent to the > operator found in the core library. pub trait CtGreater: Sized { + /// Check that the first element is greater to the second element in + /// constant time and return the associated `Choice` fn ct_gt(a: Self, b: Self) -> Choice; + + /// Check that the first element is lesser or equal to the second element in + /// constant time and return the associated `Choice` + /// + /// This is equivalent to calling `ct_gt` with the argument swapped fn ct_le(a: Self, b: Self) -> Choice { Self::ct_gt(b, a) } @@ -126,7 +144,14 @@ pub trait CtGreater: Sized { /// /// This equivalent to the < operator found in the core library. pub trait CtLesser: Sized { + /// Check that the first element is lesser to the second element in + /// constant time and return the associated `Choice` fn ct_lt(a: Self, b: Self) -> Choice; + + /// Check that the first element is greater or equal to the second element in + /// constant time and return the associated `Choice` + /// + /// This is equivalent of calling `ct_lt` with the argument swapped fn ct_ge(a: Self, b: Self) -> Choice { Self::ct_lt(b, a) } @@ -136,7 +161,12 @@ pub trait CtLesser: Sized { /// /// This equivalent to the == operator found in the core library. pub trait CtEqual { + /// Check that the two element are equal in constant time and return the associated `Choice` fn ct_eq(self, b: Rhs) -> Choice; + + /// Check that the two element are not equal in constant time and return the associated `Choice` + /// + /// this is equivalent to calling `lhs.ct_eq(rhs).negate()` fn ct_ne(self, b: Rhs) -> Choice; } diff --git a/src/curve25519/fe/fe64/mod.rs b/src/curve25519/fe/fe64/mod.rs index cda18ee..03ddbf0 100644 --- a/src/curve25519/fe/fe64/mod.rs +++ b/src/curve25519/fe/fe64/mod.rs @@ -36,9 +36,13 @@ impl PartialEq for Fe { impl Eq for Fe {} impl Fe { + /// Field Element constant representing 0 pub const ZERO: Fe = Fe([0, 0, 0, 0, 0]); + + /// Field Element constant representing 1 pub const ONE: Fe = Fe([1, 0, 0, 0, 0]); + /// Field Element constant for Sqrt(-1) pub const SQRTM1: Fe = Fe([ 0x61B274A0EA0B0, 0xD5A5FC8F189D, @@ -46,6 +50,8 @@ impl Fe { 0x78595A6804C9E, 0x2B8324804FC1D, ]); + + /// Field element constant for D pub const D: Fe = Fe([ 0x34DCA135978A3, 0x1A8283B156EBD, @@ -53,6 +59,8 @@ impl Fe { 0x739C663A03CBB, 0x52036CEE2B6FF, ]); + + /// Field element constant for D2 pub const D2: Fe = Fe([ 0x69B9426B2F159, 0x35050762ADD7A, @@ -381,10 +389,12 @@ impl Fe { x } + /// Check that the field element is non zero pub fn is_nonzero(&self) -> bool { CtEqual::ct_ne(&self.to_bytes(), &[0; 32]).into() } + /// Check that the field element is 'negative' pub fn is_negative(&self) -> bool { (self.to_packed()[0] & 1) != 0 } diff --git a/src/curve25519/fe/mod.rs b/src/curve25519/fe/mod.rs index 3601c03..eeadc6c 100644 --- a/src/curve25519/fe/mod.rs +++ b/src/curve25519/fe/mod.rs @@ -25,6 +25,7 @@ pub use fe32::*; pub use fe64::*; impl Fe { + /// Raise a field element to 2^255-23 pub fn pow25523(&self) -> Fe { let z2 = self.square(); let z8 = z2.square_repeatdly(2); diff --git a/src/curve25519/ge.rs b/src/curve25519/ge.rs index 81ab96d..a1f0dfd 100644 --- a/src/curve25519/ge.rs +++ b/src/curve25519/ge.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use core::cmp::Ordering; use core::ops::{Add, Neg, Sub}; diff --git a/src/curve25519/scalar/scalar64.rs b/src/curve25519/scalar/scalar64.rs index 05de25e..e68b93a 100644 --- a/src/curve25519/scalar/scalar64.rs +++ b/src/curve25519/scalar/scalar64.rs @@ -2,7 +2,7 @@ //! //! port of //! -//! scalar is back by 5 Limbs in 56 bits unsaturated (except last) +//! scalar is backed by 5 Limbs in 56 bits unsaturated (except last) /// Scalar in the field ℤ/2^252 + 27742317777372353535851937790883648493) #[derive(Debug, Clone, PartialEq, Eq)] @@ -80,9 +80,15 @@ const MASK40: u64 = 0x0000_00ff_ffff_ffff; const MASK56: u64 = 0x00ff_ffff_ffff_ffff; impl Scalar { + /// The 0 Scalar constant pub const ZERO: Self = Scalar([0, 0, 0, 0, 0]); + + /// The 1 Scalar constant pub const ONE: Self = Scalar([1, 0, 0, 0, 0]); + /// Create a Scalar from bytes + /// + /// Unpack 32 bytes into the 5 64bits limbs unsaturated representation pub const fn from_bytes(bytes: &[u8; 32]) -> Self { // load 8 bytes from input[ofs..ofs+7] as little endian u64 #[inline] @@ -110,7 +116,7 @@ impl Scalar { Scalar([out0, out1, out2, out3, out4]) } - // Same as from_bytes but check whether the value + /// Same as from_bytes but check whether the value is less than the order of the `Scalar` Field. pub fn from_bytes_canonical(bytes: &[u8; 32]) -> Option { let scalar = Self::from_bytes(bytes); if lt_order(&scalar.0) { @@ -120,6 +126,10 @@ impl Scalar { } } + /// Convert the Scalar back into a raw array of 32 bytes + /// + /// The function expect the limbs to have been reduce + /// ahead of calling. pub const fn to_bytes(&self) -> [u8; 32] { // contract limbs into saturated limbs let c0 = self.0[1] << 56 | self.0[0]; diff --git a/src/ed25519.rs b/src/ed25519.rs index b33bfec..943bc5f 100644 --- a/src/ed25519.rs +++ b/src/ed25519.rs @@ -27,11 +27,22 @@ use crate::hashing::sha2::Sha512; use core::convert::TryFrom; #[deprecated(since = "0.4.0", note = "use `PRIVATE_KEY_LENGTH`")] +/// ED25519 Seed length pub const SEED_LENGTH: usize = 32; + +/// ED25519 Private key length (32 bytes) pub const PRIVATE_KEY_LENGTH: usize = 32; + +/// ED25519 Public key length (32 bytes) pub const PUBLIC_KEY_LENGTH: usize = 32; + +/// ED25519 Keypair length (64 bytes) pub const KEYPAIR_LENGTH: usize = PRIVATE_KEY_LENGTH + PUBLIC_KEY_LENGTH; + +/// ED25519 Extended key size (64 bytes) pub const EXTENDED_KEY_LENGTH: usize = 64; + +/// ED25519 Signature size (64 bytes) pub const SIGNATURE_LENGTH: usize = 64; // clamp the scalar by: diff --git a/src/hashing/blake2b.rs b/src/hashing/blake2b.rs index 9be654b..206390d 100644 --- a/src/hashing/blake2b.rs +++ b/src/hashing/blake2b.rs @@ -31,11 +31,15 @@ use super::blake2::{EngineB as Engine, LastBlock}; use crate::cryptoutil::{write_u64v_le, zero}; +/// Blake2b Algorithm parametrized by the number of bits to output #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Blake2b; impl Blake2b { + /// Output of the hashing algorithm in bits pub const OUTPUT_BITS: usize = BITS; + /// The block size in bytes of the algorithm, which is the number of bytes the algorithm typically buffer + /// before calling its compression function pub const BLOCK_BYTES: usize = Engine::BLOCK_BYTES; /// Create a new context for this algorithm @@ -94,11 +98,15 @@ impl Context { Self { eng, buf, buflen } } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, input: &[u8]) -> Self { self.update_mut(input); self } + /// Update in-place the hashing state by adding the input bytes slice into the state + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, mut input: &[u8]) { if input.is_empty() { return; @@ -134,12 +142,20 @@ impl Context { write_u64v_le(&mut self.buf[0..64], &self.eng.h); } + /// Finalize the context and output the array of bytes into the mut output slice + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// The output slice size is assert checked to have the correct expected size. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize_at(mut self, out: &mut [u8]) { assert!(out.len() == ((BITS + 7) / 8)); self.internal_final(); out.copy_from_slice(&self.buf[0..out.len()]); } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset_at(&mut self, out: &mut [u8]) { assert!(out.len() == ((BITS + 7) / 8)); self.internal_final(); @@ -147,6 +163,7 @@ impl Context { self.reset(); } + /// Same as `finalize_reset` but also specify the key to reset with pub fn finalize_reset_with_key_at(&mut self, key: &[u8], out: &mut [u8]) { assert!(out.len() == ((BITS + 7) / 8)); self.internal_final(); @@ -161,6 +178,7 @@ impl Context { zero(&mut self.buf[..]); } + /// Reset the context to the state after calling `new_keyed` with the given key pub fn reset_with_key(&mut self, key: &[u8]) { assert!(key.len() <= Engine::MAX_KEYLEN); @@ -181,7 +199,9 @@ impl ContextDyn { /// Create a new Blake2b context with a specific output size in bytes defined by parameter /// /// the size need to be between 0 (non included) and 64 bytes (included) + /// which means BITS need to be between 1 and 512. pub fn new(output_bytes: usize) -> Self { + assert!(output_bytes > 0 && output_bytes <= Engine::MAX_OUTLEN); Self::new_keyed(output_bytes, &[]) } @@ -209,11 +229,15 @@ impl ContextDyn { } } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, input: &[u8]) -> Self { self.update_mut(input); self } + /// Update in-place the hashing state by adding the input bytes slice into the state + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, mut input: &[u8]) { if input.is_empty() { return; @@ -249,12 +273,20 @@ impl ContextDyn { write_u64v_le(&mut self.buf[0..64], &self.eng.h); } + /// Finalize the context and output the array of bytes into the mut output slice + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// The output slice size is assert checked to have the correct expected size. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize_at(mut self, out: &mut [u8]) { assert!(out.len() == self.outlen); self.internal_final(); out.copy_from_slice(&self.buf[0..out.len()]); } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset_at(&mut self, out: &mut [u8]) { assert!(out.len() == self.outlen); self.internal_final(); @@ -262,6 +294,7 @@ impl ContextDyn { self.reset(); } + /// Same as `finalize_reset` but also specify the key to reset with pub fn finalize_reset_with_key_at(&mut self, key: &[u8], out: &mut [u8]) { assert!(out.len() == self.outlen); self.internal_final(); @@ -276,6 +309,7 @@ impl ContextDyn { zero(&mut self.buf[..]); } + /// Reset the context to the state after calling `new_keyed` with the given key pub fn reset_with_key(&mut self, key: &[u8]) { assert!(key.len() <= Engine::MAX_KEYLEN); @@ -291,6 +325,7 @@ impl ContextDyn { } } + /// The output size in bits pub fn output_bits(&self) -> usize { self.outlen * 8 } @@ -301,16 +336,26 @@ impl ContextDyn { macro_rules! context_finalize { ($size:literal) => { impl Context<$size> { + /// Finalize the context and return an array of bytes + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize(self) -> [u8; $size / 8] { let mut out = [0; $size / 8]; self.finalize_at(&mut out); out } + + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset(&mut self) -> [u8; $size / 8] { let mut out = [0; $size / 8]; self.finalize_reset_at(&mut out); out } + + /// Same as `finalize_reset` but also specify the key to reset with pub fn finalize_reset_with_key(&mut self, key: &[u8]) -> [u8; $size / 8] { let mut out = [0; $size / 8]; self.finalize_reset_with_key_at(key, &mut out); diff --git a/src/hashing/blake2s.rs b/src/hashing/blake2s.rs index 26bc523..e0ca15a 100644 --- a/src/hashing/blake2s.rs +++ b/src/hashing/blake2s.rs @@ -31,11 +31,15 @@ use super::blake2::{EngineS as Engine, LastBlock}; use crate::cryptoutil::{write_u32v_le, zero}; +/// Blake2s Algorithm parametrized by the number of bits to output #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Blake2s; impl Blake2s { + /// Output of the hashing algorithm in bits pub const OUTPUT_BITS: usize = BITS; + /// The block size in bytes of the algorithm, which is the number of bytes the algorithm typically buffer + /// before calling its compression function pub const BLOCK_BYTES: usize = Engine::BLOCK_BYTES; /// Create a new context for this algorithm @@ -94,11 +98,15 @@ impl Context { Self { eng, buf, buflen } } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, input: &[u8]) -> Self { self.update_mut(input); self } + /// Update in-place the hashing state by adding the input bytes slice into the state + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, mut input: &[u8]) { if input.is_empty() { return; @@ -134,12 +142,20 @@ impl Context { write_u32v_le(&mut self.buf[0..32], &self.eng.h); } + /// Finalize the context and output the array of bytes into the mut output slice + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// The output slice size is assert checked to have the correct expected size. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize_at(mut self, out: &mut [u8]) { assert!(out.len() == ((BITS + 7) / 8)); self.internal_final(); out.copy_from_slice(&self.buf[0..out.len()]); } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset_at(&mut self, out: &mut [u8]) { assert!(out.len() == ((BITS + 7) / 8)); self.internal_final(); @@ -147,6 +163,7 @@ impl Context { self.reset(); } + /// Same as `finalize_reset` but also specify the key to reset with pub fn finalize_reset_with_key_at(&mut self, key: &[u8], out: &mut [u8]) { assert!(out.len() == ((BITS + 7) / 8)); self.internal_final(); @@ -161,6 +178,7 @@ impl Context { zero(&mut self.buf[..]); } + /// Reset the context to the state after calling `new_keyed` with the given key pub fn reset_with_key(&mut self, key: &[u8]) { assert!(key.len() <= Engine::MAX_KEYLEN); @@ -211,11 +229,15 @@ impl ContextDyn { } } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, input: &[u8]) -> Self { self.update_mut(input); self } + /// Update in-place the hashing state by adding the input bytes slice into the state + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, mut input: &[u8]) { if input.is_empty() { return; @@ -251,12 +273,20 @@ impl ContextDyn { write_u32v_le(&mut self.buf[0..32], &self.eng.h); } + /// Finalize the context and output the array of bytes into the mut output slice + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// The output slice size is assert checked to have the correct expected size. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize_at(mut self, out: &mut [u8]) { assert!(out.len() == self.outlen); self.internal_final(); out.copy_from_slice(&self.buf[0..out.len()]); } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset_at(&mut self, out: &mut [u8]) { assert!(out.len() == self.outlen); self.internal_final(); @@ -264,6 +294,7 @@ impl ContextDyn { self.reset(); } + /// Same as `finalize_reset` but also specify the key to reset with pub fn finalize_reset_with_key_at(&mut self, key: &[u8], out: &mut [u8]) { assert!(out.len() == self.outlen); self.internal_final(); @@ -278,6 +309,7 @@ impl ContextDyn { zero(&mut self.buf[..]); } + /// Reset the context to the state after calling `new_keyed` with the given key pub fn reset_with_key(&mut self, key: &[u8]) { assert!(key.len() <= Engine::MAX_KEYLEN); @@ -293,6 +325,7 @@ impl ContextDyn { } } + /// The output size in bits pub fn output_bits(&self) -> usize { self.outlen * 8 } @@ -303,16 +336,26 @@ impl ContextDyn { macro_rules! context_finalize { ($size:literal) => { impl Context<$size> { + /// Finalize the context and return an array of bytes + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize(self) -> [u8; $size / 8] { let mut out = [0; $size / 8]; self.finalize_at(&mut out); out } + + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset(&mut self) -> [u8; $size / 8] { let mut out = [0; $size / 8]; self.finalize_reset_at(&mut out); out } + + /// Same as `finalize_reset` but also specify the key to reset with pub fn finalize_reset_with_key(&mut self, key: &[u8]) -> [u8; $size / 8] { let mut out = [0; $size / 8]; self.finalize_reset_with_key_at(key, &mut out); diff --git a/src/hashing/keccak.rs b/src/hashing/keccak.rs index 0ba1cae..0c6bae7 100644 --- a/src/hashing/keccak.rs +++ b/src/hashing/keccak.rs @@ -18,7 +18,10 @@ macro_rules! keccak_impl { pub struct $C; impl $C { + /// Output of the hashing algorithm in bits pub const OUTPUT_BITS: usize = $digestlength * 8; + /// The block size in bytes of the algorithm, which is the number of bytes the algorithm typically buffer + /// before calling its compression function pub const BLOCK_BYTES: usize = B - ($digestlength * 2); /// Create a new context for this algorithm @@ -33,19 +36,26 @@ macro_rules! keccak_impl { pub struct $context(Engine<$digestlength, 0>); impl $context { + /// Construct a new `Keccak` object pub const fn new() -> Self { Self(Engine::new()) } + /// Update in-place the hashing state by adding the input bytes slice into the state + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, data: &[u8]) { self.0.process(data) } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, data: &[u8]) -> Self { self.0.process(data); self } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset(&mut self) -> [u8; $digestlength] { let mut out = [0; $digestlength]; self.0.output(&mut out); @@ -53,12 +63,18 @@ macro_rules! keccak_impl { out } + /// Finalize the context and return an array of bytes + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize(mut self) -> [u8; $digestlength] { let mut out = [0; $digestlength]; self.0.output(&mut out); out } + /// Reset the context state, as if a new context had been created pub fn reset(&mut self) { self.0.reset() } diff --git a/src/hashing/ripemd160.rs b/src/hashing/ripemd160.rs index 08a2f61..030d4c9 100644 --- a/src/hashing/ripemd160.rs +++ b/src/hashing/ripemd160.rs @@ -22,7 +22,10 @@ const WORK_BUF_LEN: usize = 16; pub struct Ripemd160; impl Ripemd160 { + /// Output of the hashing algorithm in bits pub const OUTPUT_BITS: usize = 160; + /// The block size in bytes of the algorithm, which is the number of bytes the algorithm typically buffer + /// before calling its compression function pub const BLOCK_BYTES: usize = 64; /// Create a new context for this algorithm @@ -335,7 +338,7 @@ fn process_msg_blocks(data: &[u8], h: &mut [u32; DIGEST_BUF_LEN]) { const H: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; impl Context { - // Construct a new `Ripemd160` object + /// Construct a new `Ripemd160` object pub const fn new() -> Self { Self { h: H, @@ -344,6 +347,9 @@ impl Context { } } + /// Update in-place the hashing state by adding the input bytes slice into the state + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, msg: &[u8]) { // Assumes that msg.len() can be converted to u64 without overflow self.processed_bytes += msg.len() as u64; @@ -353,17 +359,21 @@ impl Context { }); } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, input: &[u8]) -> Self { self.update_mut(input); self } + /// Reset the context state, as if a new context had been created pub fn reset(&mut self) { self.processed_bytes = 0; self.h = H; self.buffer.reset(); } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset(&mut self) -> [u8; 20] { let st_h = &mut self.h; @@ -384,6 +394,11 @@ impl Context { out } + /// Finalize the context and return an array of bytes + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize(mut self) -> [u8; 20] { self.finalize_reset() } diff --git a/src/hashing/sha1.rs b/src/hashing/sha1.rs index fb6c9c1..9707082 100644 --- a/src/hashing/sha1.rs +++ b/src/hashing/sha1.rs @@ -357,7 +357,10 @@ fn mk_result(st: &mut Context, rs: &mut [u8; 20]) { pub struct Sha1; impl Sha1 { + /// Output of the hashing algorithm in bits pub const OUTPUT_BITS: usize = 160; + /// The block size in bytes of the algorithm, which is the number of bytes the algorithm typically buffer + /// before calling its compression function pub const BLOCK_BYTES: usize = 64; /// Create a new context for this algorithm @@ -391,11 +394,15 @@ impl Context { } } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, input: &[u8]) -> Self { self.update_mut(input); self } + /// Update in-place the hashing state by adding the input bytes slice into + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, input: &[u8]) { self.processed_bytes += input.len() as u64; let h = &mut self.h; @@ -404,18 +411,26 @@ impl Context { }); } + /// Finalize the context and return an array of bytes + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize(mut self) -> [u8; 20] { let mut out = [0; 20]; mk_result(&mut self, &mut out); out } + /// Reset the context state, as if a new context had been created pub fn reset(&mut self) { self.processed_bytes = 0; self.h = H; self.buffer.reset(); } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset(&mut self) -> [u8; 20] { let mut out = [0; 20]; mk_result(self, &mut out); diff --git a/src/hashing/sha2/mod.rs b/src/hashing/sha2/mod.rs index 7f9e1b2..f508592 100644 --- a/src/hashing/sha2/mod.rs +++ b/src/hashing/sha2/mod.rs @@ -85,7 +85,11 @@ macro_rules! digest { pub struct $name; impl $name { + /// Output of the hashing algorithm in bits pub const OUTPUT_BITS: usize = $output_bits; + + /// The block size in bytes of the algorithm, which is the number of bytes the algorithm typically buffer + /// before calling its compression function pub const BLOCK_BYTES: usize = $block_size; /// Create a new context for this algorithm @@ -108,15 +112,24 @@ macro_rules! digest { } } + /// Update in-place the hashing state by adding the input bytes slice into the state + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, input: &[u8]) { self.engine.input(input) } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, input: &[u8]) -> Self { self.engine.input(input); self } + /// Finalize the context and return an array of bytes + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize(mut self) -> [u8; $output_bits / 8] { let mut out = [0; $output_bits / 8]; self.engine.finish(); @@ -124,6 +137,8 @@ macro_rules! digest { out } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset(&mut self) -> [u8; $output_bits / 8] { let mut out = [0; $output_bits / 8]; self.engine.finish(); @@ -132,6 +147,7 @@ macro_rules! digest { out } + /// Reset the context state, as if a new context had been created pub fn reset(&mut self) { self.engine.reset(&$state); } diff --git a/src/hashing/sha3.rs b/src/hashing/sha3.rs index 27b9104..f940d92 100644 --- a/src/hashing/sha3.rs +++ b/src/hashing/sha3.rs @@ -301,7 +301,10 @@ macro_rules! sha3_impl { pub struct $C; impl $C { + /// Output of the hashing algorithm in bits pub const OUTPUT_BITS: usize = $digestlength * 8; + /// The block size in bytes of the algorithm, which is the number of bytes the algorithm typically buffer + /// before calling its compression function pub const BLOCK_BYTES: usize = B - ($digestlength * 2); /// Create a new context for this algorithm @@ -316,19 +319,26 @@ macro_rules! sha3_impl { pub struct $context(Engine<$digestlength, 2>); impl $context { + /// Create a new SHA3 Context pub const fn new() -> Self { Self(Engine::new()) } + /// Update in-place the hashing state by adding the input bytes slice into the state + /// + /// For the immutable version see [`update`] pub fn update_mut(&mut self, data: &[u8]) { self.0.process(data) } + /// Update the hashing state by adding the input bytes slice into the state pub fn update(mut self, data: &[u8]) -> Self { self.0.process(data); self } + /// Same as `finalize` but do not consume the context, but instead + /// reset it in a ready to use state. pub fn finalize_reset(&mut self) -> [u8; $digestlength] { let mut out = [0; $digestlength]; self.0.output(&mut out); @@ -336,12 +346,18 @@ macro_rules! sha3_impl { out } + /// Finalize the context and return an array of bytes + /// + /// The context is consumed by this function, to prevent buggy reuse. + /// + /// If the context need to be kept before finalizing, the user can clone the Context pub fn finalize(mut self) -> [u8; $digestlength] { let mut out = [0; $digestlength]; self.0.output(&mut out); out } + /// Reset the context state, as if a new context had been created pub fn reset(&mut self) { self.0.reset() } diff --git a/src/kdf/argon2.rs b/src/kdf/argon2.rs index 42218c5..2eef3c7 100644 --- a/src/kdf/argon2.rs +++ b/src/kdf/argon2.rs @@ -689,10 +689,17 @@ enum Type { /// this allow to disassociate the chosen arguments (password, salt, aad), /// from the computationally and memory intensive tasks that argon2 go /// through to derive the final result. +/// +/// After H0 is computed with one call to blake2, the secret values to the overall +/// argon2 call can be disposed of, allowing for potentially tighter security around the secrets #[derive(Clone)] pub struct H0([u8; 64]); impl H0 { + /// Create a new initial hash value for Argon2 + /// + /// The secret material to argon2 (password and key) can be disposed of after this call, + /// and the computation of the value is fast compared to running argon2 pub fn new( params: &Params, password: &[u8], diff --git a/src/lib.rs b/src/lib.rs index d124cba..78868dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ #![no_std] #![cfg_attr(feature = "with-bench", feature(test))] #![cfg_attr(feature = "use-stdsimd", feature(stdsimd))] +#![deny(missing_docs)] #[cfg(test)] #[cfg(feature = "with-bench")] diff --git a/src/salsa20.rs b/src/salsa20.rs index 6afb96e..89f2d96 100644 --- a/src/salsa20.rs +++ b/src/salsa20.rs @@ -131,6 +131,7 @@ impl State { } } +/// Salsa streaming cipher context #[derive(Clone)] pub struct Salsa { state: State, @@ -138,6 +139,7 @@ pub struct Salsa { offset: usize, } +/// Typealias for Salsa with (common) 20 rounds pub type Salsa20 = Salsa<20>; impl Salsa { @@ -204,6 +206,7 @@ impl Salsa { } } +/// XSalsa streaming cipher context (Salsa Variant) #[derive(Clone)] pub struct XSalsa { state: State, @@ -211,6 +214,7 @@ pub struct XSalsa { offset: usize, } +/// Typealias for XSalsa with (common) 20 rounds pub type XSalsa20 = XSalsa<20>; impl XSalsa { diff --git a/src/x25519.rs b/src/x25519.rs index da7c091..ea56103 100644 --- a/src/x25519.rs +++ b/src/x25519.rs @@ -59,16 +59,18 @@ macro_rules! bytes_impl { }; } -/// Secret Key +/// X25519 Secret Key pub struct SecretKey([u8; 32]); bytes_impl!(SecretKey, 32); -/// Public Key +/// X25519 Public Key +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PublicKey([u8; 32]); bytes_impl!(PublicKey, 32); +/// X25519 Shared Secret (ECDH) pub struct SharedSecret([u8; 32]); bytes_impl!(SharedSecret, 32);