use {bits, c, core, der, error};
use untrusted;
mod padding;
#[cfg(feature = "rsa_signing")]
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
};
const PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN: usize = 8192 / 8;
pub struct RSAParameters {
padding_alg: &'static padding::RSAVerification,
min_bits: usize,
}
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 = try!(der::positive_integer(input));
let e = try!(der::positive_integer(input));
Ok((n, e))
})
})
}
struct PositiveInteger {
value: *mut BIGNUM,
}
impl PositiveInteger {
#[cfg(feature = "rsa_signing")]
fn from_der(input: &mut untrusted::Reader)
-> Result<PositiveInteger, error::Unspecified> {
Self::from_be_bytes(try!(der::positive_integer(input)))
}
fn from_be_bytes(input: untrusted::Input)
-> Result<PositiveInteger, error::Unspecified> {
if input.len() == 0 {
return Err(error::Unspecified);
}
if untrusted::Reader::new(input).peek(0) {
return Err(error::Unspecified);
}
let value = unsafe {
GFp_BN_bin2bn(input.as_slice_less_safe().as_ptr(), input.len(),
core::ptr::null_mut())
};
if value.is_null() {
return Err(error::Unspecified);
}
Ok(PositiveInteger { value: value })
}
unsafe fn as_ref<'a>(&'a self) -> &'a BIGNUM { &*self.value }
#[cfg(feature = "rsa_signing")]
fn into_raw(mut self) -> *mut BIGNUM {
let res = self.value;
self.value = core::ptr::null_mut();
res
}
fn bit_length(&self) -> bits::BitLength {
let bits = unsafe { GFp_BN_num_bits(self.as_ref()) };
bits::BitLength::from_usize_bits(bits)
}
}
impl<'a> Drop for PositiveInteger {
fn drop(&mut self) { unsafe { GFp_BN_free(self.value); } }
}
#[cfg(feature = "rsa_signing")]
#[allow(non_camel_case_types)]
enum BN_MONT_CTX {}
enum BIGNUM {}
pub mod verification;
#[cfg(feature = "rsa_signing")]
pub mod signing;
extern {
fn GFp_BN_bin2bn(in_: *const u8, len: c::size_t, ret: *mut BIGNUM)
-> *mut BIGNUM;
fn GFp_BN_free(bn: *mut BIGNUM);
fn GFp_BN_num_bits(bn: *const BIGNUM) -> c::size_t;
}
#[cfg(feature = "rsa_signing")]
extern {
fn GFp_BN_MONT_CTX_free(mont: *mut BN_MONT_CTX);
}
#[cfg(test)]
mod tests {
use super::PositiveInteger;
use untrusted;
#[test]
fn test_positive_integer_from_be_bytes_empty() {
assert!(PositiveInteger::from_be_bytes(
untrusted::Input::from(&[])).is_err());
}
#[test]
fn test_positive_integer_from_be_bytes_zero() {
assert!(PositiveInteger::from_be_bytes(
untrusted::Input::from(&[0])).is_err());
assert!(PositiveInteger::from_be_bytes(
untrusted::Input::from(&[0, 0])).is_err());
assert!(PositiveInteger::from_be_bytes(
untrusted::Input::from(&[0, 1])).is_err());
assert!(PositiveInteger::from_be_bytes(
untrusted::Input::from(&[1])).is_ok());
assert!(PositiveInteger::from_be_bytes(
untrusted::Input::from(&[1, 0])).is_ok());
}
}