Skip to content

Commit

Permalink
convert internals to TryCryptoRng
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo committed Feb 20, 2025
1 parent ce1e7eb commit dd554ca
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 53 deletions.
7 changes: 3 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ debug = true
[patch.crates-io]
# https://github.com/RustCrypto/crypto-bigint/pull/762
# https://github.com/RustCrypto/crypto-bigint/pull/765
crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint.git" }
# https://github.com/RustCrypto/crypto-bigint/pull/770
crypto-bigint = { git = "https://github.com/baloo/crypto-bigint.git", branch = "baloo/try_random_mod" }

# https://github.com/entropyxyz/crypto-primes/pull/74
crypto-primes = { git = "https://github.com/entropyxyz/crypto-primes.git" }

# https://github.com/rust-random/rand/pull/1593
rand_core = { git = "https://github.com/fjarri/rand.git", branch = "sized" }
10 changes: 5 additions & 5 deletions src/algorithms/oaep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use alloc::boxed::Box;
use alloc::vec::Vec;

use digest::{Digest, DynDigest, FixedOutputReset};
use rand_core::CryptoRng;
use rand_core::TryCryptoRng;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use zeroize::Zeroizing;

Expand All @@ -19,7 +19,7 @@ use crate::errors::{Error, Result};
const MAX_LABEL_LEN: u64 = 1 << 61;

