blob: 991db954a17b162eeb3687e1b68d206b12b90947 [file] [log] [blame]
// Copyright 2018 Google LLC
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
//! The RSA public-key cryptosystem.
mod bits;
pub use public::rsa::bits::{RsaKeyBits, B2048, B3072, B4096, B6144, B8192};
use std::convert::TryInto;
use std::fmt::{self, Debug, Display, Formatter};
use std::marker::PhantomData;
use boringssl::{self, BoringError, CHeapWrapper, CStackWrapper};
use hash::{inner::Digest, Hasher};
use public::rsa::inner::RsaKey;
use public::{inner::DerKey, DerPrivateKey, DerPublicKey, PrivateKey, PublicKey, Signature};
use util::Sealed;
use Error;
mod inner {
use std::convert::TryInto;
use std::marker::PhantomData;
use std::os::raw::c_uint;
use boringssl::{self, BoringError, CHeapWrapper, CStackWrapper};
use hash::Hasher;
use public::inner::BoringDerKey;
use public::rsa::RsaKeyBits;
use util::Sealed;
use Error;
// A convenience wrapper around boringssl::RSA.
//
// RsaKey maintains the following invariants:
// - The key is valid.
// - The key has B bits.
//
// This is marked pub and put in this (non-public) module so that using it in impls of
// the Key trait don't result in public-in-private errors.
#[derive(Clone)]
pub struct RsaKey<B: RsaKeyBits> {
pub key: CHeapWrapper<boringssl::RSA>,
_marker: PhantomData<B>,
}
impl<B: RsaKeyBits> RsaKey<B> {
pub fn generate() -> Result<RsaKey<B>, BoringError> {
let mut key = CHeapWrapper::default();
let mut e = CStackWrapper::default();
// BN_set_u64 can only fail due to OOM.
e.bn_set_u64(boringssl::RSA_F4.into()).unwrap();
key.rsa_generate_key_ex(B::BITS.try_into().unwrap(), &e.as_c_ref())?;
Ok(RsaKey { key, _marker: PhantomData })
}
/// Creates an `RsaKey` from a BoringSSL `RSA`.
///
/// `from_RSA` validates that `key` has `B` bits.
#[allow(non_snake_case)]
pub fn from_RSA(key: CHeapWrapper<boringssl::RSA>) -> Result<RsaKey<B>, Error> {
B::validate_bits(key.rsa_bits())?;
Ok(RsaKey { key, _marker: PhantomData })
}
}
impl<B: RsaKeyBits> BoringDerKey for RsaKey<B> {
fn pkey_assign(&self, pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>) {
pkey.evp_pkey_assign_rsa(self.key.clone())
}
fn pkey_get(pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>) -> Result<Self, Error> {
let key = pkey.evp_pkey_get1_rsa()?;
RsaKey::from_RSA(key)
}
fn parse_private_key(cbs: &mut CStackWrapper<boringssl::CBS>) -> Result<RsaKey<B>, Error> {
let key = CHeapWrapper::rsa_parse_private_key(cbs)?;
RsaKey::from_RSA(key)
}
fn marshal_private_key(
&self,
cbb: &mut CStackWrapper<boringssl::CBB>,
) -> Result<(), Error> {
self.key.rsa_marshal_private_key(cbb).map_err(From::from)
}
}
trait RsaKeyBitsExt: RsaKeyBits {
fn validate_bits(bits: c_uint) -> Result<(), Error> {
if <c_uint as TryInto<usize>>::try_into(bits).unwrap() != Self::BITS {
return Err(Error::new(format!(
"unexpected RSA key bit length: got {}; want {}",
bits,
Self::BITS
)));
}
Ok(())
}
}
impl<B: RsaKeyBits> RsaKeyBitsExt for B {}
pub trait RsaSignatureScheme: Sealed {
fn sign<B: RsaKeyBits, H: Hasher>(
rsa: &RsaKey<B>,
digest: &[u8],
sig: &mut [u8],
) -> Result<usize, BoringError>;
fn verify<B: RsaKeyBits, H: Hasher>(rsa: &RsaKey<B>, digest: &[u8], sig: &[u8]) -> bool;
}
#[cfg(test)]
mod tests {
use std::mem;
use super::*;
use public::rsa::tests::generate_rsa_key;
use public::rsa::{B2048, B3072, B4096, B6144, B8192};
#[test]
fn test_refcount() {
// Test that we refcount properly by creating many clones and then
// freeing them all. If we decrement the recount below 0, a test in
// BoringSSL will catch it and crash the program. This test cannot
// currently detect not decrementing the refcount enough (thus
// leaking resources).
//
// TODO(joshlf): Figure out a way to also test that we decrement the
// refcount enough.
fn test<B: RsaKeyBits>() {
let key = generate_rsa_key::<B>().inner;
for i in 0..8 {
// make i clones and then free them all
let mut keys = Vec::new();
for _ in 0..i {
keys.push(key.clone());
}
mem::drop(keys);
}
mem::drop(key);
}
test::<B2048>();
test::<B3072>();
test::<B4096>();
test::<B6144>();
test::<B8192>();
}
}
}
/// A `B`-bit RSA public key.
///
/// `RsaPubKey` is an RSA public key which is `B` bits long.
pub struct RsaPubKey<B: RsaKeyBits> {
inner: RsaKey<B>,
}
impl<B: RsaKeyBits> Sealed for RsaPubKey<B> {}
impl<B: RsaKeyBits> DerPublicKey for RsaPubKey<B> {}
impl<B: RsaKeyBits> DerKey for RsaPubKey<B> {
type Boring = RsaKey<B>;
fn boring(&self) -> &RsaKey<B> {
&self.inner
}
fn from_boring(inner: RsaKey<B>) -> RsaPubKey<B> {
RsaPubKey { inner }
}
}
impl<B: RsaKeyBits> PublicKey for RsaPubKey<B> {
type Private = RsaPrivKey<B>;
}
impl<B: RsaKeyBits> Debug for RsaPubKey<B> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "RsaPubKey")
}
}
/// A `B`-bit RSA private key.
///
/// `RsaPrivKey` is an RSA private key which is `B` bits long.
pub struct RsaPrivKey<B: RsaKeyBits> {
inner: RsaKey<B>,
}
impl<B: RsaKeyBits> RsaPrivKey<B> {
/// Generates a new private key.
#[must_use]
pub fn generate() -> Result<RsaPrivKey<B>, Error> {
Ok(RsaPrivKey { inner: RsaKey::generate()? })
}
}
impl<B: RsaKeyBits> Sealed for RsaPrivKey<B> {}
impl<B: RsaKeyBits> DerPrivateKey for RsaPrivKey<B> {}
impl<B: RsaKeyBits> DerKey for RsaPrivKey<B> {
type Boring = RsaKey<B>;
fn boring(&self) -> &RsaKey<B> {
&self.inner
}
fn from_boring(inner: RsaKey<B>) -> RsaPrivKey<B> {
RsaPrivKey { inner }
}
}
impl<B: RsaKeyBits> PrivateKey for RsaPrivKey<B> {
type Public = RsaPubKey<B>;
fn public(&self) -> RsaPubKey<B> {
RsaPubKey { inner: self.inner.clone() }
}
}
impl<B: RsaKeyBits> Debug for RsaPrivKey<B> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "RsaPrivKey")
}
}
/// An RSA public key whose bit length is unknown at compile time.
///
/// An `RsaPubKeyAnyBits` is an enum of [`RsaPubKey`]s over all supported bit
/// lengths. It is returned from [`RsaPubKeyAnyBits::parse_from_der`].
#[allow(missing_docs)]
#[derive(Debug)]
pub enum RsaPubKeyAnyBits {
B2048(RsaPubKey<B2048>),
B3072(RsaPubKey<B3072>),
B4096(RsaPubKey<B4096>),
B6144(RsaPubKey<B6144>),
B8192(RsaPubKey<B8192>),
}
impl RsaPubKeyAnyBits {
/// Parses a public key in DER format with any bit length.
///
/// `parse_from_der` is like [`DerPublicKey::parse_from_der`], but it
/// accepts any bit length rather than a particular bit length.
///
/// Since [`RsaPubKey`] requires a static [`RsaKeyBits`] type parameter, the
/// `parse_from_der` function on `RsaPubKey`'s `DerPublicKey` implementation
/// can only be called when the bit length is known ahead of time. This
/// function, on the other hand, accepts any bit length.
///
/// [`DerPublicKey::parse_from_der`]: ::public::DerPublicKey::parse_from_der
/// [`PublicKey`]: ::public::PublicKey
#[must_use]
pub fn parse_from_der(bytes: &[u8]) -> Result<RsaPubKeyAnyBits, Error> {
CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
let mut evp_pkey = CHeapWrapper::evp_parse_public_key(cbs)?;
let key = evp_pkey.evp_pkey_get1_rsa()?;
if cbs.cbs_len() > 0 {
return Err(Error::new("excess data provided after valid DER input".to_string()));
}
Ok(match key.rsa_bits().try_into().unwrap() {
B2048::BITS => {
RsaPubKeyAnyBits::B2048(RsaPubKey { inner: RsaKey::from_RSA(key.clone())? })
}
B3072::BITS => {
RsaPubKeyAnyBits::B3072(RsaPubKey { inner: RsaKey::from_RSA(key.clone())? })
}
B4096::BITS => {
RsaPubKeyAnyBits::B4096(RsaPubKey { inner: RsaKey::from_RSA(key.clone())? })
}
B6144::BITS => {
RsaPubKeyAnyBits::B6144(RsaPubKey { inner: RsaKey::from_RSA(key.clone())? })
}
B8192::BITS => {
RsaPubKeyAnyBits::B8192(RsaPubKey { inner: RsaKey::from_RSA(key.clone())? })
}
bits => return Err(Error::new(format!("unsupported bit length: {}", bits))),
})
})
}
}
/// An RSA private key whose bit length is unknown at compile time.
///
/// An `RsaPrivKeyAnyBits` is an enum of [`RsaPrivKey`]s over all supported bit
/// lengths. It is returned from [`RsaPrivKeyAnyBits::parse_from_der`].
#[allow(missing_docs)]
#[derive(Debug)]
pub enum RsaPrivKeyAnyBits {
B2048(RsaPrivKey<B2048>),
B3072(RsaPrivKey<B3072>),
B4096(RsaPrivKey<B4096>),
B6144(RsaPrivKey<B6144>),
B8192(RsaPrivKey<B8192>),
}
impl RsaPrivKeyAnyBits {
/// Gets the public key corresponding to this private key.
#[must_use]
pub fn public(&self) -> RsaPubKeyAnyBits {
match self {
RsaPrivKeyAnyBits::B2048(key) => RsaPubKeyAnyBits::B2048(key.public()),
RsaPrivKeyAnyBits::B3072(key) => RsaPubKeyAnyBits::B3072(key.public()),
RsaPrivKeyAnyBits::B4096(key) => RsaPubKeyAnyBits::B4096(key.public()),
RsaPrivKeyAnyBits::B6144(key) => RsaPubKeyAnyBits::B6144(key.public()),
RsaPrivKeyAnyBits::B8192(key) => RsaPubKeyAnyBits::B8192(key.public()),
}
}
/// Parses a private key in DER format with any bit length.
///
/// `parse_from_der` is like [`DerPrivateKey::parse_from_der`], but it
/// accepts any bit length rather that a particular bit length.
///
/// Since [`RsaPrivKey`] requires a static [`RsaKeyBits`] type parameter,
/// the `parse_from_der` function on `RsaPrivKey`'s `DerPrivateKey`
/// implementation can only be called when the bit length is known ahead of
/// time. This function, on the other hand, accepts any bit length.
///
/// [`DerPrivateKey::parse_from_der`]: ::public::DerPrivateKey::parse_from_der
/// [`PrivateKey`]: ::public::PrivateKey
#[must_use]
pub fn parse_from_der(bytes: &[u8]) -> Result<RsaPrivKeyAnyBits, Error> {
CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
let key = CHeapWrapper::rsa_parse_private_key(cbs)?;
if cbs.cbs_len() > 0 {
return Err(Error::new("excess data provided after valid DER input".to_string()));
}
Ok(match key.rsa_bits().try_into().unwrap() {
B2048::BITS => {
RsaPrivKeyAnyBits::B2048(RsaPrivKey { inner: RsaKey::from_RSA(key.clone())? })
}
B3072::BITS => {
RsaPrivKeyAnyBits::B3072(RsaPrivKey { inner: RsaKey::from_RSA(key.clone())? })
}
B4096::BITS => {
RsaPrivKeyAnyBits::B4096(RsaPrivKey { inner: RsaKey::from_RSA(key.clone())? })
}
B6144::BITS => {
RsaPrivKeyAnyBits::B6144(RsaPrivKey { inner: RsaKey::from_RSA(key.clone())? })
}
B8192::BITS => {
RsaPrivKeyAnyBits::B8192(RsaPrivKey { inner: RsaKey::from_RSA(key.clone())? })
}
bits => return Err(Error::new(format!("unsupported bit length: {}", bits))),
})
})
}
}
/// An RSA signature scheme.
///
/// An `RsaSignatureScheme` defines how to compute an RSA signature. The primary
/// detail defined by a signature scheme is how to perform padding.
///
/// `RsaSignatureScheme` is implemented by [`RsaPss`].
pub trait RsaSignatureScheme:
Sized + Copy + Clone + Default + Display + Debug + self::inner::RsaSignatureScheme
{
}
/// The RSA-PSS signature scheme.
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
pub struct RsaPss;
impl Display for RsaPss {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "RSA-PSS")
}
}
impl Sealed for RsaPss {}
impl RsaSignatureScheme for RsaPss {}
impl self::inner::RsaSignatureScheme for RsaPss {
fn sign<B: RsaKeyBits, H: Hasher>(
rsa: &RsaKey<B>,
digest: &[u8],
sig: &mut [u8],
) -> Result<usize, BoringError> {
// This is not needed for memory safety, but is an important security
// and correctness check, as passing a too-short signature would result
// in the signature being truncated.
assert!(sig.len() >= rsa.key.rsa_size().unwrap().get());
// A salt_len of -1 means to use a salt of the same length as the hash
// output. This is a reasonable default and, for bit lengths larger than
// 2048, ensures that the salt will never need to be truncated.
boringssl::rsa_sign_pss_mgf1(&rsa.key, sig, digest, &H::evp_md(), None, -1)
}
fn verify<B: RsaKeyBits, H: Hasher>(rsa: &RsaKey<B>, digest: &[u8], sig: &[u8]) -> bool {
// A salt_len of -2 means to recover the salt length from the signature,
// and thus to tolerate any salt length.
boringssl::rsa_verify_pss_mgf1(&rsa.key, digest, &H::evp_md(), None, -2, sig)
}
}
// The maximum length of an RSA-8192 signature. Since this isn't exposed in the
// API, we can increase later if we add support for larger bit sizes.
const MAX_SIGNATURE_LEN: usize = 1024;
/// An RSA signature.
///
/// `RsaSignature` is an RSA signature generated by keys of length `B`, using
/// the signature scheme `S`, and the hash function `H`.
pub struct RsaSignature<B: RsaKeyBits, S: RsaSignatureScheme, H: Hasher> {
bytes: [u8; MAX_SIGNATURE_LEN],
// Invariant: len is in [0; MAX_SIGNATURE_LEN). If len is 0, it indicates an
// invalid signature. Invalid signatures can be produced when a caller
// invokes from_bytes with a byte slice longer than MAX_SIGNATURE_LEN. Such
// signatures cannot possibly have been generated by an RSA signature for
// any of the key sizes or signature schemes we support, and so it could not
// possibly be valid. In other words, it would never be correct for
// rsa_verify to return true when invoked on such a signature.
//
// However, if we were to simply truncate the byte slice and store a subset
// of it, then we might open ourselves up to attacks in which an attacker
// induces a mismatch between the signature that the caller /thinks/ is
// being verified and the signature that is /actually/ being verified. Thus,
// it's important that we always reject such signatures.
//
// Finally, it's OK for us to use 0 as the sentinal value to mean "invalid
// signature" because RSA can never produce a 0-byte signature. Thus, we
// will never produce a 0-byte signature from rsa_sign, and similarly, if
// the caller constructs a 0-byte signature using from_bytes, it's correct
// for us to treat it as invalid.
len: usize,
_marker: PhantomData<(B, S, H)>,
}
impl<B: RsaKeyBits, S: RsaSignatureScheme, H: Hasher> RsaSignature<B, S, H> {
/// Constructs an `RsaSignature` from raw bytes.
#[must_use]
pub fn from_bytes(bytes: &[u8]) -> RsaSignature<B, S, H> {
if bytes.len() > MAX_SIGNATURE_LEN {
// see comment on the len field for why we do this
return Self::empty();
}
let mut ret = Self::empty();
(&mut ret.bytes[..bytes.len()]).copy_from_slice(bytes);
ret.len = bytes.len();
ret
}
// TODO(joshlf): Once we have const generics, have this return a
// fixed-length array.
/// Gets the raw bytes of this `RsaSignature`.
#[must_use]
pub fn bytes(&self) -> &[u8] {
&self.bytes[..self.len]
}
fn is_valid_format(&self) -> bool {
self.len != 0
}
fn empty() -> RsaSignature<B, S, H> {
RsaSignature { bytes: [0u8; MAX_SIGNATURE_LEN], len: 0, _marker: PhantomData }
}
}
impl<B: RsaKeyBits, S: RsaSignatureScheme, H: Hasher> Sealed for RsaSignature<B, S, H> {}
impl<B: RsaKeyBits, S: RsaSignatureScheme, H: Hasher> Signature for RsaSignature<B, S, H> {
type PrivateKey = RsaPrivKey<B>;
fn sign(key: &RsaPrivKey<B>, message: &[u8]) -> Result<RsaSignature<B, S, H>, Error> {
let digest = H::hash(message);
let mut sig = RsaSignature::empty();
sig.len = S::sign::<B, H>(&key.inner, digest.as_ref(), &mut sig.bytes[..])?;
Ok(sig)
}
fn is_valid(&self, key: &RsaPubKey<B>, message: &[u8]) -> bool {
if !self.is_valid_format() {
// see comment on RsaSignature::len for why we do this
return false;
}
let digest = H::hash(message);
S::verify::<B, H>(&key.inner, digest.as_ref(), self.bytes())
}
}
impl<B: RsaKeyBits, S: RsaSignatureScheme, H: Hasher> Debug for RsaSignature<B, S, H> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "RsaSignature")
}
}
#[cfg(test)]
mod tests {
use lazy_static::lazy_static;
use super::*;
use hash::Sha256;
use util::should_fail;
// Generating RSA keys is very expensive. In order to make these tests run
// more quickly, we generate a key of a given bit size only once, and then
// re-use that key in subsequent tests.
//
// Since RsaPrivKey doesn't implement Send, we can't store it directly in a
// lazy_static. Instead, we store its DER encoding, and parse in
// generate_rsa_key.
lazy_static! {
static ref B2048_KEY: Vec<u8> = RsaPrivKey::<B2048>::generate().unwrap().marshal_to_der();
static ref B3072_KEY: Vec<u8> = RsaPrivKey::<B3072>::generate().unwrap().marshal_to_der();
static ref B4096_KEY: Vec<u8> = RsaPrivKey::<B4096>::generate().unwrap().marshal_to_der();
static ref B6144_KEY: Vec<u8> = RsaPrivKey::<B6144>::generate().unwrap().marshal_to_der();
static ref B8192_KEY: Vec<u8> = RsaPrivKey::<B8192>::generate().unwrap().marshal_to_der();
}
// also used by inner::tests
pub(super) fn generate_rsa_key<B: RsaKeyBits>() -> RsaPrivKey<B> {
let bytes = match B::BITS {
2048 => B2048_KEY.as_slice(),
3072 => B3072_KEY.as_slice(),
4096 => B4096_KEY.as_slice(),
6144 => B6144_KEY.as_slice(),
8192 => B8192_KEY.as_slice(),
_ => unreachable!(),
};
RsaPrivKey::parse_from_der(bytes).unwrap()
}
#[test]
fn test_generate() {
generate_rsa_key::<B2048>();
generate_rsa_key::<B3072>();
generate_rsa_key::<B4096>();
generate_rsa_key::<B6144>();
generate_rsa_key::<B8192>();
}
#[test]
fn test_marshal_parse() {
// Test various combinations of parsing and serializing keys.
//
// Since we need to test dynamic parsing (the
// parse_private_key_der_any_bits and parse_public_key_der_any_bits
// functions), we need a way of unwrapping their return values into a
// static key type. Unfortunately, there's no way (on stable Rust) to do
// that generically, so the caller must pass a function which will do
// it.
fn test<
B: RsaKeyBits,
F: Fn(RsaPrivKeyAnyBits) -> RsaPrivKey<B>,
G: Fn(RsaPubKeyAnyBits) -> RsaPubKey<B>,
>(
unwrap_priv_any: F,
unwrap_pub_any: G,
) {
const MESSAGE: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7];
let key = generate_rsa_key::<B>();
let parsed_key = RsaPrivKey::<B>::parse_from_der(&key.marshal_to_der()).unwrap();
let parsed_key_any_bits =
unwrap_priv_any(RsaPrivKeyAnyBits::parse_from_der(&key.marshal_to_der()).unwrap());
let pubkey = key.public();
let parsed_pubkey = RsaPubKey::<B>::parse_from_der(&pubkey.marshal_to_der()).unwrap();
let parsed_pubkey_any_bits =
unwrap_pub_any(RsaPubKeyAnyBits::parse_from_der(&pubkey.marshal_to_der()).unwrap());
fn sign_and_verify<B: RsaKeyBits>(privkey: &RsaPrivKey<B>, pubkey: &RsaPubKey<B>) {
let sig = RsaSignature::<B, RsaPss, Sha256>::sign(&privkey, MESSAGE).unwrap();
assert!(RsaSignature::<B, RsaPss, Sha256>::from_bytes(sig.bytes())
.is_valid(&pubkey, MESSAGE));
}
// Sign and verify with every pair of keys to make sure we parsed
// the same key we marshaled.
sign_and_verify(&key, &pubkey);
sign_and_verify(&key, &parsed_pubkey);
sign_and_verify(&key, &parsed_pubkey_any_bits);
sign_and_verify(&parsed_key, &pubkey);
sign_and_verify(&parsed_key, &parsed_pubkey);
sign_and_verify(&parsed_key, &parsed_pubkey_any_bits);
sign_and_verify(&parsed_key_any_bits, &pubkey);
sign_and_verify(&parsed_key_any_bits, &parsed_pubkey);
sign_and_verify(&parsed_key_any_bits, &parsed_pubkey_any_bits);
let _ = RsaPubKey::<B>::marshal_to_der;
let _ = RsaPubKey::<B>::parse_from_der;
}
macro_rules! unwrap_any_bits {
($name:ident, $any_type:ty, $key_type:ty, $bits_variant:path) => {
fn $name(key: $any_type) -> $key_type {
match key {
$bits_variant(key) => key,
_ => panic!("unexpected bits"),
}
}
};
}
unwrap_any_bits!(
unwrap_priv_key_any_2048,
RsaPrivKeyAnyBits,
RsaPrivKey<B2048>,
RsaPrivKeyAnyBits::B2048
);
unwrap_any_bits!(
unwrap_priv_key_any_3072,
RsaPrivKeyAnyBits,
RsaPrivKey<B3072>,
RsaPrivKeyAnyBits::B3072
);
unwrap_any_bits!(
unwrap_priv_key_any_4096,
RsaPrivKeyAnyBits,
RsaPrivKey<B4096>,
RsaPrivKeyAnyBits::B4096
);
unwrap_any_bits!(
unwrap_priv_key_any_6144,
RsaPrivKeyAnyBits,
RsaPrivKey<B6144>,
RsaPrivKeyAnyBits::B6144
);
unwrap_any_bits!(
unwrap_priv_key_any_8192,
RsaPrivKeyAnyBits,
RsaPrivKey<B8192>,
RsaPrivKeyAnyBits::B8192
);
unwrap_any_bits!(
unwrap_pub_key_any_2048,
RsaPubKeyAnyBits,
RsaPubKey<B2048>,
RsaPubKeyAnyBits::B2048
);
unwrap_any_bits!(
unwrap_pub_key_any_3072,
RsaPubKeyAnyBits,
RsaPubKey<B3072>,
RsaPubKeyAnyBits::B3072
);
unwrap_any_bits!(
unwrap_pub_key_any_4096,
RsaPubKeyAnyBits,
RsaPubKey<B4096>,
RsaPubKeyAnyBits::B4096
);
unwrap_any_bits!(
unwrap_pub_key_any_6144,
RsaPubKeyAnyBits,
RsaPubKey<B6144>,
RsaPubKeyAnyBits::B6144
);
unwrap_any_bits!(
unwrap_pub_key_any_8192,
RsaPubKeyAnyBits,
RsaPubKey<B8192>,
RsaPubKeyAnyBits::B8192
);
test::<B2048, _, _>(unwrap_priv_key_any_2048, unwrap_pub_key_any_2048);
test::<B3072, _, _>(unwrap_priv_key_any_3072, unwrap_pub_key_any_3072);
test::<B4096, _, _>(unwrap_priv_key_any_4096, unwrap_pub_key_any_4096);
test::<B6144, _, _>(unwrap_priv_key_any_6144, unwrap_pub_key_any_6144);
test::<B8192, _, _>(unwrap_priv_key_any_8192, unwrap_pub_key_any_8192);
}
#[test]
fn test_parse_fail() {
// Test that invalid input is rejected.
fn test_parse_invalid<B: RsaKeyBits>() {
should_fail(
RsaPrivKey::<B>::parse_from_der(&[]),
"RsaPrivKey::parse_from_der",
"RSA routines:OPENSSL_internal:BAD_ENCODING",
);
should_fail(
RsaPubKey::<B>::parse_from_der(&[]),
"RsaPubKey::parse_from_der",
"public key routines:OPENSSL_internal:DECODE_ERROR",
);
should_fail(
RsaPrivKeyAnyBits::parse_from_der(&[]),
"RsaPrivKeyAnyBits::parse_from_der",
"RSA routines:OPENSSL_internal:BAD_ENCODING",
);
should_fail(
RsaPubKeyAnyBits::parse_from_der(&[]),
"RsaPubKeyAnyBits::parse_from_der",
"public key routines:OPENSSL_internal:DECODE_ERROR",
);
}
test_parse_invalid::<B2048>();
test_parse_invalid::<B3072>();
test_parse_invalid::<B4096>();
test_parse_invalid::<B6144>();
test_parse_invalid::<B8192>();
// Test that, when a particular bit size is expected, other bit sizes are
// rejected.
fn test_parse_wrong_bit_size<B1: RsaKeyBits, B2: RsaKeyBits>() {
let privkey = generate_rsa_key::<B1>();
let key_der = privkey.marshal_to_der();
should_fail(
RsaPrivKey::<B2>::parse_from_der(&key_der),
"RsaPrivKey::parse_from_der",
"unexpected RSA key bit length:",
);
let key_der = privkey.public().marshal_to_der();
should_fail(
RsaPubKey::<B2>::parse_from_der(&key_der),
"RsaPubKey::parse_from_der",
"unexpected RSA key bit length:",
);
}
// All pairs of bit sizes, (X, Y), such that X != Y.
test_parse_wrong_bit_size::<B2048, B3072>();
test_parse_wrong_bit_size::<B2048, B4096>();
test_parse_wrong_bit_size::<B2048, B6144>();
test_parse_wrong_bit_size::<B2048, B8192>();
test_parse_wrong_bit_size::<B3072, B2048>();
test_parse_wrong_bit_size::<B3072, B4096>();
test_parse_wrong_bit_size::<B3072, B6144>();
test_parse_wrong_bit_size::<B3072, B8192>();
test_parse_wrong_bit_size::<B4096, B2048>();
test_parse_wrong_bit_size::<B4096, B3072>();
test_parse_wrong_bit_size::<B4096, B6144>();
test_parse_wrong_bit_size::<B4096, B8192>();
test_parse_wrong_bit_size::<B6144, B2048>();
test_parse_wrong_bit_size::<B6144, B3072>();
test_parse_wrong_bit_size::<B6144, B4096>();
test_parse_wrong_bit_size::<B6144, B8192>();
test_parse_wrong_bit_size::<B8192, B2048>();
test_parse_wrong_bit_size::<B8192, B3072>();
test_parse_wrong_bit_size::<B8192, B4096>();
test_parse_wrong_bit_size::<B8192, B6144>();
}
#[test]
fn test_signature_smoke() {
fn test<B: RsaKeyBits>() {
use public::testutil::test_signature_smoke;
let key = generate_rsa_key::<B>();
test_signature_smoke(
&key,
RsaSignature::<_, RsaPss, Sha256>::from_bytes,
RsaSignature::bytes,
);
}
test::<B2048>();
test::<B3072>();
test::<B4096>();
test::<B6144>();
test::<B8192>();
}
#[test]
fn test_invalid_signature() {
fn test_is_invalid<S: RsaSignatureScheme>(sig: &RsaSignature<B2048, S, Sha256>) {
assert_eq!(sig.len, 0);
assert!(!sig.is_valid_format());
assert!(!sig.is_valid(&generate_rsa_key::<B2048>().public(), &[],));
}
test_is_invalid::<RsaPss>(&RsaSignature::from_bytes(&[0; MAX_SIGNATURE_LEN + 1]));
test_is_invalid::<RsaPss>(&RsaSignature::from_bytes(&[]));
}
}