Reformat src/rsa.

This commit is contained in:
Brian Smith 2018-11-15 15:37:51 -10:00
parent 0a9cd4dcd2
commit 730a46f665
5 changed files with 560 additions and 473 deletions

View File

@ -40,11 +40,13 @@
#![allow(box_pointers)]
use crate::{bits, bssl, c, error, limb, untrusted};
use arithmetic::montgomery::*;
use core;
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use core::{
self,
marker::PhantomData,
ops::{Deref, DerefMut},
};
use crate::{bits, bssl, c, error, limb, untrusted};
use std;
#[cfg(any(test, feature = "rsa_signing"))]
@ -70,16 +72,12 @@ struct BoxedLimbs<M> {
impl<M> Deref for BoxedLimbs<M> {
type Target = [limb::Limb];
#[inline]
fn deref(&self) -> &Self::Target {
&self.limbs
}
fn deref(&self) -> &Self::Target { &self.limbs }
}
impl<M> DerefMut for BoxedLimbs<M> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.limbs
}
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.limbs }
}
// TODO: `derive(Clone)` after https://github.com/rust-lang/rust/issues/26925
@ -94,15 +92,19 @@ impl<M> Clone for BoxedLimbs<M> {
}
impl<M> BoxedLimbs<M> {
fn positive_minimal_width_from_be_bytes(input: untrusted::Input)
-> Result<Self, error::Unspecified> {
fn positive_minimal_width_from_be_bytes(
input: untrusted::Input,
) -> Result<Self, error::Unspecified> {
// Reject leading zeros. Also reject the value zero ([0]) because zero
// isn't positive.
if untrusted::Reader::new(input).peek(0) {
return Err(error::Unspecified);
}
let num_limbs = (input.len() + limb::LIMB_BYTES - 1) / limb::LIMB_BYTES;
let mut r = Self::zero(Width { num_limbs, m: PhantomData });
let mut r = Self::zero(Width {
num_limbs,
m: PhantomData,
});
limb::parse_big_endian_and_pad_consttime(input, &mut r)?;
Ok(r)
}
@ -117,12 +119,12 @@ impl<M> BoxedLimbs<M> {
}
}
fn from_be_bytes_padded_less_than(input: untrusted::Input, m: &Modulus<M>)
-> Result<Self, error::Unspecified> {
fn from_be_bytes_padded_less_than(
input: untrusted::Input, m: &Modulus<M>,
) -> Result<Self, error::Unspecified> {
let mut r = Self::zero(m.width());
limb::parse_big_endian_and_pad_consttime(input, &mut r)?;
if limb::limbs_less_than_limbs_consttime(&r, &m.limbs) !=
limb::LimbMask::True {
if limb::limbs_less_than_limbs_consttime(&r, &m.limbs) != limb::LimbMask::True {
return Err(error::Unspecified);
}
Ok(r)
@ -213,8 +215,7 @@ pub struct Modulus<M> {
}
impl core::fmt::Debug for Modulus<super::N> {
fn fmt(&self, fmt: &mut ::core::fmt::Formatter)
-> Result<(), ::core::fmt::Error> {
fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> {
fmt.debug_struct("Modulus")
// TODO: Print modulus value.
.finish()
@ -222,9 +223,9 @@ impl core::fmt::Debug for Modulus<super::N> {
}
impl<M> Modulus<M> {
pub fn from_be_bytes_with_bit_length(input: untrusted::Input)
-> Result<(Self, bits::BitLength), error::Unspecified>
{
pub fn from_be_bytes_with_bit_length(
input: untrusted::Input,
) -> Result<(Self, bits::BitLength), error::Unspecified> {
let limbs = BoxedLimbs::positive_minimal_width_from_be_bytes(input)?;
let bits = minimal_limbs_bit_length(&limbs);
Ok((Self::from_boxed_limbs(limbs)?, bits))
@ -243,11 +244,9 @@ impl<M> Modulus<M> {
if n.len() > MODULUS_MAX_LIMBS {
return Err(error::Unspecified);
}
Result::from(unsafe {
GFp_bn_mul_mont_check_num_limbs(n.len())
})?;
Result::from(unsafe { GFp_bn_mul_mont_check_num_limbs(n.len()) })?;
if limb::limbs_are_even_constant_time(&n) != limb::LimbMask::False {
return Err(error::Unspecified)
return Err(error::Unspecified);
}
if limb::limbs_less_than_limb_constant_time(&n, 3) != limb::LimbMask::False {
return Err(error::Unspecified);
@ -308,7 +307,8 @@ impl<M> Modulus<M> {
#[cfg(feature = "rsa_signing")]
pub fn to_elem<L>(&self, l: &Modulus<L>) -> Elem<L, Unencoded>
where M: SmallerModulus<L>
where
M: SmallerModulus<L>,
{
// TODO: Encode this assertion into the `where` above.
assert_eq!(self.width().num_limbs, l.width().num_limbs);
@ -381,9 +381,7 @@ impl<M, E> Elem<M, E> {
}
impl<M, E: ReductionEncoding> Elem<M, E> {
fn decode_once(self, m: &Modulus<M>)
-> Elem<M, <E as ReductionEncoding>::Output>
{
fn decode_once(self, m: &Modulus<M>) -> Elem<M, <E as ReductionEncoding>::Output> {
// A multiplication isn't required since we're multiplying by the
// unencoded value one (1); only a Montgomery reduction is needed.
// However the only non-multiplication Montgomery reduction function we
@ -394,8 +392,14 @@ impl<M, E: ReductionEncoding> Elem<M, E> {
one[0] = 1;
let one = &one[..num_limbs]; // assert!(num_limbs <= MODULUS_MAX_LIMBS);
unsafe {
GFp_bn_mul_mont(limbs.as_mut_ptr(), limbs.as_ptr(),
one.as_ptr(), m.limbs.as_ptr(), &m.n0, num_limbs)
GFp_bn_mul_mont(
limbs.as_mut_ptr(),
limbs.as_ptr(),
one.as_ptr(),
m.limbs.as_ptr(),
&m.n0,
num_limbs,
)
}
Elem {
limbs,
@ -406,14 +410,13 @@ impl<M, E: ReductionEncoding> Elem<M, E> {
impl<M> Elem<M, R> {
#[inline]
pub fn into_unencoded(self, m: &Modulus<M>) -> Elem<M, Unencoded> {
self.decode_once(m)
}
pub fn into_unencoded(self, m: &Modulus<M>) -> Elem<M, Unencoded> { self.decode_once(m) }
}
impl<M> Elem<M, Unencoded> {
pub fn from_be_bytes_padded(input: untrusted::Input, m: &Modulus<M>)
-> Result<Self, error::Unspecified> {
pub fn from_be_bytes_padded(
input: untrusted::Input, m: &Modulus<M>,
) -> Result<Self, error::Unspecified> {
Ok(Elem {
limbs: BoxedLimbs::from_be_bytes_padded_less_than(input, m)?,
encoding: PhantomData,
@ -433,25 +436,34 @@ impl<M> Elem<M, Unencoded> {
#[cfg(feature = "rsa_signing")]
fn is_one(&self) -> bool {
limb::limbs_equal_limb_constant_time(&self.limbs, 1) ==
limb::LimbMask::True
limb::limbs_equal_limb_constant_time(&self.limbs, 1) == limb::LimbMask::True
}
}
pub fn elem_mul<M, AF, BF>(a: &Elem<M, AF>, b: Elem<M, BF>, m: &Modulus<M>)
-> Elem<M, <(AF, BF) as ProductEncoding>::Output>
where (AF, BF): ProductEncoding
pub fn elem_mul<M, AF, BF>(
a: &Elem<M, AF>, b: Elem<M, BF>, m: &Modulus<M>,
) -> Elem<M, <(AF, BF) as ProductEncoding>::Output>
where
(AF, BF): ProductEncoding,
{
elem_mul_(a, b, &m.as_partial())
}
fn elem_mul_<M, AF, BF>(a: &Elem<M, AF>, mut b: Elem<M, BF>, m: &PartialModulus<M>)
-> Elem<M, <(AF, BF) as ProductEncoding>::Output>
where (AF, BF): ProductEncoding {
fn elem_mul_<M, AF, BF>(
a: &Elem<M, AF>, mut b: Elem<M, BF>, m: &PartialModulus<M>,
) -> Elem<M, <(AF, BF) as ProductEncoding>::Output>
where
(AF, BF): ProductEncoding,
{
unsafe {
GFp_bn_mul_mont(b.limbs.as_mut_ptr(), a.limbs.as_ptr(),
b.limbs.as_ptr(), m.limbs.as_ptr(), &m.n0,
m.limbs.len());
GFp_bn_mul_mont(
b.limbs.as_mut_ptr(),
a.limbs.as_ptr(),
b.limbs.as_ptr(),
m.limbs.as_ptr(),
&m.n0,
m.limbs.len(),
);
}
Elem {
limbs: b.limbs,
@ -461,15 +473,19 @@ fn elem_mul_<M, AF, BF>(a: &Elem<M, AF>, mut b: Elem<M, BF>, m: &PartialModulus<
fn elem_mul_by_2<M, AF>(a: &mut Elem<M, AF>, m: &PartialModulus<M>) {
unsafe {
LIMBS_shl_mod(a.limbs.as_mut_ptr(), a.limbs.as_ptr(),
m.limbs.as_ptr(), m.limbs.len());
LIMBS_shl_mod(
a.limbs.as_mut_ptr(),
a.limbs.as_ptr(),
m.limbs.as_ptr(),
m.limbs.len(),
);
}
}
#[cfg(feature = "rsa_signing")]
pub fn elem_reduced_once<Larger, Smaller: SlightlySmallerModulus<Larger>>(
a: &Elem<Larger, Unencoded>, m: &Modulus<Smaller>)
-> Elem<Smaller, Unencoded> {
a: &Elem<Larger, Unencoded>, m: &Modulus<Smaller>,
) -> Elem<Smaller, Unencoded> {
let mut r = a.limbs.clone();
assert!(r.len() <= m.limbs.len());
limb::limbs_reduce_once_constant_time(&mut r, &m.limbs);
@ -485,28 +501,42 @@ pub fn elem_reduced_once<Larger, Smaller: SlightlySmallerModulus<Larger>>(
#[cfg(feature = "rsa_signing")]
#[inline]
pub fn elem_reduced<Larger, Smaller: NotMuchSmallerModulus<Larger>>(
a: &Elem<Larger, Unencoded>, m: &Modulus<Smaller>)
-> Result<Elem<Smaller, RInverse>, error::Unspecified> {
a: &Elem<Larger, Unencoded>, m: &Modulus<Smaller>,
) -> Result<Elem<Smaller, RInverse>, error::Unspecified> {
let mut tmp = [0; MODULUS_MAX_LIMBS];
let tmp = &mut tmp[..a.limbs.len()];
tmp.copy_from_slice(&a.limbs);
let mut r = m.zero();
Result::from(unsafe {
GFp_bn_from_montgomery_in_place(r.limbs.as_mut_ptr(), r.limbs.len(),
tmp.as_mut_ptr(), tmp.len(),
m.limbs.as_ptr(), m.limbs.len(), &m.n0)
GFp_bn_from_montgomery_in_place(
r.limbs.as_mut_ptr(),
r.limbs.len(),
tmp.as_mut_ptr(),
tmp.len(),
m.limbs.as_ptr(),
m.limbs.len(),
&m.n0,
)
})?;
Ok(r)
}
fn elem_squared<M, E>(mut a: Elem<M, E>, m: &PartialModulus<M>)
-> Elem<M, <(E, E) as ProductEncoding>::Output>
where (E, E): ProductEncoding {
fn elem_squared<M, E>(
mut a: Elem<M, E>, m: &PartialModulus<M>,
) -> Elem<M, <(E, E) as ProductEncoding>::Output>
where
(E, E): ProductEncoding,
{
unsafe {
GFp_bn_mul_mont(a.limbs.as_mut_ptr(), a.limbs.as_ptr(),
a.limbs.as_ptr(), m.limbs.as_ptr(), &m.n0,
m.limbs.len());
GFp_bn_mul_mont(
a.limbs.as_mut_ptr(),
a.limbs.as_ptr(),
a.limbs.as_ptr(),
m.limbs.as_ptr(),
&m.n0,
m.limbs.len(),
);
};
Elem {
limbs: a.limbs,
@ -516,40 +546,43 @@ fn elem_squared<M, E>(mut a: Elem<M, E>, m: &PartialModulus<M>)
#[cfg(feature = "rsa_signing")]
pub fn elem_widen<Larger, Smaller: SmallerModulus<Larger>>(
a: Elem<Smaller, Unencoded>, m: &Modulus<Larger>)
-> Elem<Larger, Unencoded>
{
a: Elem<Smaller, Unencoded>, m: &Modulus<Larger>,
) -> Elem<Larger, Unencoded> {
let mut r = m.zero();
r.limbs[..a.limbs.len()].copy_from_slice(&a.limbs);
r
}
// TODO: Document why this works for all Montgomery factors.
#[cfg(feature = "rsa_signing")]
pub fn elem_add<M, E>(mut a: Elem<M, E>, b: Elem<M, E>, m: &Modulus<M>)
-> Elem<M, E>
{
pub fn elem_add<M, E>(mut a: Elem<M, E>, b: Elem<M, E>, m: &Modulus<M>) -> Elem<M, E> {
unsafe {
LIMBS_add_mod(a.limbs.as_mut_ptr(), a.limbs.as_ptr(),
b.limbs.as_ptr(), m.limbs.as_ptr(), m.limbs.len())
LIMBS_add_mod(
a.limbs.as_mut_ptr(),
a.limbs.as_ptr(),
b.limbs.as_ptr(),
m.limbs.as_ptr(),
m.limbs.len(),
)
}
a
}
// TODO: Document why this works for all Montgomery factors.
#[cfg(feature = "rsa_signing")]
pub fn elem_sub<M, E>(mut a: Elem<M, E>, b: &Elem<M, E>, m: &Modulus<M>)
-> Elem<M, E>
{
pub fn elem_sub<M, E>(mut a: Elem<M, E>, b: &Elem<M, E>, m: &Modulus<M>) -> Elem<M, E> {
unsafe {
LIMBS_sub_mod(a.limbs.as_mut_ptr(), a.limbs.as_ptr(), b.limbs.as_ptr(),
m.limbs.as_ptr(), m.limbs.len());
LIMBS_sub_mod(
a.limbs.as_mut_ptr(),
a.limbs.as_ptr(),
b.limbs.as_ptr(),
m.limbs.as_ptr(),
m.limbs.len(),
);
}
a
}
// The value 1, Montgomery-encoded some number of times.
pub struct One<M, E>(Elem<M, E>);
@ -613,8 +646,9 @@ impl<M, E> AsRef<Elem<M, E>> for One<M, E> {
pub struct PublicExponent(u64);
impl PublicExponent {
pub fn from_be_bytes(input: untrusted::Input, min_value: u64)
-> Result<Self, error::Unspecified> {
pub fn from_be_bytes(
input: untrusted::Input, min_value: u64,
) -> Result<Self, error::Unspecified> {
if input.len() > 5 {
return Err(error::Unspecified);
}
@ -674,16 +708,14 @@ const PUBLIC_EXPONENT_MAX_VALUE: u64 = (1u64 << 33) - 1;
// TODO: The test coverage needs to be expanded, e.g. test with the largest
// accepted exponent and with the most common values of 65537 and 3.
pub fn elem_exp_vartime<M>(
base: Elem<M, Unencoded>, PublicExponent(exponent): PublicExponent,
m: &Modulus<M>) -> Elem<M, R> {
base: Elem<M, Unencoded>, PublicExponent(exponent): PublicExponent, m: &Modulus<M>,
) -> Elem<M, R> {
let base = elem_mul(m.oneRR().as_ref(), base, &m);
elem_exp_vartime_(base, exponent, &m.as_partial())
}
/// Calculates base**exponent (mod m).
fn elem_exp_vartime_<M>(
base: Elem<M, R>, exponent: u64, m: &PartialModulus<M>) -> Elem<M, R>
{
fn elem_exp_vartime_<M>(base: Elem<M, R>, exponent: u64, m: &PartialModulus<M>) -> Elem<M, R> {
// Use what [Knuth] calls the "S-and-X binary method", i.e. variable-time
// square-and-multiply that scans the exponent from the most significant
// bit to the least significant bit (left-to-right). Left-to-right requires
@ -727,8 +759,9 @@ pub struct PrivateExponent<M> {
#[cfg(feature = "rsa_signing")]
impl<M> PrivateExponent<M> {
pub fn from_be_bytes_padded(input: untrusted::Input, p: &Modulus<M>)
-> Result<Self, error::Unspecified> {
pub fn from_be_bytes_padded(
input: untrusted::Input, p: &Modulus<M>,
) -> Result<Self, error::Unspecified> {
let dP = BoxedLimbs::from_be_bytes_padded_less_than(input, p)?;
// Proof that `dP < p - 1`:
@ -743,9 +776,7 @@ impl<M> PrivateExponent<M> {
return Err(error::Unspecified);
}
Ok(PrivateExponent {
limbs: dP,
})
Ok(PrivateExponent { limbs: dP })
}
}
@ -763,8 +794,8 @@ impl<M: Prime> PrivateExponent<M> {
#[cfg(feature = "rsa_signing")]
pub fn elem_exp_consttime<M>(
base: Elem<M, R>, exponent: &PrivateExponent<M>, m: &Modulus<M>)
-> Result<Elem<M, Unencoded>, error::Unspecified> {
base: Elem<M, R>, exponent: &PrivateExponent<M>, m: &Modulus<M>,
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
let mut r = Elem {
limbs: base.limbs,
encoding: PhantomData,
@ -774,10 +805,15 @@ pub fn elem_exp_consttime<M>(
elem_mul(m.oneRR().as_ref(), one, m)
};
Result::from(unsafe {
GFp_BN_mod_exp_mont_consttime(r.limbs.as_mut_ptr(), r.limbs.as_ptr(),
exponent.limbs.as_ptr(),
oneR.limbs.as_ptr(), m.limbs.as_ptr(),
m.limbs.len(), &m.n0)
GFp_BN_mod_exp_mont_consttime(
r.limbs.as_mut_ptr(),
r.limbs.as_ptr(),
exponent.limbs.as_ptr(),
oneR.limbs.as_ptr(),
m.limbs.as_ptr(),
m.limbs.len(),
&m.n0,
)
})?;
// XXX: On x86-64 only, `GFp_BN_mod_exp_mont_consttime` does the conversion
@ -798,17 +834,16 @@ pub fn elem_exp_consttime<M>(
/// Uses Fermat's Little Theorem to calculate modular inverse in constant time.
#[cfg(feature = "rsa_signing")]
pub fn elem_inverse_consttime<M: Prime>(
a: Elem<M, R>,
m: &Modulus<M>) -> Result<Elem<M, Unencoded>, error::Unspecified> {
a: Elem<M, R>, m: &Modulus<M>,
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
elem_exp_consttime(a, &PrivateExponent::for_flt(&m), m)
}
/// Verified a == b**-1 (mod m), i.e. a**-1 == b (mod m).
#[cfg(feature = "rsa_signing")]
pub fn verify_inverses_consttime<M>(a: &Elem<M, R>, b: Elem<M, Unencoded>,
m: &Modulus<M>)
-> Result<(), error::Unspecified>
{
pub fn verify_inverses_consttime<M>(
a: &Elem<M, R>, b: Elem<M, Unencoded>, m: &Modulus<M>,
) -> Result<(), error::Unspecified> {
if elem_mul(a, b, m).is_one() {
Ok(())
} else {
@ -817,10 +852,13 @@ pub fn verify_inverses_consttime<M>(a: &Elem<M, R>, b: Elem<M, Unencoded>,
}
#[cfg(any(test, feature = "rsa_signing"))]
pub fn elem_verify_equal_consttime<M, E>(a: &Elem<M, E>, b: &Elem<M, E>)
-> Result<(), error::Unspecified> {
constant_time::verify_slices_are_equal(limb::limbs_as_bytes(&a.limbs),
limb::limbs_as_bytes(&b.limbs))
pub fn elem_verify_equal_consttime<M, E>(
a: &Elem<M, E>, b: &Elem<M, E>,
) -> Result<(), error::Unspecified> {
constant_time::verify_slices_are_equal(
limb::limbs_as_bytes(&a.limbs),
limb::limbs_as_bytes(&b.limbs),
)
}
/// Nonnegative integers.
@ -831,10 +869,10 @@ pub struct Nonnegative {
#[cfg(feature = "rsa_signing")]
impl Nonnegative {
pub fn from_be_bytes_with_bit_length(input: untrusted::Input)
-> Result<(Self, bits::BitLength), error::Unspecified> {
let mut limbs =
vec![0; (input.len() + limb::LIMB_BYTES - 1) / limb::LIMB_BYTES];
pub fn from_be_bytes_with_bit_length(
input: untrusted::Input,
) -> Result<(Self, bits::BitLength), error::Unspecified> {
let mut limbs = vec![0; (input.len() + limb::LIMB_BYTES - 1) / limb::LIMB_BYTES];
// Rejects empty inputs.
limb::parse_big_endian_and_pad_consttime(input, &mut limbs)?;
while limbs.last() == Some(&0) {
@ -849,35 +887,31 @@ impl Nonnegative {
limb::limbs_are_even_constant_time(&self.limbs) != limb::LimbMask::True
}
pub fn verify_less_than(&self, other: &Self)
-> Result<(), error::Unspecified> {
pub fn verify_less_than(&self, other: &Self) -> Result<(), error::Unspecified> {
if !greater_than(other, self) {
return Err(error::Unspecified);
}
Ok(())
}
pub fn to_elem<M>(&self, m: &Modulus<M>)
-> Result<Elem<M, Unencoded>, error::Unspecified> {
pub fn to_elem<M>(&self, m: &Modulus<M>) -> Result<Elem<M, Unencoded>, error::Unspecified> {
self.verify_less_than_modulus(&m)?;
let mut r = m.zero();
r.limbs[0..self.limbs.len()].copy_from_slice(&self.limbs);
Ok(r)
}
pub fn verify_less_than_modulus<M>(&self, m: &Modulus<M>)
-> Result<(), error::Unspecified>
{
pub fn verify_less_than_modulus<M>(&self, m: &Modulus<M>) -> Result<(), error::Unspecified> {
if self.limbs.len() > m.limbs.len() {
return Err(error::Unspecified);
}
if self.limbs.len() == m.limbs.len() {
if limb::limbs_less_than_limbs_consttime(&self.limbs, &m.limbs)
!= limb::LimbMask::True {
return Err(error::Unspecified)
if limb::limbs_less_than_limbs_consttime(&self.limbs, &m.limbs) != limb::LimbMask::True
{
return Err(error::Unspecified);
}
}
return Ok(())
return Ok(());
}
}
@ -929,48 +963,50 @@ impl From<u64> for N0 {
}
}
extern {
extern "C" {
// `r` and/or 'a' and/or 'b' may alias.
fn GFp_bn_mul_mont(r: *mut limb::Limb, a: *const limb::Limb,
b: *const limb::Limb, n: *const limb::Limb,
n0: &N0, num_limbs: c::size_t);
fn GFp_bn_mul_mont(
r: *mut limb::Limb, a: *const limb::Limb, b: *const limb::Limb, n: *const limb::Limb,
n0: &N0, num_limbs: c::size_t,
);
fn GFp_bn_mul_mont_check_num_limbs(num_limbs: c::size_t) -> bssl::Result;
fn GFp_bn_neg_inv_mod_r_u64(n: u64) -> u64;
fn LIMBS_shl_mod(r: *mut limb::Limb, a: *const limb::Limb,
m: *const limb::Limb, num_limbs: c::size_t);
fn LIMBS_shl_mod(
r: *mut limb::Limb, a: *const limb::Limb, m: *const limb::Limb, num_limbs: c::size_t,
);
}
#[cfg(feature = "rsa_signing")]
extern {
fn GFp_bn_from_montgomery_in_place(r: *mut limb::Limb, num_r: c::size_t,
a: *mut limb::Limb, num_a: c::size_t,
n: *const limb::Limb, num_n: c::size_t,
n0: &N0) -> bssl::Result;
extern "C" {
fn GFp_bn_from_montgomery_in_place(
r: *mut limb::Limb, num_r: c::size_t, a: *mut limb::Limb, num_a: c::size_t,
n: *const limb::Limb, num_n: c::size_t, n0: &N0,
) -> bssl::Result;
// `r` and `a` may alias.
fn GFp_BN_mod_exp_mont_consttime(r: *mut limb::Limb,
a_mont: *const limb::Limb,
p: *const limb::Limb,
one_mont: *const limb::Limb,
n: *const limb::Limb,
num_limbs: c::size_t, n0: &N0) -> bssl::Result;
fn GFp_BN_mod_exp_mont_consttime(
r: *mut limb::Limb, a_mont: *const limb::Limb, p: *const limb::Limb,
one_mont: *const limb::Limb, n: *const limb::Limb, num_limbs: c::size_t, n0: &N0,
) -> bssl::Result;
// `r` and `a` may alias.
fn LIMBS_add_mod(r: *mut limb::Limb, a: *const limb::Limb,
b: *const limb::Limb, m: *const limb::Limb,
num_limbs: c::size_t);
fn LIMBS_sub_mod(r: *mut limb::Limb, a: *const limb::Limb,
b: *const limb::Limb, m: *const limb::Limb,
num_limbs: c::size_t);
fn LIMBS_add_mod(
r: *mut limb::Limb, a: *const limb::Limb, b: *const limb::Limb, m: *const limb::Limb,
num_limbs: c::size_t,
);
fn LIMBS_sub_mod(
r: *mut limb::Limb, a: *const limb::Limb, b: *const limb::Limb, m: *const limb::Limb,
num_limbs: c::size_t,
);
}
#[cfg(test)]
mod tests {
use super::*;
use untrusted;
use crate::test;
use untrusted;
// Type-level representation of an arbitrary modulus.
struct M {}
@ -978,49 +1014,52 @@ mod tests {
#[cfg(feature = "rsa_signing")]
#[test]
fn test_elem_exp_consttime() {
test::from_file("src/rsa/bigint_elem_exp_consttime_tests.txt",
|section, test_case| {
assert_eq!(section, "");
test::from_file(
"src/rsa/bigint_elem_exp_consttime_tests.txt",
|section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M");
let expected_result = consume_elem(test_case, "ModExp", &m);
let base = consume_elem(test_case, "A", &m);
let e = {
let bytes = test_case.consume_bytes("E");
PrivateExponent::from_be_bytes_padded(
untrusted::Input::from(&bytes), &m).expect("valid exponent")
};
let base = into_encoded(base, &m);
let actual_result = elem_exp_consttime(base, &e, &m).unwrap();
assert_elem_eq(&actual_result, &expected_result);
let m = consume_modulus::<M>(test_case, "M");
let expected_result = consume_elem(test_case, "ModExp", &m);
let base = consume_elem(test_case, "A", &m);
let e = {
let bytes = test_case.consume_bytes("E");
PrivateExponent::from_be_bytes_padded(untrusted::Input::from(&bytes), &m)
.expect("valid exponent")
};
let base = into_encoded(base, &m);
let actual_result = elem_exp_consttime(base, &e, &m).unwrap();
assert_elem_eq(&actual_result, &expected_result);
Ok(())
})
Ok(())
},
)
}
#[test]
fn test_elem_exp_vartime() {
test::from_file("src/rsa/bigint_elem_exp_vartime_tests.txt",
|section, test_case| {
assert_eq!(section, "");
test::from_file(
"src/rsa/bigint_elem_exp_vartime_tests.txt",
|section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M");
let expected_result = consume_elem(test_case, "ModExp", &m);
let base = consume_elem(test_case, "A", &m);
let e = consume_public_exponent(test_case, "E");
let m = consume_modulus::<M>(test_case, "M");
let expected_result = consume_elem(test_case, "ModExp", &m);
let base = consume_elem(test_case, "A", &m);
let e = consume_public_exponent(test_case, "E");
let actual_result = elem_exp_vartime(base, e, &m);
let actual_result = actual_result.into_unencoded(&m);
assert_elem_eq(&actual_result, &expected_result);
let actual_result = elem_exp_vartime(base, e, &m);
let actual_result = actual_result.into_unencoded(&m);
assert_elem_eq(&actual_result, &expected_result);
Ok(())
})
Ok(())
},
)
}
#[test]
fn test_elem_mul() {
test::from_file("src/rsa/bigint_elem_mul_tests.txt",
|section, test_case| {
test::from_file("src/rsa/bigint_elem_mul_tests.txt", |section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M");
@ -1040,83 +1079,94 @@ mod tests {
#[test]
fn test_elem_squared() {
test::from_file("src/rsa/bigint_elem_squared_tests.txt",
|section, test_case| {
assert_eq!(section, "");
test::from_file(
"src/rsa/bigint_elem_squared_tests.txt",
|section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M");
let expected_result = consume_elem(test_case, "ModSquare", &m);
let a = consume_elem(test_case, "A", &m);
let m = consume_modulus::<M>(test_case, "M");
let expected_result = consume_elem(test_case, "ModSquare", &m);
let a = consume_elem(test_case, "A", &m);
let a = into_encoded(a, &m);
let actual_result = elem_squared(a, &m.as_partial());
let actual_result = actual_result.into_unencoded(&m);
assert_elem_eq(&actual_result, &expected_result);
let a = into_encoded(a, &m);
let actual_result = elem_squared(a, &m.as_partial());
let actual_result = actual_result.into_unencoded(&m);
assert_elem_eq(&actual_result, &expected_result);
Ok(())
})
Ok(())
},
)
}
#[cfg(feature = "rsa_signing")]
#[test]
fn test_elem_reduced() {
test::from_file("src/rsa/bigint_elem_reduced_tests.txt",
|section, test_case| {
assert_eq!(section, "");
test::from_file(
"src/rsa/bigint_elem_reduced_tests.txt",
|section, test_case| {
assert_eq!(section, "");
struct MM {}
unsafe impl SmallerModulus<MM> for M {}
unsafe impl NotMuchSmallerModulus<MM> for M {}
struct MM {}
unsafe impl SmallerModulus<MM> for M {}
unsafe impl NotMuchSmallerModulus<MM> for M {}
let m = consume_modulus::<M>(test_case, "M");
let expected_result = consume_elem(test_case, "R", &m);
let a = consume_elem_unchecked::<MM>(
test_case, "A", expected_result.limbs.len() * 2);
let m = consume_modulus::<M>(test_case, "M");
let expected_result = consume_elem(test_case, "R", &m);
let a =
consume_elem_unchecked::<MM>(test_case, "A", expected_result.limbs.len() * 2);
let actual_result = elem_reduced(&a, &m).unwrap();
let oneRR = m.oneRR();
let actual_result = elem_mul(oneRR.as_ref(), actual_result, &m);
assert_elem_eq(&actual_result, &expected_result);
let actual_result = elem_reduced(&a, &m).unwrap();
let oneRR = m.oneRR();
let actual_result = elem_mul(oneRR.as_ref(), actual_result, &m);
assert_elem_eq(&actual_result, &expected_result);
Ok(())
})
Ok(())
},
)
}
#[cfg(feature = "rsa_signing")]
#[test]
fn test_elem_reduced_once() {
test::from_file("src/rsa/bigint_elem_reduced_once_tests.txt",
|section, test_case| {
assert_eq!(section, "");
test::from_file(
"src/rsa/bigint_elem_reduced_once_tests.txt",
|section, test_case| {
assert_eq!(section, "");
struct N {}
struct QQ {}
unsafe impl SmallerModulus<N> for QQ {}
unsafe impl SlightlySmallerModulus<N> for QQ {}
struct N {}
struct QQ {}
unsafe impl SmallerModulus<N> for QQ {}
unsafe impl SlightlySmallerModulus<N> for QQ {}
let qq = consume_modulus::<QQ>(test_case, "QQ");
let expected_result = consume_elem::<QQ>(test_case, "R", &qq);
let n = consume_modulus::<N>(test_case, "N");
let a = consume_elem::<N>(test_case, "A", &n);
let qq = consume_modulus::<QQ>(test_case, "QQ");
let expected_result = consume_elem::<QQ>(test_case, "R", &qq);
let n = consume_modulus::<N>(test_case, "N");
let a = consume_elem::<N>(test_case, "A", &n);
let actual_result = elem_reduced_once(&a, &qq);
assert_elem_eq(&actual_result, &expected_result);
let actual_result = elem_reduced_once(&a, &qq);
assert_elem_eq(&actual_result, &expected_result);
Ok(())
})
Ok(())
},
)
}
fn consume_elem<M>(test_case: &mut test::TestCase, name: &str, m: &Modulus<M>)
-> Elem<M, Unencoded> {
fn consume_elem<M>(
test_case: &mut test::TestCase, name: &str, m: &Modulus<M>,
) -> Elem<M, Unencoded> {
let value = test_case.consume_bytes(name);
Elem::from_be_bytes_padded(untrusted::Input::from(&value), m).unwrap()
}
#[cfg(feature = "rsa_signing")]
fn consume_elem_unchecked<M>(test_case: &mut test::TestCase, name: &str,
num_limbs: usize) -> Elem<M, Unencoded> {
fn consume_elem_unchecked<M>(
test_case: &mut test::TestCase, name: &str, num_limbs: usize,
) -> Elem<M, Unencoded> {
let value = consume_nonnegative(test_case, name);
let mut limbs = BoxedLimbs::zero(Width { num_limbs, m: PhantomData });
let mut limbs = BoxedLimbs::zero(Width {
num_limbs,
m: PhantomData,
});
limbs[0..value.limbs.len()].copy_from_slice(&value.limbs);
Elem {
limbs,
@ -1124,27 +1174,23 @@ mod tests {
}
}
fn consume_modulus<M>(test_case: &mut test::TestCase, name: &str)
-> Modulus<M> {
fn consume_modulus<M>(test_case: &mut test::TestCase, name: &str) -> Modulus<M> {
let value = test_case.consume_bytes(name);
let (value, _) = Modulus::from_be_bytes_with_bit_length(
untrusted::Input::from(&value)).unwrap();
let (value, _) =
Modulus::from_be_bytes_with_bit_length(untrusted::Input::from(&value)).unwrap();
value
}
fn consume_public_exponent(test_case: &mut test::TestCase, name: &str)
-> PublicExponent {
fn consume_public_exponent(test_case: &mut test::TestCase, name: &str) -> PublicExponent {
let bytes = test_case.consume_bytes(name);
PublicExponent::from_be_bytes(
untrusted::Input::from(&bytes), 3).unwrap()
PublicExponent::from_be_bytes(untrusted::Input::from(&bytes), 3).unwrap()
}
#[cfg(feature = "rsa_signing")]
fn consume_nonnegative(test_case: &mut test::TestCase, name: &str)
-> Nonnegative {
fn consume_nonnegative(test_case: &mut test::TestCase, name: &str) -> Nonnegative {
let bytes = test_case.consume_bytes(name);
let (r, _r_bits) = Nonnegative::from_be_bytes_with_bit_length(
untrusted::Input::from(&bytes)).unwrap();
let (r, _r_bits) =
Nonnegative::from_be_bytes_with_bit_length(untrusted::Input::from(&bytes)).unwrap();
r
}

View File

@ -18,8 +18,7 @@
// components.
/// RSA signatures.
use crate::{bits, der, limb, error};
use crate::{bits, der, error, limb};
use untrusted;
mod padding;
@ -29,24 +28,16 @@ mod padding;
pub use self::padding::RSAEncoding;
pub use self::padding::{
RSA_PKCS1_SHA256,
RSA_PKCS1_SHA384,
RSA_PKCS1_SHA512,
RSA_PSS_SHA256,
RSA_PSS_SHA384,
RSA_PSS_SHA512
RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512, RSA_PSS_SHA256, RSA_PSS_SHA384,
RSA_PSS_SHA512,
};
// Maximum RSA modulus size supported for signature verification (in bytes).
const PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN: usize =
bigint::MODULUS_MAX_LIMBS * limb::LIMB_BYTES;
const PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN: usize = bigint::MODULUS_MAX_LIMBS * limb::LIMB_BYTES;
// Keep in sync with the documentation comment for `KeyPair`.
#[cfg(feature = "rsa_signing")]
const PRIVATE_KEY_PUBLIC_MODULUS_MAX_BITS: bits::BitLength =
bits::BitLength(4096);
const PRIVATE_KEY_PUBLIC_MODULUS_MAX_BITS: bits::BitLength = bits::BitLength(4096);
/// Parameters for RSA verification.
pub struct RSAParameters {
@ -66,9 +57,9 @@ enum RSAParametersID {
RSA_PSS_2048_8192_SHA512,
}
fn parse_public_key(input: untrusted::Input)
-> Result<(untrusted::Input, untrusted::Input),
error::Unspecified> {
fn parse_public_key(
input: untrusted::Input,
) -> Result<(untrusted::Input, untrusted::Input), error::Unspecified> {
input.read_all(error::Unspecified, |input| {
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
let n = der::positive_integer(input)?;

View File

@ -12,8 +12,8 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
use crate::{bits, der, digest, error, polyfill};
use super::PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN;
use crate::{bits, der, digest, error, polyfill};
use untrusted;
#[cfg(feature = "rsa_signing")]
@ -32,9 +32,10 @@ pub trait RSAPadding: 'static + Sync + ::private::Sealed {
#[cfg(feature = "rsa_signing")]
pub trait RSAEncoding: RSAPadding {
#[doc(hidden)]
fn encode(&self, m_hash: &digest::Digest, m_out: &mut [u8],
mod_bits: bits::BitLength, rng: &rand::SecureRandom)
-> Result<(), error::Unspecified>;
fn encode(
&self, m_hash: &digest::Digest, m_out: &mut [u8], mod_bits: bits::BitLength,
rng: &rand::SecureRandom,
) -> Result<(), error::Unspecified>;
}
/// Verification of an RSA signature encoding as described in
@ -42,8 +43,9 @@ pub trait RSAEncoding: RSAPadding {
///
/// [RFC 3447 Section 8]: https://tools.ietf.org/html/rfc3447#section-8
pub trait RSAVerification: RSAPadding {
fn verify(&self, m_hash: &digest::Digest, m: &mut untrusted::Reader,
mod_bits: bits::BitLength) -> Result<(), error::Unspecified>;
fn verify(
&self, m_hash: &digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength,
) -> Result<(), error::Unspecified>;
}
/// PKCS#1 1.5 padding as described in [RFC 3447 Section 8.2].
@ -57,30 +59,31 @@ pub struct PKCS1 {
digestinfo_prefix: &'static [u8],
}
impl ::private::Sealed for PKCS1 { }
impl ::private::Sealed for PKCS1 {}
impl RSAPadding for PKCS1 {
fn digest_alg(&self) -> &'static digest::Algorithm { self.digest_alg }
}
#[cfg(feature ="rsa_signing")]
#[cfg(feature = "rsa_signing")]
impl RSAEncoding for PKCS1 {
fn encode(&self, m_hash: &digest::Digest, m_out: &mut [u8],
_mod_bits: bits::BitLength, _rng: &rand::SecureRandom)
-> Result<(), error::Unspecified> {
fn encode(
&self, m_hash: &digest::Digest, m_out: &mut [u8], _mod_bits: bits::BitLength,
_rng: &rand::SecureRandom,
) -> Result<(), error::Unspecified> {
pkcs1_encode(&self, m_hash, m_out);
Ok(())
}
}
impl RSAVerification for PKCS1 {
fn verify(&self, m_hash: &digest::Digest, m: &mut untrusted::Reader,
mod_bits: bits::BitLength) -> Result<(), error::Unspecified> {
fn verify(
&self, m_hash: &digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength,
) -> Result<(), error::Unspecified> {
// `mod_bits.as_usize_bytes_rounded_up() <=
// PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN` is ensured by `verify_rsa()`.
let mut calculated = [0u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN];
let calculated =
&mut calculated[..mod_bits.as_usize_bytes_rounded_up()];
let calculated = &mut calculated[..mod_bits.as_usize_bytes_rounded_up()];
pkcs1_encode(&self, m_hash, calculated);
if m.skip_to_end() != polyfill::ref_from_mut_ref(calculated) {
return Err(error::Unspecified);
@ -96,8 +99,7 @@ impl RSAVerification for PKCS1 {
fn pkcs1_encode(pkcs1: &PKCS1, m_hash: &digest::Digest, m_out: &mut [u8]) {
let em = m_out;
let digest_len =
pkcs1.digestinfo_prefix.len() + pkcs1.digest_alg.output_len;
let digest_len = pkcs1.digestinfo_prefix.len() + pkcs1.digest_alg.output_len;
// The specification requires at least 8 bytes of padding. Since we
// disallow keys smaller than 2048 bits, this should always be true.
@ -110,8 +112,7 @@ fn pkcs1_encode(pkcs1: &PKCS1, m_hash: &digest::Digest, m_out: &mut [u8]) {
}
em[2 + pad_len] = 0;
let (digest_prefix, digest_dst) = em[3 + pad_len..]
.split_at_mut(pkcs1.digestinfo_prefix.len());
let (digest_prefix, digest_dst) = em[3 + pad_len..].split_at_mut(pkcs1.digestinfo_prefix.len());
digest_prefix.copy_from_slice(pkcs1.digestinfo_prefix);
digest_dst.copy_from_slice(m_hash.as_ref());
}
@ -125,21 +126,33 @@ macro_rules! rsa_pkcs1_padding {
digest_alg: $digest_alg,
digestinfo_prefix: $digestinfo_prefix,
};
}
};
}
rsa_pkcs1_padding!(RSA_PKCS1_SHA1, &digest::SHA1,
&SHA1_PKCS1_DIGESTINFO_PREFIX,
"PKCS#1 1.5 padding using SHA-1 for RSA signatures.");
rsa_pkcs1_padding!(RSA_PKCS1_SHA256, &digest::SHA256,
&SHA256_PKCS1_DIGESTINFO_PREFIX,
"PKCS#1 1.5 padding using SHA-256 for RSA signatures.");
rsa_pkcs1_padding!(RSA_PKCS1_SHA384, &digest::SHA384,
&SHA384_PKCS1_DIGESTINFO_PREFIX,
"PKCS#1 1.5 padding using SHA-384 for RSA signatures.");
rsa_pkcs1_padding!(RSA_PKCS1_SHA512, &digest::SHA512,
&SHA512_PKCS1_DIGESTINFO_PREFIX,
"PKCS#1 1.5 padding using SHA-512 for RSA signatures.");
rsa_pkcs1_padding!(
RSA_PKCS1_SHA1,
&digest::SHA1,
&SHA1_PKCS1_DIGESTINFO_PREFIX,
"PKCS#1 1.5 padding using SHA-1 for RSA signatures."
);
rsa_pkcs1_padding!(
RSA_PKCS1_SHA256,
&digest::SHA256,
&SHA256_PKCS1_DIGESTINFO_PREFIX,
"PKCS#1 1.5 padding using SHA-256 for RSA signatures."
);
rsa_pkcs1_padding!(
RSA_PKCS1_SHA384,
&digest::SHA384,
&SHA384_PKCS1_DIGESTINFO_PREFIX,
"PKCS#1 1.5 padding using SHA-384 for RSA signatures."
);
rsa_pkcs1_padding!(
RSA_PKCS1_SHA512,
&digest::SHA512,
&SHA512_PKCS1_DIGESTINFO_PREFIX,
"PKCS#1 1.5 padding using SHA-512 for RSA signatures."
);
macro_rules! pkcs1_digestinfo_prefix {
( $name:ident, $digest_len:expr, $digest_oid_len:expr,
@ -155,20 +168,32 @@ macro_rules! pkcs1_digestinfo_prefix {
}
pkcs1_digestinfo_prefix!(
SHA1_PKCS1_DIGESTINFO_PREFIX, 20, 5, [ 0x2b, 0x0e, 0x03, 0x02, 0x1a ]);
SHA1_PKCS1_DIGESTINFO_PREFIX,
20,
5,
[0x2b, 0x0e, 0x03, 0x02, 0x1a]
);
pkcs1_digestinfo_prefix!(
SHA256_PKCS1_DIGESTINFO_PREFIX, 32, 9,
[ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 ]);
SHA256_PKCS1_DIGESTINFO_PREFIX,
32,
9,
[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01]
);
pkcs1_digestinfo_prefix!(
SHA384_PKCS1_DIGESTINFO_PREFIX, 48, 9,
[ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 ]);
SHA384_PKCS1_DIGESTINFO_PREFIX,
48,
9,
[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02]
);
pkcs1_digestinfo_prefix!(
SHA512_PKCS1_DIGESTINFO_PREFIX, 64, 9,
[ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 ]);
SHA512_PKCS1_DIGESTINFO_PREFIX,
64,
9,
[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03]
);
/// RSA PSS padding as described in [RFC 3447 Section 8.1].
///
@ -180,7 +205,7 @@ pub struct PSS {
digest_alg: &'static digest::Algorithm,
}
impl ::private::Sealed for PSS { }
impl ::private::Sealed for PSS {}
#[cfg(feature = "rsa_signing")]
// Maximum supported length of the salt in bytes.
@ -195,9 +220,10 @@ impl RSAPadding for PSS {
impl RSAEncoding for PSS {
// Implement padding procedure per EMSA-PSS,
// https://tools.ietf.org/html/rfc3447#section-9.1.
fn encode(&self, m_hash: &digest::Digest, m_out: &mut [u8],
mod_bits: bits::BitLength, rng: &rand::SecureRandom)
-> Result<(), error::Unspecified> {
fn encode(
&self, m_hash: &digest::Digest, m_out: &mut [u8], mod_bits: bits::BitLength,
rng: &rand::SecureRandom,
) -> Result<(), error::Unspecified> {
let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
// The `m_out` this function fills is the big-endian-encoded value of `m`
@ -230,8 +256,7 @@ impl RSAEncoding for PSS {
// into `em`, and then XOR the value of db.
// Step 9. First output the mask into the out buffer.
let (mut masked_db, digest_terminator) =
em.split_at_mut(metrics.db_len);
let (mut masked_db, digest_terminator) = em.split_at_mut(metrics.db_len);
mgf1(self.digest_alg, h_hash.as_ref(), &mut masked_db)?;
{
@ -264,8 +289,9 @@ impl RSAEncoding for PSS {
impl RSAVerification for PSS {
// RSASSA-PSS-VERIFY from https://tools.ietf.org/html/rfc3447#section-8.1.2
// where steps 1, 2(a), and 2(b) have been done for us.
fn verify(&self, m_hash: &digest::Digest, m: &mut untrusted::Reader,
mod_bits: bits::BitLength) -> Result<(), error::Unspecified> {
fn verify(
&self, m_hash: &digest::Digest, m: &mut untrusted::Reader, mod_bits: bits::BitLength,
) -> Result<(), error::Unspecified> {
let metrics = PSSMetrics::new(self.digest_alg, mod_bits)?;
// RSASSA-PSS-VERIFY Step 2(c). The `m` this function is given is the
@ -351,7 +377,8 @@ impl RSAVerification for PSS {
}
struct PSSMetrics {
#[cfg_attr(not(feature = "rsa_signing"), allow(dead_code))] em_len: usize,
#[cfg_attr(not(feature = "rsa_signing"), allow(dead_code))]
em_len: usize,
db_len: usize,
ps_len: usize,
s_len: usize,
@ -360,8 +387,9 @@ struct PSSMetrics {
}
impl PSSMetrics {
fn new(digest_alg: &'static digest::Algorithm, mod_bits: bits::BitLength)
-> Result<PSSMetrics, error::Unspecified> {
fn new(
digest_alg: &'static digest::Algorithm, mod_bits: bits::BitLength,
) -> Result<PSSMetrics, error::Unspecified> {
let em_bits = mod_bits.try_sub(bits::ONE)?;
let em_len = em_bits.as_usize_bytes_rounded_up();
let leading_zero_bits = (8 * em_len) - em_bits.as_usize_bits();
@ -386,20 +414,21 @@ impl PSSMetrics {
debug_assert!(em_bits.as_usize_bits() >= (8 * h_len) + (8 * s_len) + 9);
Ok(PSSMetrics {
em_len: em_len,
db_len: db_len,
ps_len: ps_len,
s_len: s_len,
h_len: h_len,
top_byte_mask: top_byte_mask,
em_len,
db_len,
ps_len,
s_len,
h_len,
top_byte_mask,
})
}
}
// Mask-generating function MGF1 as described in
// https://tools.ietf.org/html/rfc3447#appendix-B.2.1.
fn mgf1(digest_alg: &'static digest::Algorithm, seed: &[u8], mask: &mut [u8])
-> Result<(), error::Unspecified> {
fn mgf1(
digest_alg: &'static digest::Algorithm, seed: &[u8], mask: &mut [u8],
) -> Result<(), error::Unspecified> {
let digest_len = digest_alg.output_len;
// Maximum counter value is the value of (mask_len / digest_len) rounded up.
@ -417,8 +446,9 @@ fn mgf1(digest_alg: &'static digest::Algorithm, seed: &[u8], mask: &mut [u8])
Ok(())
}
fn pss_digest(digest_alg: &'static digest::Algorithm, m_hash: &digest::Digest,
salt: &[u8]) -> digest::Digest {
fn pss_digest(
digest_alg: &'static digest::Algorithm, m_hash: &digest::Digest, salt: &[u8],
) -> digest::Digest {
// Fixed prefix.
const PREFIX_ZEROS: [u8; 8] = [0u8; 8];
@ -437,32 +467,40 @@ macro_rules! rsa_pss_padding {
pub static $PADDING_ALGORITHM: PSS = PSS {
digest_alg: $digest_alg,
};
}
};
}
rsa_pss_padding!(RSA_PSS_SHA256, &digest::SHA256,
"RSA PSS padding using SHA-256 for RSA signatures.\n\nSee
rsa_pss_padding!(
RSA_PSS_SHA256,
&digest::SHA256,
"RSA PSS padding using SHA-256 for RSA signatures.\n\nSee
\"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
documentation for more details.");
rsa_pss_padding!(RSA_PSS_SHA384, &digest::SHA384,
"RSA PSS padding using SHA-384 for RSA signatures.\n\nSee
documentation for more details."
);
rsa_pss_padding!(
RSA_PSS_SHA384,
&digest::SHA384,
"RSA PSS padding using SHA-384 for RSA signatures.\n\nSee
\"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
documentation for more details.");
rsa_pss_padding!(RSA_PSS_SHA512, &digest::SHA512,
"RSA PSS padding using SHA-512 for RSA signatures.\n\nSee
documentation for more details."
);
rsa_pss_padding!(
RSA_PSS_SHA512,
&digest::SHA512,
"RSA PSS padding using SHA-512 for RSA signatures.\n\nSee
\"`RSA_PSS_*` Details\" in `ring::signature`'s module-level
documentation for more details.");
documentation for more details."
);
#[cfg(test)]
mod test {
use crate::{digest, error, test};
use super::*;
use crate::{digest, error, test};
use untrusted;
#[test]
fn test_pss_padding_verify() {
test::from_file("src/rsa/rsa_pss_padding_tests.txt",
|section, test_case| {
test::from_file("src/rsa/rsa_pss_padding_tests.txt", |section, test_case| {
assert_eq!(section, "");
let digest_name = test_case.consume_string("Digest");
@ -470,13 +508,12 @@ mod test {
"SHA256" => &RSA_PSS_SHA256,
"SHA384" => &RSA_PSS_SHA384,
"SHA512" => &RSA_PSS_SHA512,
_ => { panic!("Unsupported digest: {}", digest_name) }
_ => panic!("Unsupported digest: {}", digest_name),
};
let msg = test_case.consume_bytes("Msg");
let msg = untrusted::Input::from(&msg);
let m_hash = digest::digest(alg.digest_alg(),
msg.as_slice_less_safe());
let m_hash = digest::digest(alg.digest_alg(), msg.as_slice_less_safe());
let encoded = test_case.consume_bytes("EM");
let encoded = untrusted::Input::from(&encoded);
@ -488,8 +525,7 @@ mod test {
let expected_result = test_case.consume_string("Result");
let actual_result =
encoded.read_all(error::Unspecified,
|m| alg.verify(&m_hash, m, bit_len));
encoded.read_all(error::Unspecified, |m| alg.verify(&m_hash, m, bit_len));
assert_eq!(actual_result.is_ok(), expected_result == "P");
Ok(())
@ -500,8 +536,7 @@ mod test {
#[cfg(feature = "rsa_signing")]
#[test]
fn test_pss_padding_encode() {
test::from_file("src/rsa/rsa_pss_padding_tests.txt",
|section, test_case| {
test::from_file("src/rsa/rsa_pss_padding_tests.txt", |section, test_case| {
assert_eq!(section, "");
let digest_name = test_case.consume_string("Digest");
@ -509,7 +544,7 @@ mod test {
"SHA256" => &RSA_PSS_SHA256,
"SHA384" => &RSA_PSS_SHA384,
"SHA512" => &RSA_PSS_SHA512,
_ => { panic!("Unsupported digest: {}", digest_name) }
_ => panic!("Unsupported digest: {}", digest_name),
};
let msg = test_case.consume_bytes("Msg");
@ -520,7 +555,7 @@ mod test {
// Only test the valid outputs
if expected_result != "P" {
return Ok(())
return Ok(());
}
let rng = test::rand::FixedSliceRandom { bytes: &salt };

View File

@ -12,12 +12,14 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
use super::{
bigint::{self, Prime},
verification, N,
};
use arithmetic::montgomery::R;
/// RSA PKCS#1 1.5 signatures.
use crate::{bits, der, digest, error, pkcs8, rand};
use std;
use super::{bigint, bigint::Prime, N, verification};
use arithmetic::montgomery::R;
use untrusted;
/// An RSA key pair, used for signing. Feature: `rsa_signing`.
@ -91,7 +93,8 @@ impl KeyPair {
/// regarding these expectations are not done.
/// * Section 6.4.1.2.1, Step 3: Since neither the public key nor the
/// expected modulus length is provided as a parameter, the consistency
/// check between these values and the private key's value of n isn't done.
/// check between these values and the private key's value of n isn't
/// done.
/// * Section 6.4.1.2.1, Step 5: No primality tests are done, both for
/// performance reasons and to avoid any side channels that such tests
/// would provide.
@ -133,13 +136,9 @@ impl KeyPair {
///
/// [RFC 5958]:
/// https://tools.ietf.org/html/rfc5958
///
pub fn from_pkcs8(input: untrusted::Input)
-> Result<Self, error::Unspecified> {
const RSA_ENCRYPTION: &[u8] =
include_bytes!("../data/alg-rsa-encryption.der");
let (der, _) = pkcs8::unwrap_key_(&RSA_ENCRYPTION,
pkcs8::Version::V1Only, input)?;
pub fn from_pkcs8(input: untrusted::Input) -> Result<Self, error::Unspecified> {
const RSA_ENCRYPTION: &[u8] = include_bytes!("../data/alg-rsa-encryption.der");
let (der, _) = pkcs8::unwrap_key_(&RSA_ENCRYPTION, pkcs8::Version::V1Only, input)?;
Self::from_der(der)
}
@ -158,8 +157,7 @@ impl KeyPair {
///
/// [NIST SP-800-56B rev. 1]:
/// http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br1.pdf
pub fn from_der(input: untrusted::Input)
-> Result<Self, error::Unspecified> {
pub fn from_der(input: untrusted::Input) -> Result<Self, error::Unspecified> {
input.read_all(error::Unspecified, |input| {
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
let version = der::small_nonnegative_integer(input)?;
@ -175,18 +173,15 @@ impl KeyPair {
let dQ = der::positive_integer(input)?;
let qInv = der::positive_integer(input)?;
let (p, p_bits) =
bigint::Nonnegative::from_be_bytes_with_bit_length(p)?;
let (q, q_bits) =
bigint::Nonnegative::from_be_bytes_with_bit_length(q)?;
let (p, p_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(p)?;
let (q, q_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(q)?;
// Our implementation of CRT-based modular exponentiation used
// requires that `p > q` so swap them if `p < q`. If swapped,
// `qInv` is recalculated below. `p != q` is verified
// implicitly below, e.g. when `q_mod_p` is constructed.
let ((p, p_bits, dP), (q, q_bits, dQ, qInv)) =
match q.verify_less_than(&p) {
Ok(_) => ((p, p_bits, dP), (q, q_bits, dQ, Some(qInv))),
let ((p, p_bits, dP), (q, q_bits, dQ, qInv)) = match q.verify_less_than(&p) {
Ok(_) => ((p, p_bits, dP), (q, q_bits, dQ, Some(qInv))),
Err(_) => {
// TODO: verify `q` and `qInv` are inverses (mod p).
((q, q_bits, dQ), (p, p_bits, dP, None))
@ -214,8 +209,12 @@ impl KeyPair {
// Step 1.c. We validate e >= 65537.
let public_key = verification::Key::from_modulus_and_exponent(
n, e, bits::BitLength::from_usize_bits(2048),
super::PRIVATE_KEY_PUBLIC_MODULUS_MAX_BITS, 65537)?;
n,
e,
bits::BitLength::from_usize_bits(2048),
super::PRIVATE_KEY_PUBLIC_MODULUS_MAX_BITS,
65537,
)?;
// 6.4.1.4.3 says to skip 6.4.1.2.1 Step 2.
@ -270,12 +269,13 @@ impl KeyPair {
// and then assume that these preconditions are enough to
// let us assume that checking p * q == 0 (mod n) is equivalent
// to checking p * q == n.
let q_mod_n = bigint::elem_mul(public_key.n.oneRR().as_ref(),
q_mod_n_decoded.clone(),
&public_key.n);
let q_mod_n = bigint::elem_mul(
public_key.n.oneRR().as_ref(),
q_mod_n_decoded.clone(),
&public_key.n,
);
let p_mod_n = p.to_elem(&public_key.n)?;
let pq_mod_n =
bigint::elem_mul(&q_mod_n, p_mod_n, &public_key.n);
let pq_mod_n = bigint::elem_mul(&q_mod_n, p_mod_n, &public_key.n);
if !pq_mod_n.is_zero() {
return Err(error::Unspecified);
}
@ -288,8 +288,7 @@ impl KeyPair {
// has a bit length of half_n_bits + 1, this check gives us
// 2**half_n_bits <= d, and knowing d is odd makes the
// inequality strict.
let (d, d_bits) =
bigint::Nonnegative::from_be_bytes_with_bit_length(d)?;
let (d, d_bits) = bigint::Nonnegative::from_be_bytes_with_bit_length(d)?;
if !(half_n_bits < d_bits) {
return Err(error::Unspecified);
}
@ -319,9 +318,8 @@ impl KeyPair {
} else {
// We swapped `p` and `q` above, so we need to calculate
// `qInv`. Step 7.f below will verify `qInv` is correct.
let q_mod_p = bigint::elem_mul(p.modulus.oneRR().as_ref(),
q_mod_p.clone(),
&p.modulus);
let q_mod_p =
bigint::elem_mul(p.modulus.oneRR().as_ref(), q_mod_p.clone(), &p.modulus);
bigint::elem_inverse_consttime(q_mod_p, &p.modulus)?
};
@ -330,12 +328,10 @@ impl KeyPair {
// do modulo with an even modulus.
// Step 7.f.
let qInv =
bigint::elem_mul(p.modulus.oneRR().as_ref(), qInv, &p.modulus);
let qInv = bigint::elem_mul(p.modulus.oneRR().as_ref(), qInv, &p.modulus);
bigint::verify_inverses_consttime(&qInv, q_mod_p, &p.modulus)?;
let qq =
bigint::elem_mul(&q_mod_n, q_mod_n_decoded, &public_key.n)
let qq = bigint::elem_mul(&q_mod_n, q_mod_n_decoded, &public_key.n)
.into_modulus::<QQ>()?;
Ok(Self {
@ -353,9 +349,7 @@ impl KeyPair {
/// Returns the length in bytes of the key pair's public modulus.
///
/// A signature has the same length as the public modulus.
pub fn public_modulus_len(&self) -> usize {
self.public_key.modulus_len()
}
pub fn public_modulus_len(&self) -> usize { self.public_key.modulus_len() }
}
struct PrivatePrime<M: Prime> {
@ -366,8 +360,7 @@ struct PrivatePrime<M: Prime> {
impl<M: Prime + Clone> PrivatePrime<M> {
/// Constructs a `PrivatePrime` from the private prime `p` and `dP` where
/// dP == d % (p - 1).
fn new(p: bigint::Nonnegative, dP: untrusted::Input)
-> Result<Self, error::Unspecified> {
fn new(p: bigint::Nonnegative, dP: untrusted::Input) -> Result<Self, error::Unspecified> {
let p = bigint::Modulus::from(p)?;
// [NIST SP-800-56B rev. 1] 6.4.1.4.3 - Steps 7.a & 7.b.
@ -389,10 +382,13 @@ impl<M: Prime + Clone> PrivatePrime<M> {
}
}
fn elem_exp_consttime<M, MM>(c: &bigint::Elem<MM>, p: &PrivatePrime<M>)
-> Result<bigint::Elem<M>, error::Unspecified>
where M: bigint::NotMuchSmallerModulus<MM>,
M: Prime {
fn elem_exp_consttime<M, MM>(
c: &bigint::Elem<MM>, p: &PrivatePrime<M>,
) -> Result<bigint::Elem<M>, error::Unspecified>
where
M: bigint::NotMuchSmallerModulus<MM>,
M: Prime,
{
let c_mod_m = bigint::elem_reduced(c, &p.modulus)?;
// We could precompute `oneRRR = elem_squared(&p.oneRR`) as mentioned
// in the Smooth CRT-RSA paper.
@ -401,7 +397,6 @@ fn elem_exp_consttime<M, MM>(c: &bigint::Elem<MM>, p: &PrivatePrime<M>)
bigint::elem_exp_consttime(c_mod_m, &p.exponent, &p.modulus)
}
// Type-level representations of the different moduli used in RSA signing, in
// addition to `super::N`. See `super::bigint`'s modulue-level documentation.
@ -435,7 +430,6 @@ unsafe impl bigint::SlightlySmallerModulus<P> for Q {}
unsafe impl bigint::SmallerModulus<QQ> for Q {}
unsafe impl bigint::NotMuchSmallerModulus<QQ> for Q {}
/// State used for RSA Signing. Feature: `rsa_signing`.
//
// TODO: Remove this; it's not needed if we don't have RSA blinding.
@ -445,11 +439,8 @@ pub struct SigningState {
impl SigningState {
/// Construct a signing state appropriate for use with the given key pair.
pub fn new(key_pair: std::sync::Arc<KeyPair>)
-> Result<Self, error::Unspecified> {
Ok(SigningState {
key_pair: key_pair,
})
pub fn new(key_pair: std::sync::Arc<KeyPair>) -> Result<Self, error::Unspecified> {
Ok(SigningState { key_pair })
}
/// The key pair. This can be used, for example, to access the key pair's
@ -472,9 +463,10 @@ impl SigningState {
/// constant time to protect the private key from side channel attacks. On
/// x86-64, this is done pretty well, but not perfectly. On other
/// platforms, it is done less perfectly.
pub fn sign(&mut self, padding_alg: &'static ::signature::RSAEncoding,
rng: &rand::SecureRandom, msg: &[u8], signature: &mut [u8])
-> Result<(), error::Unspecified> {
pub fn sign(
&mut self, padding_alg: &'static ::signature::RSAEncoding, rng: &rand::SecureRandom,
msg: &[u8], signature: &mut [u8],
) -> Result<(), error::Unspecified> {
let mod_bits = self.key_pair.public_key.n_bits;
if signature.len() != mod_bits.as_usize_bytes_rounded_up() {
return Err(error::Unspecified);
@ -491,8 +483,7 @@ impl SigningState {
let n = &key.public_key.n;
// Step 1. The value zero is also rejected.
let base = bigint::Elem::from_be_bytes_padded(
untrusted::Input::from(signature), n)?;
let base = bigint::Elem::from_be_bytes_padded(untrusted::Input::from(signature), n)?;
// Step 2
let c = base;
@ -530,8 +521,7 @@ impl SigningState {
// minimum value, since the relationship of `e` to `d`, `p`, and `q` is
// not verified during `KeyPair` construction.
{
let verify =
bigint::elem_exp_vartime(m.clone(), key.public_key.e, n);
let verify = bigint::elem_exp_vartime(m.clone(), key.public_key.e, n);
let verify = verify.into_unencoded(n);
bigint::elem_verify_equal_consttime(&verify, &c)?;
}
@ -545,7 +535,6 @@ impl SigningState {
}
}
#[cfg(test)]
mod tests {
// We intentionally avoid `use super::*` so that we are sure to use only
@ -568,25 +557,25 @@ mod tests {
let key_bytes_der = untrusted::Input::from(PRIVATE_KEY_DER);
let key_pair = signature::RSAKeyPair::from_der(key_bytes_der).unwrap();
let key_pair = std::sync::Arc::new(key_pair);
let mut signing_state =
signature::RSASigningState::new(key_pair).unwrap();
let mut signing_state = signature::RSASigningState::new(key_pair).unwrap();
// The output buffer is one byte too short.
let mut signature =
vec![0; signing_state.key_pair().public_modulus_len() - 1];
let mut signature = vec![0; signing_state.key_pair().public_modulus_len() - 1];
assert!(signing_state.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE,
&mut signature).is_err());
assert!(signing_state
.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
.is_err());
// The output buffer is the right length.
signature.push(0);
assert!(signing_state.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE,
&mut signature).is_ok());
assert!(signing_state
.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
.is_ok());
// The output buffer is one byte too long.
signature.push(0);
assert!(signing_state.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE,
&mut signature).is_err());
assert!(signing_state
.sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
.is_err());
}
}

View File

@ -12,15 +12,12 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
use super::{bigint, parse_public_key, RSAParameters, N, PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN};
/// RSA PKCS#1 1.5 signatures.
use core;
use crate::{bits, digest, error, private, signature};
use super::{bigint, N, PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN, RSAParameters,
parse_public_key};
use untrusted;
#[derive(Debug)]
pub struct Key {
pub n: bigint::Modulus<N>,
@ -31,9 +28,8 @@ pub struct Key {
impl Key {
pub fn from_modulus_and_exponent(
n: untrusted::Input, e: untrusted::Input, n_min_bits: bits::BitLength,
n_max_bits: bits::BitLength, e_min_value: u64)
-> Result<Self, error::Unspecified>
{
n_max_bits: bits::BitLength, e_min_value: u64,
) -> Result<Self, error::Unspecified> {
// This is an incomplete implementation of NIST SP800-56Br1 Section
// 6.4.2.2, "Partial Public-Key Validation for RSA." That spec defers
// to NIST SP800-89 Section 5.3.3, "(Explicit) Partial Public Key
@ -82,15 +78,13 @@ impl Key {
///
/// A signature has the same length as the public modulus.
#[cfg(feature = "rsa_signing")]
pub fn modulus_len(&self) -> usize {
self.n_bits.as_usize_bytes_rounded_up()
}
pub fn modulus_len(&self) -> usize { self.n_bits.as_usize_bytes_rounded_up() }
}
impl signature::VerificationAlgorithm for RSAParameters {
fn verify(&self, public_key: untrusted::Input, msg: untrusted::Input,
signature: untrusted::Input)
-> Result<(), error::Unspecified> {
fn verify(
&self, public_key: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input,
) -> Result<(), error::Unspecified> {
let public_key = parse_public_key(public_key)?;
verify_rsa(self, public_key, msg, signature)
}
@ -102,16 +96,20 @@ impl core::fmt::Debug for RSAParameters {
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
use super::RSAParametersID::*;
// XXX: This doesn't include the padding algorithm nor the size range.
write!(f, "ring::signature::{}", match self.id {
RSA_PKCS1_2048_8192_SHA1 => "RSA_PKCS1_2048_8192_SHA1",
RSA_PKCS1_2048_8192_SHA256 => "RSA_PKCS1_2048_8192_SHA256",
RSA_PKCS1_2048_8192_SHA384 => "RSA_PKCS1_2048_8192_SHA384",
RSA_PKCS1_2048_8192_SHA512 => "RSA_PKCS1_2048_8192_SHA512",
RSA_PKCS1_3072_8192_SHA384 => "RSA_PKCS1_3072_8192_SHA384",
RSA_PSS_2048_8192_SHA256 => "RSA_PSS_2048_8192_SHA256",
RSA_PSS_2048_8192_SHA384 => "RSA_PSS_2048_8192_SHA384",
RSA_PSS_2048_8192_SHA512 => "RSA_PSS_2048_8192_SHA512",
})
write!(
f,
"ring::signature::{}",
match self.id {
RSA_PKCS1_2048_8192_SHA1 => "RSA_PKCS1_2048_8192_SHA1",
RSA_PKCS1_2048_8192_SHA256 => "RSA_PKCS1_2048_8192_SHA256",
RSA_PKCS1_2048_8192_SHA384 => "RSA_PKCS1_2048_8192_SHA384",
RSA_PKCS1_2048_8192_SHA512 => "RSA_PKCS1_2048_8192_SHA512",
RSA_PKCS1_3072_8192_SHA384 => "RSA_PKCS1_3072_8192_SHA384",
RSA_PSS_2048_8192_SHA256 => "RSA_PSS_2048_8192_SHA256",
RSA_PSS_2048_8192_SHA384 => "RSA_PSS_2048_8192_SHA384",
RSA_PSS_2048_8192_SHA512 => "RSA_PSS_2048_8192_SHA512",
}
)
}
}
@ -121,49 +119,79 @@ macro_rules! rsa_params {
#[doc=$doc_str]
///
/// Only available in `use_heap` mode.
pub static $VERIFY_ALGORITHM: RSAParameters =
RSAParameters {
padding_alg: $PADDING_ALGORITHM,
min_bits: bits::BitLength($min_bits),
id: super::RSAParametersID::$VERIFY_ALGORITHM,
};
}
pub static $VERIFY_ALGORITHM: RSAParameters = RSAParameters {
padding_alg: $PADDING_ALGORITHM,
min_bits: bits::BitLength($min_bits),
id: super::RSAParametersID::$VERIFY_ALGORITHM,
};
};
}
rsa_params!(RSA_PKCS1_2048_8192_SHA1, 2048, &super::padding::RSA_PKCS1_SHA1,
"Verification of signatures using RSA keys of 2048-8192 bits,
rsa_params!(
RSA_PKCS1_2048_8192_SHA1,
2048,
&super::padding::RSA_PKCS1_SHA1,
"Verification of signatures using RSA keys of 2048-8192 bits,
PKCS#1.5 padding, and SHA-1.\n\nSee \"`RSA_PKCS1_*` Details\" in
`ring::signature`'s module-level documentation for more details.");
rsa_params!(RSA_PKCS1_2048_8192_SHA256, 2048, &super::RSA_PKCS1_SHA256,
"Verification of signatures using RSA keys of 2048-8192 bits,
`ring::signature`'s module-level documentation for more details."
);
rsa_params!(
RSA_PKCS1_2048_8192_SHA256,
2048,
&super::RSA_PKCS1_SHA256,
"Verification of signatures using RSA keys of 2048-8192 bits,
PKCS#1.5 padding, and SHA-256.\n\nSee \"`RSA_PKCS1_*` Details\" in
`ring::signature`'s module-level documentation for more details.");
rsa_params!(RSA_PKCS1_2048_8192_SHA384, 2048, &super::RSA_PKCS1_SHA384,
"Verification of signatures using RSA keys of 2048-8192 bits,
`ring::signature`'s module-level documentation for more details."
);
rsa_params!(
RSA_PKCS1_2048_8192_SHA384,
2048,
&super::RSA_PKCS1_SHA384,
"Verification of signatures using RSA keys of 2048-8192 bits,
PKCS#1.5 padding, and SHA-384.\n\nSee \"`RSA_PKCS1_*` Details\" in
`ring::signature`'s module-level documentation for more details.");
rsa_params!(RSA_PKCS1_2048_8192_SHA512, 2048, &super::RSA_PKCS1_SHA512,
"Verification of signatures using RSA keys of 2048-8192 bits,
`ring::signature`'s module-level documentation for more details."
);
rsa_params!(
RSA_PKCS1_2048_8192_SHA512,
2048,
&super::RSA_PKCS1_SHA512,
"Verification of signatures using RSA keys of 2048-8192 bits,
PKCS#1.5 padding, and SHA-512.\n\nSee \"`RSA_PKCS1_*` Details\" in
`ring::signature`'s module-level documentation for more details.");
rsa_params!(RSA_PKCS1_3072_8192_SHA384, 3072, &super::RSA_PKCS1_SHA384,
"Verification of signatures using RSA keys of 3072-8192 bits,
`ring::signature`'s module-level documentation for more details."
);
rsa_params!(
RSA_PKCS1_3072_8192_SHA384,
3072,
&super::RSA_PKCS1_SHA384,
"Verification of signatures using RSA keys of 3072-8192 bits,
PKCS#1.5 padding, and SHA-384.\n\nSee \"`RSA_PKCS1_*` Details\" in
`ring::signature`'s module-level documentation for more details.");
`ring::signature`'s module-level documentation for more details."
);
rsa_params!(RSA_PSS_2048_8192_SHA256, 2048, &super::RSA_PSS_SHA256,
"Verification of signatures using RSA keys of 2048-8192 bits,
rsa_params!(
RSA_PSS_2048_8192_SHA256,
2048,
&super::RSA_PSS_SHA256,
"Verification of signatures using RSA keys of 2048-8192 bits,
PSS padding, and SHA-256.\n\nSee \"`RSA_PSS_*` Details\" in
`ring::signature`'s module-level documentation for more details.");
rsa_params!(RSA_PSS_2048_8192_SHA384, 2048, &super::RSA_PSS_SHA384,
"Verification of signatures using RSA keys of 2048-8192 bits,
`ring::signature`'s module-level documentation for more details."
);
rsa_params!(
RSA_PSS_2048_8192_SHA384,
2048,
&super::RSA_PSS_SHA384,
"Verification of signatures using RSA keys of 2048-8192 bits,
PSS padding, and SHA-384.\n\nSee \"`RSA_PSS_*` Details\" in
`ring::signature`'s module-level documentation for more details.");
rsa_params!(RSA_PSS_2048_8192_SHA512, 2048, &super::RSA_PSS_SHA512,
"Verification of signatures using RSA keys of 2048-8192 bits,
`ring::signature`'s module-level documentation for more details."
);
rsa_params!(
RSA_PSS_2048_8192_SHA512,
2048,
&super::RSA_PSS_SHA512,
"Verification of signatures using RSA keys of 2048-8192 bits,
PSS padding, and SHA-512.\n\nSee \"`RSA_PSS_*` Details\" in
`ring::signature`'s module-level documentation for more details.");
`ring::signature`'s module-level documentation for more details."
);
/// Lower-level API for the verification of RSA signatures.
///
@ -190,19 +218,17 @@ rsa_params!(RSA_PSS_2048_8192_SHA512, 2048, &super::RSA_PSS_SHA512,
// testing `verify_rsa` directly, but the testing work for RSA PKCS#1
// verification was done during the implementation of
// `signature::VerificationAlgorithm`, before `verify_rsa` was factored out).
pub fn verify_rsa(params: &RSAParameters,
(n, e): (untrusted::Input, untrusted::Input),
msg: untrusted::Input, signature: untrusted::Input)
-> Result<(), error::Unspecified> {
let max_bits = bits::BitLength::from_usize_bytes(
PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN)?;
pub fn verify_rsa(
params: &RSAParameters, (n, e): (untrusted::Input, untrusted::Input), msg: untrusted::Input,
signature: untrusted::Input,
) -> Result<(), error::Unspecified> {
let max_bits = bits::BitLength::from_usize_bytes(PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN)?;
// XXX: FIPS 186-4 seems to indicate that the minimum
// exponent value is 2**16 + 1, but it isn't clear if this is just for
// signing or also for verification. We support exponents of 3 and larger
// for compatibility with other commonly-used crypto libraries.
let Key { n, e, n_bits } =
Key::from_modulus_and_exponent(n, e, params.min_bits, max_bits, 3)?;
let Key { n, e, n_bits } = Key::from_modulus_and_exponent(n, e, params.min_bits, max_bits, 3)?;
// The signature must be the same length as the modulus, in bytes.
if signature.len() != n_bits.as_usize_bytes_rounded_up() {
@ -227,8 +253,8 @@ pub fn verify_rsa(params: &RSAParameters,
m.fill_be_bytes(decoded);
// Verify the padded message is correct.
let m_hash = digest::digest(params.padding_alg.digest_alg(),
msg.as_slice_less_safe());
untrusted::Input::from(decoded).read_all(
error::Unspecified, |m| params.padding_alg.verify(&m_hash, m, n_bits))
let m_hash = digest::digest(params.padding_alg.digest_alg(), msg.as_slice_less_safe());
untrusted::Input::from(decoded).read_all(error::Unspecified, |m| {
params.padding_alg.verify(&m_hash, m, n_bits)
})
}