Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/algorithms/mgf.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
//! Mask generation function common to both PSS and OAEP padding

use digest::{Digest, DynDigest, FixedOutputReset};
use digest::{Digest, FixedOutputReset};

/// Mask generation function.
///
/// Panics if out is larger than 2**32. This is in accordance with RFC 8017 - PKCS #1 B.2.1
pub(crate) fn mgf1_xor(out: &mut [u8], digest: &mut dyn DynDigest, seed: &[u8]) {
pub(crate) fn mgf1_xor<D>(out: &mut [u8], digest: &mut D, seed: &[u8])
where
D: Digest + FixedOutputReset,
{
let mut counter = [0u8; 4];
let mut i = 0;

Expand All @@ -17,7 +20,7 @@ pub(crate) fn mgf1_xor(out: &mut [u8], digest: &mut dyn DynDigest, seed: &[u8])
digest_input[0..seed.len()].copy_from_slice(seed);
digest_input[seed.len()..].copy_from_slice(&counter);

digest.update(digest_input.as_slice());
Digest::update(digest, digest_input.as_slice());
let digest_output = &*digest.finalize_reset();
let mut j = 0;
loop {
Expand Down
56 changes: 35 additions & 21 deletions src/algorithms/oaep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use alloc::boxed::Box;
use alloc::vec::Vec;

use digest::{Digest, DynDigest, FixedOutputReset};
use digest::{Digest, FixedOutputReset};
use rand_core::TryCryptoRng;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use zeroize::Zeroizing;
Expand Down Expand Up @@ -57,22 +57,27 @@ fn encrypt_internal<R: TryCryptoRng + ?Sized, MGF: FnMut(&mut [u8], &mut [u8])>(
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
pub(crate) fn oaep_encrypt<R: TryCryptoRng + ?Sized>(
pub(crate) fn oaep_encrypt<R, D, MGD>(
rng: &mut R,
msg: &[u8],
digest: &mut dyn DynDigest,
mgf_digest: &mut dyn DynDigest,
digest: &mut D,
mgf_digest: &mut MGD,
label: Option<Box<[u8]>>,
k: usize,
) -> Result<Zeroizing<Vec<u8>>> {
let h_size = digest.output_size();
) -> Result<Zeroizing<Vec<u8>>>
where
R: TryCryptoRng + ?Sized,
D: Digest + FixedOutputReset,
MGD: Digest + FixedOutputReset,
{
let h_size = <D as Digest>::output_size();

let label = label.unwrap_or_default();
if label.len() as u64 >= MAX_LABEL_LEN {
return Err(Error::LabelTooLong);
}

digest.update(&label);
Digest::update(digest, &label);
let p_hash = digest.finalize_reset();

encrypt_internal(rng, msg, &p_hash, h_size, k, |seed, db| {
Expand All @@ -89,16 +94,17 @@ pub(crate) fn oaep_encrypt<R: TryCryptoRng + ?Sized>(
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
pub(crate) fn oaep_encrypt_digest<
R: TryCryptoRng + ?Sized,
D: Digest,
MGD: Digest + FixedOutputReset,
>(
pub(crate) fn oaep_encrypt_digest<R, D, MGD>(
rng: &mut R,
msg: &[u8],
label: Option<Box<[u8]>>,
k: usize,
) -> Result<Zeroizing<Vec<u8>>> {
) -> Result<Zeroizing<Vec<u8>>>
where
R: TryCryptoRng + ?Sized,
D: Digest,
MGD: Digest + FixedOutputReset,
{
let h_size = <D as Digest>::output_size();

let label = label.unwrap_or_default();
Expand Down Expand Up @@ -126,21 +132,25 @@ pub(crate) fn oaep_encrypt_digest<
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
pub(crate) fn oaep_decrypt(
pub(crate) fn oaep_decrypt<D, MGD>(
em: &mut [u8],
digest: &mut dyn DynDigest,
mgf_digest: &mut dyn DynDigest,
digest: &mut D,
mgf_digest: &mut MGD,
label: Option<Box<[u8]>>,
k: usize,
) -> Result<Vec<u8>> {
let h_size = digest.output_size();
) -> Result<Vec<u8>>
where
D: Digest + FixedOutputReset,
MGD: Digest + FixedOutputReset,
{
let h_size = <D as Digest>::output_size();

let label = label.unwrap_or_default();
if label.len() as u64 >= MAX_LABEL_LEN {
return Err(Error::Decryption);
}

digest.update(&label);
Digest::update(digest, &label);

let expected_p_hash = digest.finalize_reset();

Expand Down Expand Up @@ -168,11 +178,15 @@ pub(crate) fn oaep_decrypt(
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
pub(crate) fn oaep_decrypt_digest<D: Digest, MGD: Digest + FixedOutputReset>(
pub(crate) fn oaep_decrypt_digest<D, MGD>(
em: &mut [u8],
label: Option<Box<[u8]>>,
k: usize,
) -> Result<Vec<u8>> {
) -> Result<Vec<u8>>
where
D: Digest,
MGD: Digest + FixedOutputReset,
{
let h_size = <D as Digest>::output_size();

let label = label.unwrap_or_default();
Expand Down
38 changes: 22 additions & 16 deletions src/algorithms/pss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@
//! [RFC8017 § 8.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.1

use alloc::vec::Vec;
use digest::{Digest, DynDigest, FixedOutputReset};
use digest::{Digest, FixedOutputReset};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};

use super::mgf::{mgf1_xor, mgf1_xor_digest};
use crate::errors::{Error, Result};

pub(crate) fn emsa_pss_encode(
pub(crate) fn emsa_pss_encode<D>(
m_hash: &[u8],
em_bits: usize,
salt: &[u8],
hash: &mut dyn DynDigest,
) -> Result<Vec<u8>> {
hash: &mut D,
) -> Result<Vec<u8>>
where
D: Digest + FixedOutputReset,
{
// See [1], section 9.1.1
let h_len = hash.output_size();
let h_len = <D as Digest>::output_size();
let s_len = salt.len();
let em_len = em_bits.div_ceil(8);

Expand Down Expand Up @@ -59,9 +62,9 @@ pub(crate) fn emsa_pss_encode(
// 6. Let H = Hash(M'), an octet string of length h_len.
let prefix = [0u8; 8];

hash.update(&prefix);
hash.update(m_hash);
hash.update(salt);
Digest::update(hash, prefix);
Digest::update(hash, m_hash);
Digest::update(hash, salt);

let hashed = hash.finalize_reset();
h.copy_from_slice(&hashed);
Expand Down Expand Up @@ -267,17 +270,20 @@ fn emsa_pss_get_salt_len(db: &[u8], em_len: usize, h_len: usize) -> (usize, Choi
(result_len as usize, final_valid)
}

pub(crate) fn emsa_pss_verify(
pub(crate) fn emsa_pss_verify<D>(
m_hash: &[u8],
em: &mut [u8],
s_len: Option<usize>,
hash: &mut dyn DynDigest,
hash: &mut D,
key_bits: usize,
) -> Result<()> {
) -> Result<()>
where
D: Digest + FixedOutputReset,
{
let em_bits = key_bits - 1;
let em_len = em_bits.div_ceil(8);
let key_len = key_bits.div_ceil(8);
let h_len = hash.output_size();
let h_len = <D as Digest>::output_size();

let em = &mut em[key_len - em_len..];

Expand Down Expand Up @@ -308,13 +314,13 @@ pub(crate) fn emsa_pss_verify(
// 13. Let H' = Hash(M'), an octet string of length hLen.
let prefix = [0u8; 8];

hash.update(&prefix[..]);
hash.update(m_hash);
hash.update(salt);
Digest::update(hash, &prefix[..]);
Digest::update(hash, m_hash);
Digest::update(hash, salt);
let h0 = hash.finalize_reset();

// 14. If H = H', output "consistent." Otherwise, output "inconsistent."
if (salt_valid & h0.ct_eq(h)).into() {
if (salt_valid & h0.as_slice().ct_eq(h)).into() {
Ok(())
} else {
Err(Error::Verification)
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
//!
//! // Encrypt
//! let data = b"hello world";
//! let padding = Oaep::new::<Sha256>();
//! let padding = Oaep::<Sha256>::new();
//! let enc_data = public_key.encrypt(&mut rng, padding, &data[..]).expect("failed to encrypt");
//! assert_ne!(&data[..], &enc_data[..]);
//!
//! // Decrypt
//! let padding = Oaep::new::<Sha256>();
//! let padding = Oaep::<Sha256>::new();
//! let dec_data = private_key.decrypt(padding, &enc_data).expect("failed to decrypt");
//! assert_eq!(&data[..], &dec_data[..]);
//! ```
Expand Down
Loading