fix: proper error handling

This commit is contained in:
dignifiedquire 2018-07-24 23:46:58 +02:00
parent 1a6c9a9487
commit 73cbdd7c0d
4 changed files with 58 additions and 49 deletions

View File

@ -1,6 +1,6 @@
use rand::Rng;
use errors::Result;
use errors::{Error, Result};
use key::RSAPrivateKey;
use math::ModInverse;
use num_bigint::BigUint;
@ -27,7 +27,7 @@ pub fn generate_multi_prime_key<R: Rng>(
bit_size: usize,
) -> Result<RSAPrivateKey> {
if nprimes < 2 {
return Err(format_err!("nprimes must be >= 2"));
return Err(Error::NprimesTooSmall);
}
if bit_size < 64 {
@ -40,11 +40,9 @@ pub fn generate_multi_prime_key<R: Rng>(
// Use a factor of two to ensure taht key generation terminates in a
// reasonable amount of time.
pi /= 2f64;
println!("{} < {}", pi, nprimes as f64);
if pi < nprimes as f64 {
return Err(format_err!(
"too few primes of given length to generate an RSA key"
));
return Err(Error::TooFewPrimes);
}
}

View File

@ -1,3 +1,32 @@
use failure::Error;
pub type Result<T> = ::std::result::Result<T, Error>;
/// Error types
#[derive(Debug, Fail)]
pub enum Error {
#[fail(display = "invalid padding scheme")]
InvalidPaddingScheme,
#[fail(display = "decryption error")]
Decryption,
#[fail(display = "verification error")]
Verification,
#[fail(display = "message too long")]
MessageTooLong,
#[fail(display = "input must be hashed")]
InputNotHashed,
#[fail(display = "nprimes must be >= 2")]
NprimesTooSmall,
#[fail(display = "too few primes of given length to generate an RSA key")]
TooFewPrimes,
#[fail(display = "invalid prime value")]
InvalidPrime,
#[fail(display = "invalid modulus")]
InvalidModulus,
#[fail(display = "invalid exponent")]
InvalidExponent,
#[fail(display = "public exponent too small")]
PublicExponentTooSmall,
#[fail(display = "public exponent too large")]
PublicExponentTooLarge,
#[fail(display = "internal error")]
Internal,
}

View File

@ -4,7 +4,7 @@ use num_traits::{FromPrimitive, One, Signed, Zero};
use rand::{Rng, ThreadRng};
use algorithms::generate_multi_prime_key;
use errors::Result;
use errors::{Error, Result};
use hash::Hash;
use math::ModInverse;
use padding::PaddingScheme;
@ -102,10 +102,7 @@ impl RSAPublicKey {
match padding {
PaddingScheme::PKCS1v15 => pkcs1v15::encrypt(rng, self, msg),
PaddingScheme::OAEP => unimplemented!("not yet implemented"),
_ => Err(format_err!(
"invalid padding scheme for decryption: {:?}",
padding
)),
_ => Err(Error::InvalidPaddingScheme),
}
}
@ -123,10 +120,7 @@ impl RSAPublicKey {
match padding {
PaddingScheme::PKCS1v15 => pkcs1v15::verify(self, hash, hashed, sig),
PaddingScheme::PSS => unimplemented!("not yet implemented"),
_ => Err(format_err!(
"invalid padding scheme for decryption: {:?}",
padding
)),
_ => Err(Error::InvalidPaddingScheme),
}
}
}
@ -241,12 +235,12 @@ impl RSAPrivateKey {
for prime in &self.primes {
// Any primes ≤ 1 will cause divide-by-zero panics later.
if prime < &BigUint::one() {
return Err(format_err!("invalid prime value"));
return Err(Error::InvalidPrime);
}
m *= prime;
}
if m != self.n {
return Err(format_err!("invalid modulus"));
return Err(Error::InvalidModulus);
}
// Check that de ≡ 1 mod p-1, for each prime.
@ -259,7 +253,7 @@ impl RSAPrivateKey {
for prime in &self.primes {
let congruence: BigUint = &de % (prime - BigUint::one());
if !congruence.is_one() {
return Err(format_err!("invalid exponents"));
return Err(Error::InvalidExponent);
}
}
@ -272,10 +266,7 @@ impl RSAPrivateKey {
// need to pass any Rng as the type arg, so the type checker is happy, it is not actually used for anything
PaddingScheme::PKCS1v15 => pkcs1v15::decrypt::<ThreadRng>(None, self, ciphertext),
PaddingScheme::OAEP => unimplemented!("not yet implemented"),
_ => Err(format_err!(
"invalid padding scheme for decryption: {:?}",
padding
)),
_ => Err(Error::InvalidPaddingScheme),
}
}
@ -290,10 +281,7 @@ impl RSAPrivateKey {
match padding {
PaddingScheme::PKCS1v15 => pkcs1v15::decrypt(Some(rng), self, ciphertext),
PaddingScheme::OAEP => unimplemented!("not yet implemented"),
_ => Err(format_err!(
"invalid padding scheme for decryption: {:?}",
padding
)),
_ => Err(Error::InvalidPaddingScheme),
}
}
@ -307,10 +295,7 @@ impl RSAPrivateKey {
match padding {
PaddingScheme::PKCS1v15 => pkcs1v15::sign::<ThreadRng, _>(None, self, hash, digest),
PaddingScheme::PSS => unimplemented!("not yet implemented"),
_ => Err(format_err!(
"invalid padding scheme for decryption: {:?}",
padding
)),
_ => Err(Error::InvalidPaddingScheme),
}
}
@ -326,10 +311,7 @@ impl RSAPrivateKey {
match padding {
PaddingScheme::PKCS1v15 => pkcs1v15::sign(Some(rng), self, hash, digest),
PaddingScheme::PSS => unimplemented!("not yet implemented"),
_ => Err(format_err!(
"invalid padding scheme for decryption: {:?}",
padding
)),
_ => Err(Error::InvalidPaddingScheme),
}
}
}
@ -337,11 +319,11 @@ impl RSAPrivateKey {
#[inline]
pub fn check_public(public_key: &impl PublicKey) -> Result<()> {
if public_key.e() < 2 {
return Err(format_err!("public exponent too small"));
return Err(Error::PublicExponentTooSmall);
}
if public_key.e() > 1 << (31 - 1) {
return Err(format_err!("public exponent too large"));
return Err(Error::PublicExponentTooLarge);
}
Ok(())
@ -362,11 +344,11 @@ pub fn decrypt<R: Rng>(
c: &BigUint,
) -> Result<BigUint> {
if c > priv_key.n() {
return Err(format_err!("decryption error"));
return Err(Error::Decryption);
}
if priv_key.n().is_zero() {
return Err(format_err!("decryption error"));
return Err(Error::Decryption);
}
let mut c = c.clone();
@ -456,7 +438,7 @@ pub fn decrypt_and_check<R: Rng>(
// calculated, which should match the original ciphertext.
let check = encrypt(priv_key, &m);
if c != &check {
return Err(format_err!("internal error"));
return Err(Error::Internal);
}
Ok(m)

View File

@ -2,7 +2,7 @@ use num_bigint::BigUint;
use rand::Rng;
use subtle::{Choice, ConditionallyAssignable, ConditionallySelectable, ConstantTimeEq};
use errors::Result;
use errors::{Error, Result};
use hash::Hash;
use key::{self, PublicKey, RSAPrivateKey};
@ -15,7 +15,7 @@ pub fn encrypt<R: Rng, K: PublicKey>(rng: &mut R, pub_key: &K, msg: &[u8]) -> Re
let k = pub_key.size();
if msg.len() > k - 11 {
return Err(format_err!("message too long"));
return Err(Error::MessageTooLong);
}
// EM = 0x00 || 0x02 || PS || 0x00 || M
@ -50,7 +50,7 @@ pub fn decrypt<R: Rng>(
let (valid, out, index) = decrypt_inner(rng, priv_key, ciphertext)?;
if valid == 0 {
return Err(format_err!("decryption error"));
return Err(Error::Decryption);
}
Ok(out[index as usize..].to_vec())
@ -81,7 +81,7 @@ pub fn sign<R: Rng, H: Hash>(
let t_len = prefix.len() + hash_len;
let k = priv_key.size();
if k < t_len + 11 {
return Err(format_err!("message too long"));
return Err(Error::MessageTooLong);
}
// EM = 0x00 || 0x01 || PS || 0x00 || T
@ -113,7 +113,7 @@ pub fn verify<H: Hash, K: PublicKey>(
let t_len = prefix.len() + hash_len;
let k = pub_key.size();
if k < t_len + 11 {
return Err(format_err!("verification error"));
return Err(Error::Verification);
}
let c = BigUint::from_bytes_be(sig);
@ -132,7 +132,7 @@ pub fn verify<H: Hash, K: PublicKey>(
}
if ok.unwrap_u8() != 1 {
return Err(format_err!("verification error"));
return Err(Error::Verification);
}
Ok(())
@ -144,7 +144,7 @@ fn hash_info<H: Hash>(hash: Option<&H>, digest_len: usize) -> Result<(usize, Vec
Some(hash) => {
let hash_len = hash.size();
if digest_len != hash_len {
return Err(format_err!("input must be a hashed messsage"));
return Err(Error::InputNotHashed);
}
Ok((hash_len, hash.asn1_prefix()))
@ -178,7 +178,7 @@ fn decrypt_inner<R: Rng>(
) -> Result<(u8, Vec<u8>, u32)> {
let k = priv_key.size();
if k < 11 {
return Err(format_err!("decryption error"));
return Err(Error::Decryption);
}
let c = BigUint::from_bytes_be(ciphertext);