Skip to content

Commit

Permalink
convert more internal use to crypto-bigint
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire committed Dec 1, 2023
1 parent 97f8fa4 commit cc3f03b
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 60 deletions.
11 changes: 9 additions & 2 deletions src/algorithms/pad.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Special handling for converting the BigUint to u8 vectors

use alloc::vec::Vec;
use crypto_bigint::BoxedUint;
use num_bigint::BigUint;
use zeroize::Zeroizing;

Expand All @@ -26,9 +27,15 @@ pub(crate) fn uint_to_be_pad(input: BigUint, padded_len: usize) -> Result<Vec<u8

/// Converts input to the new vector of the given length, using BE and with 0s left padded.
#[inline]
pub(crate) fn uint_to_zeroizing_be_pad(input: BigUint, padded_len: usize) -> Result<Vec<u8>> {
pub(crate) fn uint_to_be_pad_new(input: BoxedUint, padded_len: usize) -> Result<Vec<u8>> {
left_pad(&input.to_be_bytes(), padded_len)
}

/// Converts input to the new vector of the given length, using BE and with 0s left padded.
#[inline]
pub(crate) fn uint_to_zeroizing_be_pad_new(input: BoxedUint, padded_len: usize) -> Result<Vec<u8>> {
let m = Zeroizing::new(input);
let m = Zeroizing::new(m.to_bytes_be());
let m = Zeroizing::new(m.to_be_bytes());
left_pad(&m, padded_len)
}

Expand Down
19 changes: 9 additions & 10 deletions src/algorithms/rsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rand_core::CryptoRngCore;
use zeroize::{Zeroize, Zeroizing};

use crate::errors::{Error, Result};
use crate::key::{reduce, to_biguint, to_uint_exact};
use crate::key::reduce;
use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew};

/// ⚠️ Raw RSA encryption of m with the public key. No padding is performed.
Expand All @@ -20,10 +20,9 @@ use crate::traits::keys::{PrivateKeyPartsNew, PublicKeyPartsNew};
/// 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_encrypt<K: PublicKeyPartsNew>(key: &K, m: &BigUint) -> Result<BigUint> {
let m = to_uint_exact(m.clone(), key.n().bits_precision()); // TODO: change input
let res = pow_mod_params(&m, key.e(), key.n_params());
Ok(to_biguint(&res))
pub fn rsa_encrypt<K: PublicKeyPartsNew>(key: &K, m: &BoxedUint) -> Result<BoxedUint> {
let res = pow_mod_params(m, key.e(), key.n_params());
Ok(res)
}

/// ⚠️ Performs raw RSA decryption with no padding or error checking.
Expand All @@ -39,7 +38,7 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
mut rng: Option<&mut R>,
priv_key: &impl PrivateKeyPartsNew,
c: &BoxedUint,
) -> Result<BigUint> {
) -> Result<BoxedUint> {
let n = priv_key.n();
let d = priv_key.d();

Expand Down Expand Up @@ -103,10 +102,10 @@ pub fn rsa_decrypt<R: CryptoRngCore + ?Sized>(
match ir {
Some(ref ir) => {
// unblind
let res = to_biguint(&unblind(&m, ir, n_params));
let res = unblind(&m, ir, n_params);
Ok(res)
}
None => Ok(to_biguint(&m)),
None => Ok(m),
}
}

Expand All @@ -124,14 +123,14 @@ pub fn rsa_decrypt_and_check<R: CryptoRngCore + ?Sized>(
priv_key: &impl PrivateKeyPartsNew,
rng: Option<&mut R>,
c: &BoxedUint,
) -> Result<BigUint> {
) -> Result<BoxedUint> {
let m = rsa_decrypt(rng, priv_key, c)?;

// In order to defend against errors in the CRT computation, m^e is
// calculated, which should match the original ciphertext.
let check = rsa_encrypt(priv_key, &m)?;

if to_biguint(c) != check {
if c != &check {
return Err(Error::Internal);
}

Expand Down
9 changes: 9 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub enum Error {

/// Invalid arguments.
InvalidArguments,

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

#[cfg(feature = "std")]
Expand Down Expand Up @@ -95,6 +98,7 @@ impl core::fmt::Display for Error {
Error::LabelTooLong => write!(f, "label too long"),
Error::InvalidPadLen => write!(f, "invalid padding length"),
Error::InvalidArguments => write!(f, "invalid arguments"),
Error::Decode(err) => write!(f, "{:?}", err),
}
}
}
Expand All @@ -110,6 +114,11 @@ impl From<pkcs8::Error> for Error {
Error::Pkcs8(err)
}
}
impl From<crypto_bigint::DecodeError> for Error {
fn from(err: crypto_bigint::DecodeError) -> Error {
Error::Decode(err)
}
}

#[cfg(feature = "std")]
impl From<Error> for signature::Error {
Expand Down
3 changes: 1 addition & 2 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,9 +686,8 @@ mod tests {
);

let pub_key: RsaPublicKey = private_key.clone().into();
let m = BigUint::from_u64(42).expect("invalid 42");
let m = BoxedUint::from(42u64);
let c = rsa_encrypt(&pub_key, &m).expect("encryption successfull");
let c = to_uint_exact(c, PublicKeyPartsNew::n(&pub_key).bits_precision());

let m2 = rsa_decrypt_and_check::<ChaCha8Rng>(private_key, None, &c)
.expect("unable to decrypt without blinding");
Expand Down
42 changes: 24 additions & 18 deletions src/oaep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@ use alloc::boxed::Box;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::fmt;
use crypto_bigint::BoxedUint;

use digest::{Digest, DynDigest, FixedOutputReset};
use num_bigint::BigUint;
use rand_core::CryptoRngCore;
use zeroize::Zeroizing;

use crate::algorithms::oaep::*;
use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad};
use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new};
use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
use crate::errors::{Error, Result};
use crate::key::{self, to_uint_exact, RsaPrivateKey, RsaPublicKey};
use crate::key::{self, RsaPrivateKey, RsaPublicKey};
use crate::traits::{PaddingScheme, PublicKeyParts};