#[inline]
fn encrypt_internal<R: CryptoRng + ?Sized, MGF: FnMut(&mut [u8], &mut [u8])>(
fn encrypt_internal<R: TryCryptoRng + ?Sized, MGF: FnMut(&mut [u8], &mut [u8])>(
rng: &mut R,
msg: &[u8],
p_hash: &[u8],
Expand All @@ -35,7 +35,7 @@ fn encrypt_internal<R: CryptoRng + ?Sized, MGF: FnMut(&mut [u8], &mut [u8])>(

let (_, payload) = em.split_at_mut(1);
let (seed, db) = payload.split_at_mut(h_size);
rng.fill_bytes(seed);
rng.try_fill_bytes(seed).map_err(|_| Error::Rng)?;

// Data block DB = pHash || PS || 01 || M
let db_len = k - h_size - 1;
Expand All @@ -57,7 +57,7 @@ fn encrypt_internal<R: CryptoRng + ?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: CryptoRng + ?Sized>(
pub(crate) fn oaep_encrypt<R: TryCryptoRng + ?Sized>(
rng: &mut R,
msg: &[u8],
digest: &mut dyn DynDigest,
Expand Down Expand Up @@ -90,7 +90,7 @@ pub(crate) fn oaep_encrypt<R: CryptoRng + ?Sized>(
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
pub(crate) fn oaep_encrypt_digest<
R: CryptoRng + ?Sized,
R: TryCryptoRng + ?Sized,
D: Digest,
MGD: Digest + FixedOutputReset,
>(
Expand Down
19 changes: 12 additions & 7 deletions src/algorithms/pkcs1v15.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use alloc::vec::Vec;
use digest::Digest;
use pkcs8::AssociatedOid;
use rand_core::CryptoRng;
use rand_core::TryCryptoRng;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
use zeroize::Zeroizing;

Expand All @@ -18,17 +18,22 @@ use crate::errors::{Error, Result};
/// Fills the provided slice with random values, which are guaranteed
/// to not be zero.
#[inline]
fn non_zero_random_bytes<R: CryptoRng + ?Sized>(rng: &mut R, data: &mut [u8]) {
rng.fill_bytes(data);
fn non_zero_random_bytes<R: TryCryptoRng + ?Sized>(
rng: &mut R,
data: &mut [u8],
) -> core::result::Result<(), R::Error> {
rng.try_fill_bytes(data)?;

for el in data {
if *el == 0u8 {
// TODO: break after a certain amount of time
while *el == 0u8 {
rng.fill_bytes(core::slice::from_mut(el));
rng.try_fill_bytes(core::slice::from_mut(el))?;
}
}
}

Ok(())
}

/// Applied the padding scheme from PKCS#1 v1.5 for encryption. The message must be no longer than
Expand All @@ -39,7 +44,7 @@ pub(crate) fn pkcs1v15_encrypt_pad<R>(
k: usize,
) -> Result<Zeroizing<Vec<u8>>>
where
R: CryptoRng + ?Sized,
R: TryCryptoRng + ?Sized,
{
if msg.len() + 11 > k {
return Err(Error::MessageTooLong);
Expand All @@ -48,7 +53,7 @@ where
// EM = 0x00 || 0x02 || PS || 0x00 || M
let mut em = Zeroizing::new(vec![0u8; k]);
em[1] = 2;
non_zero_random_bytes(rng, &mut em[2..k - msg.len() - 1]);
non_zero_random_bytes(rng, &mut em[2..k - msg.len() - 1]).map_err(|_: R::Error| Error::Rng)?;
em[k - msg.len() - 1] = 0;
em[k - msg.len()..].copy_from_slice(msg);
Ok(em)
Expand Down Expand Up @@ -189,7 +194,7 @@ mod tests {
for _ in 0..10 {
let mut rng = ChaCha8Rng::from_seed([42; 32]);
let mut b = vec![0u8; 512];
non_zero_random_bytes(&mut rng, &mut b);
non_zero_random_bytes(&mut rng, &mut b).unwrap();
for el in &b {
assert_ne!(*el, 0u8);
}
Expand Down
20 changes: 10 additions & 10 deletions src/algorithms/rsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::cmp::Ordering;

use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams};
use crypto_bigint::{BoxedUint, Gcd, NonZero, Odd, RandomMod, Wrapping};
use rand_core::CryptoRng;
use rand_core::TryCryptoRng;
use zeroize::Zeroize;

use crate::errors::{Error, Result};
Expand All @@ -31,8 +31,8 @@ pub fn rsa_encrypt<K: PublicKeyParts>(key: &K, m: &BoxedUint) -> Result<BoxedUin
/// Use this function with great care! Raw RSA should never be used without an appropriate padding
/// or signature scheme. See the [module-level documentation][crate::hazmat] for more information.
#[inline]
pub fn rsa_decrypt<R: CryptoRng + ?Sized>(
mut rng: Option<&mut R>,
pub fn rsa_decrypt<R: TryCryptoRng + ?Sized>(
rng: Option<&mut R>,
priv_key: &impl PrivateKeyParts,
c: &BoxedUint,
) -> Result<BoxedUint> {
Expand All @@ -48,8 +48,8 @@ pub fn rsa_decrypt<R: CryptoRng + ?Sized>(
let n_params = priv_key.n_params();
let bits = d.bits_precision();

let c = if let Some(ref mut rng) = rng {
let (blinded, unblinder) = blind(rng, priv_key, c, n_params);
let c = if let Some(rng) = rng {
let (blinded, unblinder) = blind(rng, priv_key, c, n_params)?;
ir = Some(unblinder);
blinded.widen(bits)
} else {
Expand Down Expand Up @@ -123,7 +123,7 @@ pub fn rsa_decrypt<R: CryptoRng + ?Sized>(
/// Use this function with great care! Raw RSA should never be used without an appropriate padding
/// or signature scheme. See the [module-level documentation][crate::hazmat] for more information.
#[inline]
pub fn rsa_decrypt_and_check<R: CryptoRng + ?Sized>(
pub fn rsa_decrypt_and_check<R: TryCryptoRng + ?Sized>(
priv_key: &impl PrivateKeyParts,
rng: Option<&mut R>,
c: &BoxedUint,
Expand All @@ -142,12 +142,12 @@ pub fn rsa_decrypt_and_check<R: CryptoRng + ?Sized>(
}

/// Returns the blinded c, along with the unblinding factor.
fn blind<R: CryptoRng, K: PublicKeyParts>(
fn blind<R: TryCryptoRng + ?Sized, K: PublicKeyParts>(
rng: &mut R,
key: &K,
c: &BoxedUint,
n_params: &BoxedMontyParams,
) -> (BoxedUint, BoxedUint) {
) -> Result<(BoxedUint, BoxedUint)> {
// Blinding involves multiplying c by r^e.
// Then the decryption operation performs (m^e * r^e)^d mod n
// which equals mr mod n. The factor of r can then be removed
Expand All @@ -158,7 +158,7 @@ fn blind<R: CryptoRng, K: PublicKeyParts>(
let mut r: BoxedUint = BoxedUint::one_with_precision(bits);
let mut ir: Option<BoxedUint> = None;
while ir.is_none() {
r = BoxedUint::random_mod(rng, key.n());
r = BoxedUint::try_random_mod(rng, key.n()).map_err(|_| Error::Rng)?;
if r.is_zero().into() {
r = BoxedUint::one_with_precision(bits);
}
Expand All @@ -181,7 +181,7 @@ fn blind<R: CryptoRng, K: PublicKeyParts>(
debug_assert_eq!(blinded.bits_precision(), bits);
debug_assert_eq!(ir.bits_precision(), bits);

(blinded, ir)
Ok((blinded, ir))
}

/// Given an m and and unblinding factor, unblind the m.
Expand Down
4 changes: 4 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ pub enum Error {

/// Decoding error.
Decode(crypto_bigint::DecodeError),

/// Random number generator error.
Rng,
}

#[cfg(feature = "std")]
Expand Down Expand Up @@ -99,6 +102,7 @@ impl core::fmt::Display for Error {
Error::InvalidPadLen => write!(f, "invalid padding length"),
Error::InvalidArguments => write!(f, "invalid arguments"),
Error::Decode(err) => write!(f, "{:?}", err),
Error::Rng => write!(f, "rng error"),
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/oaep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use core::fmt;
use crypto_bigint::BoxedUint;

use digest::{Digest, DynDigest, FixedOutputReset};
use rand_core::CryptoRng;
use rand_core::TryCryptoRng;

use crate::algorithms::oaep::*;
use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad};
Expand Down Expand Up @@ -135,7 +135,7 @@ impl Oaep {
}

impl PaddingScheme for Oaep {
fn decrypt<Rng: CryptoRng>(
fn decrypt<Rng: TryCryptoRng>(
mut self,
rng: Option<&mut Rng>,
priv_key: &RsaPrivateKey,
Expand All @@ -151,7 +151,7 @@ impl PaddingScheme for Oaep {
)
}

fn encrypt<Rng: CryptoRng>(
fn encrypt<Rng: TryCryptoRng>(
mut self,
rng: &mut Rng,
pub_key: &RsaPublicKey,
Expand Down Expand Up @@ -186,7 +186,7 @@ impl fmt::Debug for Oaep {
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
fn encrypt<R: CryptoRng + ?Sized>(
fn encrypt<R: TryCryptoRng + ?Sized>(
rng: &mut R,
pub_key: &RsaPublicKey,
msg: &[u8],
Expand All @@ -209,7 +209,7 @@ fn encrypt<R: CryptoRng + ?Sized>(
/// `2 + (2 * hash.size())`.
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
fn encrypt_digest<R: CryptoRng + ?Sized, D: Digest, MGD: Digest + FixedOutputReset>(
fn encrypt_digest<R: TryCryptoRng + ?Sized, D: Digest, MGD: Digest + FixedOutputReset>(
rng: &mut R,
pub_key: &RsaPublicKey,
msg: &[u8],
Expand All @@ -236,7 +236,7 @@ fn encrypt_digest<R: CryptoRng + ?Sized, D: Digest, MGD: Digest + FixedOutputRes
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
fn decrypt<R: CryptoRng + ?Sized>(
fn decrypt<R: TryCryptoRng + ?Sized>(
rng: Option<&mut R>,
priv_key: &RsaPrivateKey,
ciphertext: &[u8],
Expand Down Expand Up @@ -269,7 +269,7 @@ fn decrypt<R: CryptoRng + ?Sized>(
///
/// [PKCS#1 OAEP]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1
#[inline]
fn decrypt_digest<R: CryptoRng + ?Sized, D: Digest, MGD: Digest + FixedOutputReset>(
fn decrypt_digest<R: TryCryptoRng + ?Sized, D: Digest, MGD: Digest + FixedOutputReset>(
rng: Option<&mut R>,
priv_key: &RsaPrivateKey,
ciphertext: &[u8],
Expand Down
14 changes: 7 additions & 7 deletions src/pkcs1v15.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use core::fmt::Debug;
use crypto_bigint::BoxedUint;
use digest::Digest;
use pkcs8::AssociatedOid;
use rand_core::CryptoRng;
use rand_core::TryCryptoRng;

use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad};
use crate::algorithms::pkcs1v15::*;
Expand All @@ -36,7 +36,7 @@ use crate::traits::{PaddingScheme, PublicKeyParts, SignatureScheme};
pub struct Pkcs1v15Encrypt;

impl PaddingScheme for Pkcs1v15Encrypt {
fn decrypt<Rng: CryptoRng>(
fn decrypt<Rng: TryCryptoRng>(
self,
rng: Option<&mut Rng>,
priv_key: &RsaPrivateKey,
Expand All @@ -45,7 +45,7 @@ impl PaddingScheme for Pkcs1v15Encrypt {
decrypt(rng, priv_key, ciphertext)
}

fn encrypt<Rng: CryptoRng>(
fn encrypt<Rng: TryCryptoRng>(
self,
rng: &mut Rng,
pub_key: &RsaPublicKey,
Expand Down Expand Up @@ -100,7 +100,7 @@ impl Pkcs1v15Sign {
}

impl SignatureScheme for Pkcs1v15Sign {
fn sign<Rng: CryptoRng>(
fn sign<Rng: TryCryptoRng>(
self,
rng: Option<&mut Rng>,
priv_key: &RsaPrivateKey,
Expand Down Expand Up @@ -135,7 +135,7 @@ impl SignatureScheme for Pkcs1v15Sign {
/// scheme from PKCS#1 v1.5. The message must be no longer than the
/// length of the public modulus minus 11 bytes.
#[inline]
fn encrypt<R: CryptoRng + ?Sized>(
fn encrypt<R: TryCryptoRng + ?Sized>(
rng: &mut R,
pub_key: &RsaPublicKey,
msg: &[u8],
Expand All @@ -157,7 +157,7 @@ fn encrypt<R: CryptoRng + ?Sized>(
/// forge signatures as if they had the private key. See
/// `decrypt_session_key` for a way of solving this problem.
#[inline]
fn decrypt<R: CryptoRng + ?Sized>(
fn decrypt<R: TryCryptoRng + ?Sized>(
rng: Option<&mut R>,
priv_key: &RsaPrivateKey,
ciphertext: &[u8],
Expand Down Expand Up @@ -185,7 +185,7 @@ fn decrypt<R: CryptoRng + ?Sized>(
/// messages to signatures and identify the signed messages. As ever,
/// signatures provide authenticity, not confidentiality.
#[inline]
fn sign<R: CryptoRng + ?Sized>(
fn sign<R: TryCryptoRng + ?Sized>(
rng: Option<&mut R>,
priv_key: &RsaPrivateKey,
prefix: &[u8],
Expand Down
Loading

0 comments on commit dd554ca

Please sign in to comment.