/// Encryption and Decryption using [OAEP padding](https://datatracker.ietf.org/doc/html/rfc8017#section-7.1).
Expand Down Expand Up @@ -194,8 +193,11 @@ fn encrypt<R: CryptoRngCore + ?Sized>(

let em = oaep_encrypt(rng, msg, digest, mgf_digest, label, pub_key.size())?;

let int = Zeroizing::new(BigUint::from_bytes_be(&em));
uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size())
let int = BoxedUint::from_be_slice(
&em,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key),
)?;
uint_to_be_pad_new(rsa_encrypt(pub_key, &int)?, pub_key.size())
}

/// Encrypts the given message with RSA and the padding scheme from
Expand All @@ -215,8 +217,11 @@ fn encrypt_digest<R: CryptoRngCore + ?Sized, D: Digest, MGD: Digest + FixedOutpu

let em = oaep_encrypt_digest::<_, D, MGD>(rng, msg, label, pub_key.size())?;

let int = Zeroizing::new(BigUint::from_bytes_be(&em));
uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size())
let int = BoxedUint::from_be_slice(
&em,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key),
)?;
uint_to_be_pad_new(rsa_encrypt(pub_key, &int)?, pub_key.size())
}

/// Decrypts a plaintext using RSA and the padding scheme from [PKCS#1 OAEP].
Expand Down Expand Up @@ -246,12 +251,13 @@ fn decrypt<R: CryptoRngCore + ?Sized>(
return Err(Error::Decryption);
}

let ciphertext = to_uint_exact(
BigUint::from_bytes_be(ciphertext),
crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(),
);
let ciphertext = BoxedUint::from_be_slice(
ciphertext,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key),
)?;

let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?;
let mut em = uint_to_zeroizing_be_pad(em, priv_key.size())?;
let mut em = uint_to_zeroizing_be_pad_new(em, priv_key.size())?;

oaep_decrypt(&mut em, digest, mgf_digest, label, priv_key.size())
}
Expand Down Expand Up @@ -281,12 +287,12 @@ fn decrypt_digest<R: CryptoRngCore + ?Sized, D: Digest, MGD: Digest + FixedOutpu
return Err(Error::Decryption);
}

let ciphertext = to_uint_exact(
BigUint::from_bytes_be(ciphertext),
crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(),
);
let ciphertext = BoxedUint::from_be_slice(
ciphertext,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key),
)?;
let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?;
let mut em = uint_to_zeroizing_be_pad(em, priv_key.size())?;
let mut em = uint_to_zeroizing_be_pad_new(em, priv_key.size())?;

oaep_decrypt_digest::<D, MGD>(&mut em, label, priv_key.size())
}
Expand Down
37 changes: 22 additions & 15 deletions src/pkcs1v15.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ pub use self::{

use alloc::{boxed::Box, vec::Vec};
use core::fmt::Debug;
use crypto_bigint::BoxedUint;
use digest::Digest;
use num_bigint::BigUint;
use pkcs8::AssociatedOid;
use rand_core::CryptoRngCore;
use zeroize::Zeroizing;

use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad};
use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new};
use crate::algorithms::pkcs1v15::*;
use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
use crate::errors::{Error, Result};
Expand Down Expand Up @@ -145,8 +145,11 @@ fn encrypt<R: CryptoRngCore + ?Sized>(
key::check_public(pub_key)?;

let em = pkcs1v15_encrypt_pad(rng, msg, pub_key.size())?;
let int = Zeroizing::new(BigUint::from_bytes_be(&em));
uint_to_be_pad(rsa_encrypt(pub_key, &int)?, pub_key.size())
let int = BoxedUint::from_be_slice(
&em,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key),
)?;
uint_to_be_pad_new(rsa_encrypt(pub_key, &int)?, pub_key.size())
}

/// Decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
Expand All @@ -166,12 +169,12 @@ fn decrypt<R: CryptoRngCore + ?Sized>(
) -> Result<Vec<u8>> {
key::check_public(priv_key)?;

let ciphertext = to_uint_exact(
BigUint::from_bytes_be(ciphertext),
crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(),
);
let ciphertext = BoxedUint::from_be_slice(
ciphertext,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key),
)?;
let em = rsa_decrypt_and_check(priv_key, rng, &ciphertext)?;
let em = uint_to_zeroizing_be_pad(em, priv_key.size())?;
let em = uint_to_zeroizing_be_pad_new(em, priv_key.size())?;

pkcs1v15_encrypt_unpad(em, priv_key.size())
}
Expand All @@ -198,11 +201,11 @@ fn sign<R: CryptoRngCore + ?Sized>(
) -> Result<Vec<u8>> {
let em = pkcs1v15_sign_pad(prefix, hashed, priv_key.size())?;

let em = to_uint_exact(
BigUint::from_bytes_be(&em),
crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(),
);
uint_to_zeroizing_be_pad(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size())
let em = BoxedUint::from_be_slice(
&em,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key),
)?;
uint_to_zeroizing_be_pad_new(rsa_decrypt_and_check(priv_key, rng, &em)?, priv_key.size())
}

/// Verifies an RSA PKCS#1 v1.5 signature.
Expand All @@ -218,7 +221,11 @@ fn verify(
return Err(Error::Verification);
}

let em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?;
let sig = to_uint_exact(
sig.clone(),
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key),
);
let em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?;

pkcs1v15_sign_unpad(prefix, hashed, &em, pub_key.size())
}
Expand Down
35 changes: 22 additions & 13 deletions src/pss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use self::{

use alloc::{boxed::Box, vec::Vec};
use core::fmt::{self, Debug};
use crypto_bigint::BoxedUint;

use const_oid::{AssociatedOid, ObjectIdentifier};
use digest::{Digest, DynDigest, FixedOutputReset};
Expand All @@ -29,7 +30,7 @@ use pkcs1::RsaPssParams;
use pkcs8::spki::{der::Any, AlgorithmIdentifierOwned};
use rand_core::CryptoRngCore;

use crate::algorithms::pad::{uint_to_be_pad, uint_to_zeroizing_be_pad};
use crate::algorithms::pad::{uint_to_be_pad_new, uint_to_zeroizing_be_pad_new};
use crate::algorithms::pss::*;
use crate::algorithms::rsa::{rsa_decrypt_and_check, rsa_encrypt};
use crate::errors::{Error, Result};
Expand Down Expand Up @@ -136,7 +137,11 @@ pub(crate) fn verify(
return Err(Error::Verification);
}

let mut em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?;
let sig = to_uint_exact(
sig.clone(),
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key),
);
let mut em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?;

emsa_pss_verify(hashed, &mut em, salt_len, digest, pub_key.n().bits())
}
Expand All @@ -155,7 +160,11 @@ where
return Err(Error::Verification);
}

let mut em = uint_to_be_pad(rsa_encrypt(pub_key, sig)?, pub_key.size())?;
let sig = to_uint_exact(
sig.clone(),
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(pub_key),
);
let mut em = uint_to_be_pad_new(rsa_encrypt(pub_key, &sig)?, pub_key.size())?;

emsa_pss_verify_digest::<D>(hashed, &mut em, salt_len, pub_key.n().bits())
}
Expand Down Expand Up @@ -207,11 +216,11 @@ fn sign_pss_with_salt<T: CryptoRngCore>(
let em_bits = priv_key.n().bits() - 1;
let em = emsa_pss_encode(hashed, em_bits, salt, digest)?;

let em = to_uint_exact(
BigUint::from_bytes_be(&em),
crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(),
);
uint_to_zeroizing_be_pad(
let em = BoxedUint::from_be_slice(
&em,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key),
)?;
uint_to_zeroizing_be_pad_new(
rsa_decrypt_and_check(priv_key, blind_rng, &em)?,
priv_key.size(),
)
Expand All @@ -226,11 +235,11 @@ fn sign_pss_with_salt_digest<T: CryptoRngCore + ?Sized, D: Digest + FixedOutputR
let em_bits = priv_key.n().bits() - 1;
let em = emsa_pss_encode_digest::<D>(hashed, em_bits, salt)?;

let em = to_uint_exact(
BigUint::from_bytes_be(&em),
crate::traits::keys::PublicKeyPartsNew::n(priv_key).bits_precision(),
);
uint_to_zeroizing_be_pad(
let em = BoxedUint::from_be_slice(
&em,
crate::traits::keys::PublicKeyPartsNew::n_bits_precision(priv_key),
)?;
uint_to_zeroizing_be_pad_new(
rsa_decrypt_and_check(priv_key, blind_rng, &em)?,
priv_key.size(),
)
Expand Down
4 changes: 4 additions & 0 deletions src/traits/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ pub trait PublicKeyPartsNew {

fn n_params(&self) -> BoxedResidueParams;

fn n_bits_precision(&self) -> usize {
self.n().bits_precision()
}

/// Returns the modulus size in bytes. Raw signatures and ciphertexts for
/// or by this public key will have the same size.
fn size(&self) -> usize {
Expand Down

0 comments on commit cc3f03b

Please sign in to comment.