#[cfg(not(feature = "std"))]
use crate::alloc_prelude::*;
use mbedtls_sys::*;
use mbedtls_sys::types::raw_types::c_void;
use crate::error::{Error, IntoResult, Result};
use crate::hash::Type as MdType;
use crate::private::UnsafeFrom;
use crate::rng::Random;
use core::convert::TryInto;
use core::ops::Sub;
use core::ptr;
use byteorder::{BigEndian, ByteOrder};
pub(crate) mod dhparam;
mod ec;
mod rfc6979;
use self::rfc6979::Rfc6979Rng;
use crate::bignum::Mpi;
use crate::ecp::EcPoint;
#[cfg(feature = "dsa")]
pub mod dsa;
#[doc(inline)]
pub use self::ec::{EcGroupId, ECDSA_MAX_LEN};
#[doc(inline)]
pub use crate::ecp::EcGroup;
pub use dhparam::Dhm;
const CUSTOM_PK_TYPE: pk_type_t = 0x8b205408u32 as pk_type_t;
const RAW_RSA_DECRYPT: i32 = 1040451858;
define!(
#[c_ty(pk_type_t)]
#[derive(Copy, Clone, PartialEq, Debug)]
enum Type {
None = PK_NONE,
Rsa = PK_RSA,
Eckey = PK_ECKEY,
EckeyDh = PK_ECKEY_DH,
Ecdsa = PK_ECDSA,
RsaAlt = PK_RSA_ALT,
RsassaPss = PK_RSASSA_PSS,
Custom = CUSTOM_PK_TYPE,
}
);
impl From<pk_type_t> for Type {
fn from(inner: pk_type_t) -> Type {
match inner {
PK_NONE => Type::None,
PK_RSA => Type::Rsa,
PK_ECKEY => Type::Eckey,
PK_ECKEY_DH => Type::EckeyDh,
PK_ECDSA => Type::Ecdsa,
PK_RSA_ALT => Type::RsaAlt,
PK_RSASSA_PSS => Type::RsassaPss,
CUSTOM_PK_TYPE => Type::Custom,
_ => panic!("Invalid PK type"),
}
}
}
pub enum RsaPadding {
Pkcs1V15,
Pkcs1V21 {
mgf: MdType,
},
None,
}
pub enum Options {
Rsa { padding: RsaPadding },
}
struct CustomPkContext {
pub algo_id: Vec<u64>,
pub pk: Vec<u8>,
pub sk: Vec<u8>,
}
impl CustomPkContext {
fn new() -> CustomPkContext {
CustomPkContext {
algo_id: Vec::new(),
pk: Vec::new(),
sk: Vec::new(),
}
}
}
extern "C" fn alloc_custom_pk_ctx() -> *mut c_void {
let boxed = Box::new(CustomPkContext::new());
Box::into_raw(boxed) as *mut c_void
}
unsafe extern "C" fn free_custom_pk_ctx(p: *mut c_void) {
let _ = Box::from_raw(p as *mut CustomPkContext);
}
unsafe extern "C" fn custom_pk_can_do(_t: pk_type_t) -> types::raw_types::c_int {
0
}
const CUSTOM_PK_INFO: pk_info_t = {
pk_info_t {
type_: CUSTOM_PK_TYPE,
can_do: Some(custom_pk_can_do),
check_pair_func: None,
debug_func: None,
encrypt_func: None,
decrypt_func: None,
sign_func: None,
verify_func: None,
get_bitlen: None,
name: b"\0" as *const u8 as *const _,
ctx_alloc_func: Some(alloc_custom_pk_ctx),
ctx_free_func: Some(free_custom_pk_ctx),
}
};
pub enum RsaPrivateComponents<'a> {
WithPrimes {
p: &'a Mpi,
q: &'a Mpi,
e: &'a Mpi,
},
WithPrivateExponent {
n: &'a Mpi,
d: &'a Mpi,
e: &'a Mpi,
},
}
pub struct RsaPublicComponents<'a> {
pub n: &'a Mpi,
pub e: &'a Mpi,
}
define!(
#[c_ty(pk_context)]
#[repr(C)]
struct Pk;
const init: fn() -> Self = pk_init;
const drop: fn(&mut Self) = pk_free;
impl<'a> Into<ptr> {}
impl<'a> UnsafeFrom<ptr> {}
);
unsafe impl Sync for Pk {}
impl Pk {
pub fn from_private_key(key: &[u8], password: Option<&[u8]>) -> Result<Pk> {
let mut ret = Self::init();
unsafe {
pk_parse_key(
&mut ret.inner,
key.as_ptr(),
key.len(),
password.map(<[_]>::as_ptr).unwrap_or(::core::ptr::null()),
password.map(<[_]>::len).unwrap_or(0),
)
.into_result()?;
};
Ok(ret)
}
pub fn from_public_key(key: &[u8]) -> Result<Pk> {
let mut ret = Self::init();
unsafe { pk_parse_public_key(&mut ret.inner, key.as_ptr(), key.len()).into_result()? };
Ok(ret)
}
pub fn generate_rsa<F: Random>(rng: &mut F, bits: u32, exponent: u32) -> Result<Pk> {
let mut ret = Self::init();
unsafe {
pk_setup(&mut ret.inner, pk_info_from_type(Type::Rsa.into())).into_result()?;
rsa_gen_key(ret.inner.pk_ctx as *mut _, Some(F::call), rng.data_ptr(), bits, exponent as _).into_result()?;
}
Ok(ret)
}
pub fn generate_ec<F: Random, C: TryInto<EcGroup, Error = impl Into<Error>>>(rng: &mut F, curve: C) -> Result<Pk> {
let mut ret = Self::init();
unsafe {
let curve: EcGroup = curve.try_into().map_err(|e| e.into())?;
pk_setup(&mut ret.inner, pk_info_from_type(Type::Eckey.into())).into_result()?;
let ctx = ret.inner.pk_ctx as *mut ecp_keypair;
(*ctx).grp = curve.clone().into_inner();
ecp_gen_keypair(&mut (*ctx).grp, &mut (*ctx).d, &mut (*ctx).Q, Some(F::call), rng.data_ptr()).into_result()?;
}
Ok(ret)
}
#[deprecated(
since = "0.12.3",
note = "This function does not accept an RNG so it's vulnerable to side channel attacks.
Please use `private_from_ec_scalar_with_rng` instead."
)]
pub fn private_from_ec_components(mut curve: EcGroup, private_key: Mpi) -> Result<Pk> {
let mut ret = Self::init();
let curve_generator = curve.generator()?;
#[allow(deprecated)]
let public_point = curve_generator.mul(&mut curve, &private_key)?;
unsafe {
pk_setup(&mut ret.inner, pk_info_from_type(Type::Eckey.into())).into_result()?;
let ctx = ret.inner.pk_ctx as *mut ecp_keypair;
(*ctx).grp = curve.into_inner();
(*ctx).d = private_key.into_inner();
(*ctx).Q = public_point.into_inner();
}
Ok(ret)
}
pub fn private_from_ec_scalar_with_rng<F: Random>(mut curve: EcGroup, private_key: Mpi, rng: &mut F) -> Result<Pk> {
let mut ret = Self::init();
let curve_generator = curve.generator()?;
let public_point = curve_generator.mul_with_rng(&mut curve, &private_key, rng)?;
unsafe {
pk_setup(&mut ret.inner, pk_info_from_type(Type::Eckey.into())).into_result()?;
let ctx = ret.inner.pk_ctx as *mut ecp_keypair;
(*ctx).grp = curve.into_inner();
(*ctx).d = private_key.into_inner();
(*ctx).Q = public_point.into_inner();
}
Ok(ret)
}
pub fn public_from_ec_components(curve: EcGroup, public_point: EcPoint) -> Result<Pk> {
let mut ret = Self::init();
unsafe {
pk_setup(&mut ret.inner, pk_info_from_type(Type::Eckey.into())).into_result()?;
let ctx = ret.inner.pk_ctx as *mut ecp_keypair;
(*ctx).grp = curve.into_inner();
(*ctx).Q = public_point.into_inner();
}
Ok(ret)
}
pub fn private_from_rsa_components(components: RsaPrivateComponents<'_>) -> Result<Pk> {
let mut ret = Self::init();
let (n, p, q, d, e) = match components {
RsaPrivateComponents::WithPrimes { p, q, e } => (None, Some(p), Some(q), None, Some(e)),
RsaPrivateComponents::WithPrivateExponent { n, d, e } => (Some(n), None, None, Some(d), Some(e)),
};
let to_ptr = |mpi: Option<&Mpi>| match mpi {
None => ptr::null(),
Some(mpi) => mpi.handle(),
};
unsafe {
pk_setup(&mut ret.inner, pk_info_from_type(Type::Rsa.into())).into_result()?;
let ctx = ret.inner.pk_ctx as *mut rsa_context;
rsa_import(ctx, to_ptr(n), to_ptr(p), to_ptr(q), to_ptr(d), to_ptr(e)).into_result()?;
rsa_complete(ctx).into_result()?;
rsa_check_privkey(ctx).into_result()?;
}
Ok(ret)
}
pub fn public_from_rsa_components(components: RsaPublicComponents<'_>) -> Result<Pk> {
let mut ret = Self::init();
let RsaPublicComponents { n, e } = components;
unsafe {
pk_setup(&mut ret.inner, pk_info_from_type(Type::Rsa.into())).into_result()?;
let ctx = ret.inner.pk_ctx as *mut rsa_context;
rsa_import(ctx, n.handle(), ptr::null(), ptr::null(), ptr::null(), e.handle()).into_result()?;
rsa_complete(ctx).into_result()?;
}
Ok(ret)
}
pub fn public_custom_algo(algo_id: &[u64], pk: &[u8]) -> Result<Pk> {
let mut ret = Self::init();
unsafe {
pk_setup(&mut ret.inner, &CUSTOM_PK_INFO).into_result()?;
let ctx = ret.inner.pk_ctx as *mut CustomPkContext;
(*ctx).algo_id = algo_id.to_owned();
(*ctx).pk = pk.to_owned();
}
Ok(ret)
}
pub fn private_custom_algo(algo_id: &[u64], pk: &[u8], sk: &[u8]) -> Result<Pk> {
let mut ret = Self::init();
unsafe {
pk_setup(&mut ret.inner, &CUSTOM_PK_INFO).into_result()?;
let ctx = ret.inner.pk_ctx as *mut CustomPkContext;
(*ctx).algo_id = algo_id.to_owned();
(*ctx).pk = pk.to_owned();
(*ctx).sk = sk.to_owned();
}
Ok(ret)
}
pub fn custom_algo_id(&self) -> Result<&[u64]> {
if self.pk_type() != Type::Custom {
return Err(Error::PkInvalidAlg);
}
unsafe {
let ctx = self.inner.pk_ctx as *const CustomPkContext;
Ok(&(*ctx).algo_id)
}
}
pub fn custom_public_key(&self) -> Result<&[u8]> {
if self.pk_type() != Type::Custom {
return Err(Error::PkInvalidAlg);
}
let ctx = self.inner.pk_ctx as *const CustomPkContext;
unsafe { Ok(&(*ctx).pk) }
}
pub fn custom_private_key(&self) -> Result<&[u8]> {
if self.pk_type() != Type::Custom {
return Err(Error::PkInvalidAlg);
}
let ctx = self.inner.pk_ctx as *const CustomPkContext;
unsafe {
if (*ctx).sk.len() == 0 {
return Err(Error::PkTypeMismatch);
}
Ok(&(*ctx).sk)
}
}
pub fn set_options(&mut self, options: Options) {
unsafe {
match (Type::from(pk_get_type(&self.inner)), options) {
(Type::Rsa, Options::Rsa { padding }) | (Type::RsassaPss, Options::Rsa { padding }) => {
let (padding, hash_id) = match padding {
RsaPadding::Pkcs1V15 => (RSA_PKCS_V15, 0),
RsaPadding::Pkcs1V21 { mgf } => (RSA_PKCS_V21, mgf.into()),
RsaPadding::None => {
let ctx = self.inner.pk_ctx as *mut rsa_context;
(*ctx).padding = RAW_RSA_DECRYPT; return;
}
};
rsa_set_padding(self.inner.pk_ctx as *mut rsa_context, padding, hash_id as _);
}
_ => panic!("Invalid options for this key type"),
}
}
}
pub fn can_do(&self, t: Type) -> bool {
if unsafe { pk_can_do(&self.inner, t.into()) } == 0 {
false
} else {
true
}
}
pub fn check_pair(public: &Self, private: &Self) -> bool {
unsafe { pk_check_pair(&public.inner, &private.inner) }.into_result().is_ok()
}
getter!(
len() -> usize = fn pk_get_bitlen
);
getter!(pk_type() -> Type = fn pk_get_type);
pub fn curve(&self) -> Result<EcGroupId> {
match self.pk_type() {
Type::Eckey | Type::EckeyDh | Type::Ecdsa => {}
_ => return Err(Error::PkTypeMismatch),
}
unsafe { Ok((*(self.inner.pk_ctx as *const ecp_keypair)).grp.id.into()) }
}
pub fn curve_oid(&self) -> Result<Vec<u64>> {
match self.curve()? {
EcGroupId::Bp256R1 => Ok(vec![1, 3, 36, 3, 3, 2, 8, 1, 1, 7]),
EcGroupId::Bp384R1 => Ok(vec![1, 3, 36, 3, 3, 2, 8, 1, 1, 11]),
EcGroupId::Bp512R1 => Ok(vec![1, 3, 36, 3, 3, 2, 8, 1, 1, 13]),
EcGroupId::SecP192K1 => Ok(vec![1, 3, 132, 0, 31]),
EcGroupId::SecP192R1 => Ok(vec![1, 2, 840, 10045, 3, 1, 1]),
EcGroupId::SecP224K1 => Ok(vec![1, 3, 132, 0, 32]),
EcGroupId::SecP224R1 => Ok(vec![1, 3, 132, 0, 33]),
EcGroupId::SecP256K1 => Ok(vec![1, 3, 132, 0, 10]),
EcGroupId::SecP256R1 => Ok(vec![1, 2, 840, 10045, 3, 1, 7]),
EcGroupId::SecP384R1 => Ok(vec![1, 3, 132, 0, 34]),
EcGroupId::SecP521R1 => Ok(vec![1, 3, 132, 0, 35]),
_ => Err(Error::OidNotFound),
}
}
pub fn ec_group(&self) -> Result<EcGroup> {
match self.pk_type() {
Type::Eckey | Type::EckeyDh | Type::Ecdsa => {}
_ => return Err(Error::PkTypeMismatch),
}
match self.curve()? {
EcGroupId::None => {
unsafe {
let ecp = self.inner.pk_ctx as *const ecp_keypair;
let p = Mpi::copy(&(*ecp).grp.P)?;
let a = Mpi::copy(&(*ecp).grp.A)?;
let b = Mpi::copy(&(*ecp).grp.B)?;
let n = Mpi::copy(&(*ecp).grp.N)?;
let g_x = Mpi::copy(&(*ecp).grp.G.X)?;
let g_y = Mpi::copy(&(*ecp).grp.G.Y)?;
EcGroup::from_parameters(p, a, b, g_x, g_y, n)
}
}
curve_id => EcGroup::new(curve_id),
}
}
pub fn ec_public(&self) -> Result<EcPoint> {
match self.pk_type() {
Type::Eckey | Type::EckeyDh | Type::Ecdsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let q = &unsafe { (*(self.inner.pk_ctx as *const ecp_keypair)).Q };
EcPoint::copy(q)
}
pub fn ec_private(&self) -> Result<Mpi> {
match self.pk_type() {
Type::Eckey | Type::EckeyDh | Type::Ecdsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let d = &unsafe { (*(self.inner.pk_ctx as *const ecp_keypair)).d };
Mpi::copy(d)
}
pub fn rsa_public_modulus(&self) -> Result<Mpi> {
match self.pk_type() {
Type::Rsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let mut n = Mpi::new(0)?;
unsafe {
rsa_export(
self.inner.pk_ctx as *const rsa_context,
n.handle_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
.into_result()?;
}
Ok(n)
}
pub fn rsa_private_prime1(&self) -> Result<Mpi> {
match self.pk_type() {
Type::Rsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let mut p = Mpi::new(0)?;
unsafe {
rsa_export(
self.inner.pk_ctx as *const rsa_context,
ptr::null_mut(),
p.handle_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
.into_result()?;
}
Ok(p)
}
pub fn rsa_private_prime2(&self) -> Result<Mpi> {
match self.pk_type() {
Type::Rsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let mut q = Mpi::new(0)?;
unsafe {
rsa_export(
self.inner.pk_ctx as *const rsa_context,
ptr::null_mut(),
ptr::null_mut(),
q.handle_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
.into_result()?;
}
Ok(q)
}
pub fn rsa_private_exponent(&self) -> Result<Mpi> {
match self.pk_type() {
Type::Rsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let mut d = Mpi::new(0)?;
unsafe {
rsa_export(
self.inner.pk_ctx as *const rsa_context,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
d.handle_mut(),
ptr::null_mut(),
)
.into_result()?;
}
Ok(d)
}
pub fn rsa_crt_dp(&self) -> Result<Mpi> {
match self.pk_type() {
Type::Rsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let mut dp = Mpi::new(0)?;
unsafe {
rsa_export_crt(
self.inner.pk_ctx as *const rsa_context,
dp.handle_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
.into_result()?;
}
Ok(dp)
}
pub fn rsa_crt_dq(&self) -> Result<Mpi> {
match self.pk_type() {
Type::Rsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let mut dq = Mpi::new(0)?;
unsafe {
rsa_export_crt(
self.inner.pk_ctx as *const rsa_context,
ptr::null_mut(),
dq.handle_mut(),
ptr::null_mut(),
)
.into_result()?;
}
Ok(dq)
}
pub fn rsa_crt_qp(&self) -> Result<Mpi> {
match self.pk_type() {
Type::Rsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let mut qp = Mpi::new(0)?;
unsafe {
rsa_export_crt(
self.inner.pk_ctx as *const rsa_context,
ptr::null_mut(),
ptr::null_mut(),
qp.handle_mut(),
)
.into_result()?;
}
Ok(qp)
}
pub fn rsa_public_exponent(&self) -> Result<u32> {
match self.pk_type() {
Type::Rsa => {}
_ => return Err(Error::PkTypeMismatch),
}
let mut e: [u8; 4] = [0, 0, 0, 0];
unsafe {
rsa_export_raw(
self.inner.pk_ctx as *const rsa_context,
ptr::null_mut(),
0,
ptr::null_mut(),
0,
ptr::null_mut(),
0,
ptr::null_mut(),
0,
e.as_mut_ptr(),
e.len(),
)
.into_result()?;
}
Ok(BigEndian::read_u32(&e))
}
pub fn name(&self) -> Result<&str> {
let s = unsafe { crate::private::cstr_to_slice(pk_get_name(&self.inner)) };
Ok(::core::str::from_utf8(s)?)
}
pub fn decrypt<F: Random>(&mut self, cipher: &[u8], plain: &mut [u8], rng: &mut F) -> Result<usize> {
if self.pk_type() == Type::Rsa {
let ctx = self.inner.pk_ctx as *mut rsa_context;
if unsafe { (*ctx).padding == RAW_RSA_DECRYPT } {
let olen = self.len() / 8;
if plain.len() < olen {
return Err(Error::RsaOutputTooLarge);
}
let nm1 = self.rsa_public_modulus()?.sub(&Mpi::new(1)?)?;
let c_mpi = Mpi::from_binary(cipher)?;
if c_mpi <= Mpi::new(1).unwrap() || c_mpi >= nm1 {
return Err(Error::MpiBadInputData);
}
unsafe {
rsa_private(ctx, Some(F::call), rng.data_ptr(), cipher.as_ptr(), plain.as_mut_ptr()).into_result()?;
};
return Ok(olen);
}
}
let mut ret = 0usize;
unsafe {
pk_decrypt(
&mut self.inner,
cipher.as_ptr(),
cipher.len(),
plain.as_mut_ptr(),
&mut ret,
plain.len(),
Some(F::call),
rng.data_ptr(),
)
.into_result()?;
};
Ok(ret)
}
pub fn decrypt_with_label<F: Random>(
&mut self,
cipher: &[u8],
plain: &mut [u8],
rng: &mut F,
label: &[u8],
) -> Result<usize> {
if self.pk_type() != Type::Rsa {
return Err(Error::PkTypeMismatch);
}
let ctx = self.inner.pk_ctx as *mut rsa_context;
if unsafe { (*ctx).padding != RSA_PKCS_V21 } {
return Err(Error::RsaInvalidPadding);
}
let mut ret = 0usize;
unsafe {
rsa_rsaes_oaep_decrypt(
ctx,
Some(F::call),
rng.data_ptr(),
RSA_PRIVATE,
label.as_ptr(),
label.len(),
&mut ret,
cipher.as_ptr(),
plain.as_mut_ptr(),
plain.len(),
)
.into_result()?;
}
Ok(ret)
}
pub fn encrypt<F: Random>(&mut self, plain: &[u8], cipher: &mut [u8], rng: &mut F) -> Result<usize> {
let mut ret = 0usize;
unsafe {
pk_encrypt(
&mut self.inner,
plain.as_ptr(),
plain.len(),
cipher.as_mut_ptr(),
&mut ret,
cipher.len(),
Some(F::call),
rng.data_ptr(),
)
.into_result()?;
};
Ok(ret)
}
pub fn encrypt_with_label<F: Random>(
&mut self,
plain: &[u8],
cipher: &mut [u8],
rng: &mut F,
label: &[u8],
) -> Result<usize> {
if self.pk_type() != Type::Rsa {
return Err(Error::PkTypeMismatch);
}
let ctx = self.inner.pk_ctx as *mut rsa_context;
if unsafe { (*ctx).padding != RSA_PKCS_V21 } {
return Err(Error::RsaInvalidPadding);
}
let olen = self.len() / 8;
if cipher.len() < olen {
return Err(Error::RsaOutputTooLarge);
}
unsafe {
rsa_rsaes_oaep_encrypt(
ctx,
Some(F::call),
rng.data_ptr(),
RSA_PUBLIC,
label.as_ptr(),
label.len(),
plain.len(),
plain.as_ptr(),
cipher.as_mut_ptr(),
)
.into_result()?;
}
Ok(olen)
}
pub fn sign<F: Random>(&mut self, md: MdType, hash: &[u8], sig: &mut [u8], rng: &mut F) -> Result<usize> {
if hash.len() == 0 || sig.len() == 0 {
return Err(Error::PkBadInputData);
}
match self.pk_type() {
Type::Rsa | Type::RsaAlt | Type::RsassaPss => {
if sig.len() < (self.len() / 8) {
return Err(Error::PkSigLenMismatch);
}
}
Type::Eckey | Type::Ecdsa => {
if sig.len() < ECDSA_MAX_LEN {
return Err(Error::PkSigLenMismatch);
}
}
_ => return Err(Error::PkSigLenMismatch),
}
let mut ret = 0usize;
unsafe {
pk_sign(
&mut self.inner,
md.into(),
hash.as_ptr(),
hash.len(),
sig.as_mut_ptr(),
&mut ret,
Some(F::call),
rng.data_ptr(),
)
.into_result()?;
};
Ok(ret)
}
pub fn sign_deterministic<F: Random>(&mut self, md: MdType, hash: &[u8], sig: &mut [u8], rng: &mut F) -> Result<usize> {
if hash.len() == 0 || sig.len() == 0 {
return Err(Error::PkBadInputData);
}
use crate::rng::RngCallbackMut;
if self.pk_type() == Type::Ecdsa || self.pk_type() == Type::Eckey {
if sig.len() < ECDSA_MAX_LEN {
return Err(Error::PkSigLenMismatch);
}
let q = EcGroup::new(self.curve()?)?.order()?;
let x = self.ec_private()?;
let mut random_seed = [0u8; 64];
rng.random(&mut random_seed)?;
let mut rng = Rfc6979Rng::new(md, &q, &x, hash, &random_seed)?;
let mut ret = 0usize;
unsafe {
pk_sign(
&mut self.inner,
md.into(),
hash.as_ptr(),
hash.len(),
sig.as_mut_ptr(),
&mut ret,
Some(Rfc6979Rng::call_mut),
rng.data_ptr_mut(),
)
.into_result()?;
};
Ok(ret)
} else if self.pk_type() == Type::Rsa {
if unsafe { (*(self.inner.pk_ctx as *mut rsa_context)).padding } != RSA_PKCS_V15 {
return Err(Error::PkInvalidAlg);
}
return self.sign(md, hash, sig, rng);
} else {
return Err(Error::PkInvalidAlg);
}
}
pub fn verify(&mut self, md: MdType, hash: &[u8], sig: &[u8]) -> Result<()> {
if hash.len() == 0 || sig.len() == 0 {
return Err(Error::PkBadInputData);
}
unsafe {
pk_verify(&mut self.inner, md.into(), hash.as_ptr(), hash.len(), sig.as_ptr(), sig.len())
.into_result()
.map(|_| ())
}
}
pub fn agree<F: Random>(&mut self, other: &Pk, shared: &mut [u8], rng: &mut F) -> Result<usize> {
match (self.pk_type(), other.pk_type()) {
(Type::Eckey, Type::Eckey)
| (Type::EckeyDh, Type::Eckey)
| (Type::Eckey, Type::EckeyDh)
| (Type::EckeyDh, Type::EckeyDh) => unsafe {
let mut ecdh = ec::Ecdh::from_keys(
UnsafeFrom::from(self.inner.pk_ctx as *const _).unwrap(),
UnsafeFrom::from(other.inner.pk_ctx as *const _).unwrap(),
)?;
ecdh.calc_secret(shared, rng)
},
_ => return Err(Error::PkTypeMismatch),
}
}
pub fn write_private_der<'buf>(&mut self, buf: &'buf mut [u8]) -> Result<Option<&'buf [u8]>> {
match unsafe { pk_write_key_der(&mut self.inner, buf.as_mut_ptr(), buf.len()).into_result() } {
Err(Error::Asn1BufTooSmall) => Ok(None),
Err(e) => Err(e),
Ok(n) => Ok(Some(&buf[buf.len() - (n as usize)..])),
}
}
pub fn write_private_der_vec(&mut self) -> Result<Vec<u8>> {
crate::private::alloc_vec_repeat(|buf, size| unsafe { pk_write_key_der(&mut self.inner, buf, size) }, true)
}
pub fn write_private_pem<'buf>(&mut self, buf: &'buf mut [u8]) -> Result<Option<&'buf [u8]>> {
match unsafe { pk_write_key_pem(&mut self.inner, buf.as_mut_ptr(), buf.len()).into_result() } {
Err(Error::Base64BufferTooSmall) => Ok(None),
Err(e) => Err(e),
Ok(n) => Ok(Some(&buf[buf.len() - (n as usize)..])),
}
}
pub fn write_private_pem_string(&mut self) -> Result<String> {
crate::private::alloc_string_repeat(|buf, size| unsafe {
match pk_write_key_pem(&mut self.inner, buf as _, size) {
0 => crate::private::cstr_to_slice(buf as _).len() as _,
r => r,
}
})
}
pub fn write_public_der<'buf>(&mut self, buf: &'buf mut [u8]) -> Result<Option<&'buf [u8]>> {
match unsafe { pk_write_pubkey_der(&mut self.inner, buf.as_mut_ptr(), buf.len()).into_result() } {
Err(Error::Asn1BufTooSmall) => Ok(None),
Err(e) => Err(e),
Ok(n) => Ok(Some(&buf[buf.len() - (n as usize)..])),
}
}
pub fn write_public_der_vec(&mut self) -> Result<Vec<u8>> {
crate::private::alloc_vec_repeat(|buf, size| unsafe { pk_write_pubkey_der(&mut self.inner, buf, size) }, true)
}
pub fn write_public_pem<'buf>(&mut self, buf: &'buf mut [u8]) -> Result<Option<&'buf [u8]>> {
match unsafe { pk_write_pubkey_pem(&mut self.inner, buf.as_mut_ptr(), buf.len()).into_result() } {
Err(Error::Base64BufferTooSmall) => Ok(None),
Err(e) => Err(e),
Ok(n) => Ok(Some(&buf[buf.len() - (n as usize)..])),
}
}
pub fn write_public_pem_string(&mut self) -> Result<String> {
crate::private::alloc_string_repeat(|buf, size| unsafe {
match pk_write_pubkey_pem(&mut self.inner, buf as _, size) {
0 => crate::private::cstr_to_slice(buf as _).len() as _,
r => r,
}
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::hash::{MdInfo, Type};
use crate::pk::Type as PkType;
use core::ops::Sub;
const TEST_PEM: &'static str = "-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAh1aoz6wFwVHaCVDISSy+dZ8rOsJmfYBCrgzUjX+VNb2RwdT8
xv5fF0j0IXq+fKBShdZA+WGEQd6BMU0fqc2o7ACLvPWbvdKrLcwWpnL/UpFV8PxJ
yLemR8CBkGYcN2EJHhRhZcAGMBKwR1lI+ymOPJz4+nyDWVh9ttrvkKZU9b59zDkP
ET6PDJb5x9+fd41laQVOLvwlF4Xrl0b0DakXF3BVYpJIJ+b51QnMnwQ2xHVybFlZ
ONBwv1h52Xy7chvx79zPXzxZFbEc0phIhRqenv0/6/8HxpqqctSs9HHUn5A+4d/o
955ki8ZB1Nl5EuY+S59HzdsnQXR+OZxt3PxjTQIDAQABAoIBAANfW3UaPdfOTFqh
S5jXNbUhFgp3sa2ufaWMraHvQYPwM9Vo6KSIXGleIZV7/jVo0x6BVry1e2ICmMGR
FjWSIqAkPuVp36DD+9QGU+zVBan9SSgTD5SFh+4dzNWfOVRVSSJu+c13hKG70e5/
5KLKDvmKXSye/Ftg8VuysWmS6bxolGm86b+tltQ95V2qgim41MpaOUzilf1sDc5A
3hnorZvxH+kbMSGTRBdlPX54dux0SlT+o7sh9ig2sPJKkevnHeWd6nEeyeVYzP05
vH5yXirYb1CttPb5tqLcNCKRgawR5ByMMycn8bRSHScxyCLKco++JWL7L8hmcFTM
qFqCa9kCgYEAunw/Qofipch+bcMDsNmd6d9s9l1bBpXkP1ARQohuoVpsJITg+CH6
Dm3tWHnawwCxuQEUZ1/2cqZtrDBukgC90HK0H5j6b8FfyQ0mS3OOnqBHnhV66AXM
Hzlin1Vgaqwuhooy/CfOAyqpMqAfCgCAscxs6EOMteYrY+Xy7Ou02fMCgYEAucme
nNMsSElhsQwW7xpz8rr4k3THKSoetg2pbaUwXR4XDz/J1XWCIkSo8RuN1hA+z6+a
GzJa7CozmaM1j7aGo91U/LN/aNZ9etEbDOO+WCU/K0uTFtVAwgivRqETMARzEvuy
r1M2amUUDM5pX8Jk/Q19cGXQdyJdpShqp8Y93b8CgYEAhukkCsmrmiv16wpOPT7y
EyPj/EeFdroxqewO0IdLIcf8vF61Mk3CTXYRYxSkwrZZ3HF/hVnTPRZR+WQAWffX
WlnhHYragsbuuNCeh69N2kwyA5eelwS6q0wkoQhu/D0cW5DXWbyiOYA/b7SPP/kl
IXu2vkFAJsghU+AjYmsTJykCgYBtuzvHfKKG/3CH1ZAmIQWis/Plg++tzIbfGCqd
7BcoqIEOLKrVPNZjzxHJdnDLokS2/gyTS6aQHkzjzZXxD+luF2f+6TWzghwS0jab
4lemUDmDJNv3fHUHJYIAwVpH3hjpeWgMTaWyKYkyFyf9ux9SpwkTvc7mzpFo3vo/
pcMcmQKBgCVZpfRJxJ1pc4v0M2pxF3zsyDo3CbvhO7ZjOwYyNa5A+p65BsGbOjuR
2v6GLNvYtgqM+FXqTyqz2RkyoKIOqXyOWdSDPHaP2mu5A0xaTom6H7F8PuNFIm4F
iy6KC991zzvaWY/Ys+q/84Afqa+0qJKQnPuy/7F5GkVdQA/lfbhi
-----END RSA PRIVATE KEY-----
\0";
const TEST_DER: &'static [u8] = &[
0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0x8d, 0x76, 0xa1, 0x2e, 0xb6, 0xc0, 0xe5, 0x1e,
0x1a, 0x06, 0x74, 0x13, 0x57, 0x6a, 0xc2, 0x6c, 0x02, 0x9d, 0x82, 0x91, 0x5b, 0xb0, 0xe5, 0xa9, 0x7f, 0xe0, 0x6d, 0x3f,
0xc0, 0x94, 0x88, 0x8e, 0x72, 0xd4, 0x4a, 0xc1, 0xf5, 0x54, 0x71, 0x63, 0x10, 0xaa, 0xef, 0x9d, 0xa5, 0x1a, 0xdc, 0x00,
0x82, 0x2d, 0xea, 0x5f, 0x5b, 0xe8, 0x73, 0x6e, 0x03, 0xf8, 0x07, 0x90, 0x8c, 0xd5, 0x52, 0xf5, 0x6d, 0xfc, 0x4d, 0xe5,
0x6a, 0x87, 0x5a, 0x85, 0xf7, 0x34, 0x85, 0x9a, 0x19, 0x3a, 0x74, 0x46, 0x1e, 0xcb, 0x30, 0x77, 0x8d, 0x68, 0x8a, 0xb8,
0xfd, 0x6e, 0xbc, 0xee, 0xd2, 0xd0, 0xb3, 0xd0, 0x1c, 0x44, 0x29, 0xd0, 0xd6, 0x91, 0xb5, 0xa8, 0xc1, 0xe3, 0x88, 0x64,
0x40, 0x16, 0x31, 0x6c, 0xdc, 0x4b, 0xba, 0x69, 0xc3, 0xcd, 0x8d, 0x4a, 0xd8, 0x7d, 0xf4, 0xa7, 0xe2, 0xe8, 0xc5, 0x01,
0x6f, 0xcc, 0x91, 0x22, 0x81, 0x52, 0x83, 0x11, 0x28, 0xb3, 0x97, 0x1d, 0x57, 0xa2, 0x2a, 0x01, 0x77, 0x65, 0x87, 0x3e,
0xdc, 0x6c, 0x7f, 0x0a, 0xca, 0x95, 0x04, 0x6a, 0x4e, 0x47, 0xa4, 0xfb, 0xa1, 0x42, 0x19, 0x0f, 0x80, 0x14, 0xed, 0xf9,
0x4a, 0x42, 0x9c, 0x6f, 0xef, 0x0f, 0x82, 0x51, 0xbb, 0x46, 0x66, 0xc6, 0xfd, 0xd9, 0x01, 0x93, 0x6d, 0xda, 0x36, 0xc7,
0x58, 0x37, 0x4b, 0xa7, 0xdb, 0xbd, 0xb2, 0x6f, 0x5b, 0x33, 0x4b, 0x78, 0x70, 0x7e, 0xe8, 0x02, 0xdd, 0x5f, 0xa4, 0x2f,
0xea, 0x3c, 0x6b, 0xfb, 0x51, 0xe1, 0x19, 0x21, 0x9f, 0x52, 0xd6, 0x29, 0x53, 0x09, 0x98, 0xbc, 0x3e, 0x3b, 0xb3, 0xdc,
0x25, 0x13, 0x36, 0x1b, 0x24, 0xf4, 0x33, 0xdd, 0xdf, 0xa8, 0xd6, 0xe8, 0x97, 0x11, 0x2f, 0x9a, 0x81, 0xc1, 0xb6, 0xf1,
0x7b, 0xa5, 0xa4, 0x2c, 0xda, 0x41, 0xb6, 0x11, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x38, 0x98, 0xb9,
0xab, 0xe2, 0xda, 0x11, 0xd0, 0x95, 0x40, 0xf7, 0xb7, 0xb5, 0x45, 0xb5, 0x3b, 0x59, 0x60, 0x83, 0x18, 0x7c, 0xc2, 0xad,
0x5f, 0xbf, 0x15, 0x9f, 0x1f, 0xde, 0x80, 0x8e, 0x91, 0xcf, 0x47, 0x38, 0x11, 0x99, 0x81, 0x8b, 0x4b, 0xc3, 0x23, 0x60,
0x72, 0x85, 0xd7, 0xd5, 0x25, 0x2e, 0xf0, 0x07, 0xd0, 0xd7, 0x08, 0x8d, 0x05, 0xfa, 0xf8, 0x84, 0xae, 0x44, 0x6a, 0x24,
0xa2, 0xa4, 0xba, 0x48, 0xbf, 0xfc, 0x7a, 0xe2, 0xb0, 0xae, 0x52, 0x89, 0x11, 0x39, 0xfe, 0xb4, 0xfe, 0x48, 0xdb, 0xaa,
0x2c, 0x6a, 0x9a, 0xe4, 0xc5, 0x56, 0x3f, 0xb3, 0xbf, 0x29, 0x00, 0xee, 0xaf, 0xd8, 0x5f, 0x3d, 0x0b, 0x9c, 0x8c, 0xf7,
0x4c, 0xe9, 0x25, 0x8b, 0x2f, 0xf0, 0xa3, 0xf0, 0x6a, 0x49, 0x48, 0xd2, 0xef, 0xf5, 0xb2, 0x8b, 0x50, 0xe2, 0x84, 0xa2,
0x19, 0x79, 0x22, 0xff, 0x8e, 0x16, 0xbe, 0x00, 0x70, 0xc4, 0x6d, 0xd0, 0x29, 0x54, 0x28, 0x99, 0x97, 0x84, 0xc9, 0xaf,
0xd8, 0xb6, 0xb1, 0x44, 0x6d, 0x4a, 0x74, 0x82, 0x4e, 0xde, 0x44, 0x1c, 0x47, 0x11, 0x52, 0x86, 0x48, 0xd7, 0x78, 0x52,
0xa9, 0x98, 0x20, 0x9d, 0x83, 0x39, 0x3d, 0xe5, 0xd6, 0xed, 0x94, 0x6a, 0x67, 0xd0, 0x65, 0x23, 0xf6, 0xdd, 0xe1, 0xe3,
0xed, 0xe9, 0x6b, 0x85, 0xcb, 0x91, 0x0b, 0xcd, 0xc4, 0x6b, 0xe4, 0x90, 0xd4, 0xeb, 0x7b, 0x80, 0x0b, 0x67, 0x9d, 0xb5,
0x37, 0x0b, 0x83, 0x7d, 0x79, 0x45, 0x6b, 0x60, 0x7d, 0x6f, 0xe3, 0xe0, 0x5e, 0x92, 0xf6, 0x13, 0x67, 0xd2, 0xd4, 0xdc,
0x43, 0x5f, 0xd8, 0xee, 0xf5, 0x28, 0x05, 0x64, 0x78, 0x6a, 0x6f, 0xaf, 0xef, 0x64, 0x52, 0x93, 0x70, 0x4f, 0x9a, 0xab,
0xce, 0x4a, 0x51, 0x63, 0x2a, 0xf1, 0x33, 0xfd, 0xd8, 0x1e, 0xf9, 0xef, 0xf1, 0x02, 0x81, 0x81, 0x00, 0xcf, 0xa7, 0x89,
0x75, 0xdd, 0x09, 0x66, 0x8b, 0x4e, 0xda, 0x52, 0x38, 0x4a, 0xc3, 0x7c, 0xca, 0x90, 0x68, 0x4a, 0xbb, 0x78, 0x14, 0xc1,
0x83, 0x24, 0xb2, 0x2e, 0x39, 0x20, 0x8a, 0x00, 0x97, 0x8d, 0xf3, 0x21, 0x5a, 0xad, 0x03, 0xc7, 0xb2, 0xe9, 0x17, 0x10,
0x85, 0x63, 0x23, 0xe3, 0xc9, 0x73, 0x91, 0xa8, 0x5a, 0x8d, 0xb6, 0x40, 0x0f, 0x98, 0xb8, 0x2a, 0x8f, 0x7e, 0x59, 0x80,
0x8a, 0xee, 0xb9, 0xe9, 0x9b, 0x2e, 0x83, 0xd4, 0x85, 0xc1, 0xdc, 0x1e, 0xc9, 0x44, 0x48, 0x2a, 0x13, 0x06, 0x09, 0x02,
0x3e, 0x3f, 0xfb, 0xf2, 0xe8, 0x1a, 0x2d, 0xec, 0x40, 0xea, 0x0e, 0x2b, 0x7f, 0xf3, 0x79, 0xdc, 0x11, 0x3b, 0x0d, 0xb8,
0x3f, 0x4f, 0x06, 0x02, 0x17, 0x7c, 0x79, 0xa7, 0x36, 0x56, 0xef, 0xcd, 0x1a, 0x41, 0x00, 0x2c, 0xe8, 0x2e, 0x55, 0x9b,
0x10, 0xea, 0x19, 0xb2, 0xe3, 0x02, 0x81, 0x81, 0x00, 0xae, 0x66, 0x06, 0x29, 0xcd, 0x44, 0x6b, 0x4d, 0xb0, 0x1e, 0xba,
0xb8, 0x4f, 0x5e, 0x06, 0xaa, 0x02, 0x58, 0xc9, 0xb5, 0x46, 0x68, 0xe0, 0xaf, 0x48, 0x48, 0x82, 0x45, 0xd2, 0x9c, 0xa5,
0x2d, 0x9d, 0xe6, 0x7a, 0x16, 0xe6, 0xba, 0x8c, 0xe9, 0x2b, 0x61, 0xaf, 0x40, 0x8c, 0xab, 0x38, 0x17, 0x4e, 0xe1, 0xf7,
0x0d, 0x52, 0xb8, 0x78, 0xcc, 0x4d, 0xcb, 0xdc, 0xe4, 0xb7, 0x4f, 0x41, 0xdf, 0xde, 0x34, 0x20, 0x5f, 0xac, 0x45, 0x6f,
0xed, 0xcd, 0xc0, 0x4d, 0x88, 0x7a, 0xf4, 0xc9, 0x8a, 0xa4, 0xf7, 0x40, 0x41, 0x4d, 0xb6, 0x98, 0x1f, 0x2a, 0x42, 0x42,
0x62, 0xd2, 0xb1, 0xef, 0x84, 0x94, 0x87, 0x09, 0xfe, 0xf1, 0xba, 0xb2, 0xb8, 0x6c, 0x99, 0xb2, 0x77, 0xa6, 0xd8, 0x91,
0x07, 0xb5, 0xd9, 0x7d, 0xe8, 0x59, 0xc0, 0xfa, 0x5a, 0x55, 0xf4, 0x3a, 0x82, 0xf4, 0x78, 0xa1, 0x7b, 0x02, 0x81, 0x80,
0x3f, 0x6e, 0xfa, 0x7a, 0xda, 0xce, 0xe8, 0x58, 0x5d, 0xfa, 0x2b, 0x6b, 0xae, 0xcb, 0x10, 0xf0, 0x00, 0x35, 0x1b, 0xbf,
0x30, 0xeb, 0x86, 0x41, 0xbd, 0x90, 0x00, 0xb6, 0xca, 0xcd, 0xdd, 0x68, 0x6e, 0xa0, 0x7a, 0xeb, 0xec, 0x36, 0x5f, 0x66,
0xb3, 0xf5, 0xab, 0xc2, 0x53, 0x8a, 0xbf, 0x26, 0xe6, 0xfa, 0xf3, 0xe6, 0xd5, 0xab, 0x7a, 0xde, 0x48, 0xd4, 0xd9, 0x8b,
0x84, 0x19, 0x6b, 0x3f, 0x05, 0xb6, 0x1d, 0x3a, 0x9e, 0x76, 0xff, 0x10, 0xed, 0x2b, 0x84, 0xec, 0x0e, 0xc3, 0xcc, 0xb6,
0x8a, 0xfd, 0x6d, 0x85, 0xfe, 0x9d, 0xc4, 0x92, 0x4a, 0x8d, 0x04, 0xc2, 0xbf, 0xbd, 0x1c, 0x64, 0xb5, 0xc7, 0xe0, 0x06,
0x13, 0x78, 0x19, 0x74, 0x9d, 0x7b, 0x44, 0x60, 0x50, 0x52, 0x09, 0x56, 0x7c, 0x30, 0x3d, 0x03, 0x6c, 0x1f, 0xd5, 0x98,
0x07, 0xaf, 0x76, 0xf3, 0x2f, 0xd0, 0x31, 0xe9, 0x02, 0x81, 0x81, 0x00, 0xa6, 0x61, 0x77, 0x67, 0xd2, 0x09, 0x80, 0x45,
0xb1, 0xcc, 0xdf, 0x5e, 0x8f, 0x79, 0xa8, 0xe9, 0xf1, 0x2b, 0x3b, 0xe4, 0xd1, 0xb3, 0xa5, 0x08, 0x14, 0xf1, 0xf8, 0x37,
0x1c, 0xe3, 0x8d, 0x42, 0xa3, 0xee, 0x0a, 0x74, 0x66, 0xd3, 0x7b, 0x33, 0xc8, 0xcb, 0x7d, 0x23, 0x1c, 0x11, 0x0d, 0x86,
0x4f, 0x1f, 0x8d, 0x4f, 0x0c, 0xa8, 0x29, 0xb6, 0xe0, 0x51, 0xaa, 0x00, 0x1a, 0x52, 0x67, 0x0a, 0x69, 0x37, 0x59, 0xdb,
0x6c, 0xc3, 0x22, 0x31, 0xc1, 0xa5, 0xc1, 0x52, 0x7f, 0xdb, 0xa1, 0x9b, 0xc0, 0x1e, 0x93, 0x12, 0xba, 0x4d, 0x85, 0x7b,
0xd6, 0x19, 0x38, 0xb4, 0x87, 0x46, 0x72, 0xb8, 0x0d, 0xeb, 0x77, 0x41, 0xde, 0xe4, 0xbb, 0x34, 0xef, 0x87, 0x02, 0x98,
0xdc, 0x78, 0xa8, 0x84, 0xae, 0x9d, 0x3c, 0x5d, 0xbb, 0xa3, 0x3c, 0x35, 0x8a, 0xe3, 0x62, 0x1f, 0x25, 0x95, 0x20, 0x99,
0x02, 0x81, 0x80, 0x5b, 0xfb, 0x99, 0x65, 0xaa, 0x0d, 0x55, 0xf5, 0x66, 0x27, 0x95, 0xc8, 0xb2, 0x68, 0x7f, 0x8b, 0xd3,
0x26, 0xd1, 0x51, 0x68, 0xe3, 0x5f, 0x84, 0x1b, 0x13, 0xbf, 0xec, 0xb4, 0x92, 0x09, 0xa8, 0x0c, 0xac, 0x5f, 0x99, 0x3a,
0xd5, 0xda, 0xdd, 0xee, 0xba, 0x1c, 0xce, 0x92, 0x7c, 0x54, 0xd4, 0xf8, 0x6a, 0xc3, 0xb3, 0x07, 0xea, 0xce, 0x18, 0xad,
0x8e, 0x26, 0x5e, 0x54, 0xa1, 0x87, 0x77, 0x6a, 0x7b, 0x23, 0x2e, 0x76, 0xb6, 0x3a, 0xe7, 0xd9, 0x67, 0x0d, 0x7e, 0x19,
0xd9, 0x6e, 0x2c, 0xe0, 0x00, 0xd6, 0x8e, 0xd2, 0x5a, 0xc9, 0x59, 0x44, 0x58, 0xd8, 0x73, 0x15, 0x0f, 0x17, 0x63, 0x3e,
0xef, 0x74, 0x2f, 0xfe, 0xbd, 0x50, 0x07, 0x5f, 0x7d, 0x15, 0x23, 0xab, 0xc2, 0x77, 0x6d, 0xc9, 0x3d, 0x08, 0x1a, 0x88,
0xdd, 0x45, 0x26, 0xd9, 0x2d, 0xe9, 0xde, 0xb9, 0x58, 0x36, 0x5f,
];
#[test]
fn generate_rsa() {
let mut pk = Pk::generate_rsa(&mut crate::test_support::rand::test_deterministic_rng(), 2048, 0x10001).unwrap();
let generated = pk.write_private_pem_string().unwrap();
assert_eq!(0x10001, pk.rsa_public_exponent().unwrap());
assert_eq!(generated, TEST_PEM[..TEST_PEM.len() - 1]);
}
#[test]
fn generate_ec_curve25519() {
let _generated = Pk::generate_ec(&mut crate::test_support::rand::test_rng(), EcGroupId::Curve25519).unwrap();
}
#[test]
fn generate_ec_secp192r1() {
let _generated = Pk::generate_ec(&mut crate::test_support::rand::test_rng(), EcGroupId::SecP192R1)
.unwrap()
.write_private_pem_string()
.unwrap();
}
#[test]
fn generate_ec_secp256r1() {
let mut key1 = Pk::generate_ec(&mut crate::test_support::rand::test_deterministic_rng(), EcGroupId::SecP256R1).unwrap();
let pem1 = key1.write_private_pem_string().unwrap();
let secp256r1 = EcGroup::new(EcGroupId::SecP256R1).unwrap();
let mut key2 = Pk::generate_ec(&mut crate::test_support::rand::test_deterministic_rng(), secp256r1.clone()).unwrap();
let pem2 = key2.write_private_pem_string().unwrap();
assert_eq!(pem1, pem2);
let mut key_from_components = Pk::private_from_ec_scalar_with_rng(
secp256r1.clone(),
key1.ec_private().unwrap(),
&mut crate::test_support::rand::test_deterministic_rng(),
)
.unwrap();
let pem3 = key_from_components.write_private_pem_string().unwrap();
assert_eq!(pem3, pem2);
let mut pub1 = Pk::from_public_key(&key1.write_public_der_vec().unwrap()).unwrap();
let mut pub2 = Pk::public_from_ec_components(secp256r1.clone(), key1.ec_public().unwrap()).unwrap();
assert_eq!(
pub1.write_public_pem_string().unwrap(),
pub2.write_public_pem_string().unwrap()
);
}
#[test]
fn generate_ec_secp256k1() {
let _generated = Pk::generate_ec(&mut crate::test_support::rand::test_rng(), EcGroupId::SecP256K1)
.unwrap()
.write_private_pem_string()
.unwrap();
}
#[test]
fn parse_write_pem() {
let parsed = Pk::from_private_key(TEST_PEM.as_bytes(), None)
.unwrap()
.write_private_pem_string()
.unwrap();
assert_eq!(parsed, TEST_PEM[..TEST_PEM.len() - 1]);
}
#[test]
fn parse_write_der() {
let parsed = Pk::from_private_key(TEST_DER, None).unwrap().write_private_der_vec().unwrap();
assert!(parsed == TEST_DER);
}
#[test]
fn rsa_sign_verify_pkcs1v15() {
let mut pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
let data = b"SIGNATURE TEST SIGNATURE TEST SIGNATURE TEST SIGNATURE TEST SIGN";
let mut signature = vec![0u8; (pk.len() + 7) / 8];
let digests = [
Type::None,
Type::Md2,
Type::Md4,
Type::Md5,
Type::Sha1,
Type::Sha224,
Type::Sha256,
Type::Sha384,
Type::Sha512,
Type::Ripemd,
];
for &digest in &digests {
let data = if let Some(md @ MdInfo { .. }) = digest.into() {
&data[..md.size()]
} else {
&data[..]
};
let len = pk
.sign(digest, data, &mut signature, &mut crate::test_support::rand::test_rng())
.unwrap();
pk.verify(digest, data, &signature[0..len]).unwrap();
assert_eq!(pk.verify(digest, data, &[]).unwrap_err(), Error::PkBadInputData);
assert_eq!(pk.verify(digest, &[], &signature[0..len]).unwrap_err(), Error::PkBadInputData);
let mut dummy_sig = [];
assert_eq!(
pk.sign(digest, data, &mut dummy_sig, &mut crate::test_support::rand::test_rng())
.unwrap_err(),
Error::PkBadInputData
);
assert_eq!(
pk.sign(digest, &[], &mut signature, &mut crate::test_support::rand::test_rng())
.unwrap_err(),
Error::PkBadInputData
);
assert_eq!(
pk.sign_deterministic(digest, data, &mut dummy_sig, &mut crate::test_support::rand::test_rng())
.unwrap_err(),
Error::PkBadInputData
);
assert_eq!(
pk.sign_deterministic(digest, &[], &mut signature, &mut crate::test_support::rand::test_rng())
.unwrap_err(),
Error::PkBadInputData
);
}
}
#[test]
fn rsa_sign_verify_pss() {
let mut pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
let data = b"SIGNATURE TEST SIGNATURE TEST SIGNATURE TEST SIGNATURE TEST SIGN";
let mut signature = vec![0u8; (pk.len() + 7) / 8];
let digests = [
Type::None,
Type::Md2,
Type::Md4,
Type::Md5,
Type::Sha1,
Type::Sha224,
Type::Sha256,
Type::Sha384,
Type::Sha512,
Type::Ripemd,
];
for &digest in &digests {
let data = if let Some(md @ MdInfo { .. }) = digest.into() {
&data[..md.size()]
} else {
&data[..]
};
pk.set_options(Options::Rsa {
padding: RsaPadding::Pkcs1V21 { mgf: digest },
});
if digest == Type::None {
assert!(pk
.sign(digest, data, &mut signature, &mut crate::test_support::rand::test_rng())
.is_err());
} else {
let len = pk
.sign(digest, data, &mut signature, &mut crate::test_support::rand::test_rng())
.unwrap();
pk.verify(digest, data, &signature[0..len]).unwrap();
}
}
}
#[test]
fn encrypt_v15_oaep() {
let mut pk = Pk::from_private_key(TEST_DER, None).unwrap();
let mut cipher1 = [0u8; 2048 / 8];
let mut cipher2 = [0u8; 2048 / 8];
assert_eq!(
pk.encrypt(b"test", &mut cipher1, &mut crate::test_support::rand::test_rng())
.unwrap(),
cipher1.len()
);
pk.set_options(Options::Rsa {
padding: RsaPadding::Pkcs1V21 { mgf: Type::Sha256 },
});
assert_eq!(
pk.encrypt(b"test", &mut cipher2, &mut crate::test_support::rand::test_rng())
.unwrap(),
cipher2.len()
);
assert_ne!(&cipher1[..], &cipher2[..]);
}
#[test]
fn encrypt_raw_decrypt_with_pkcs1_v15() {
let mut pk = Pk::from_private_key(TEST_DER, None).unwrap();
let mut cipher = [0u8; 2048 / 8];
let mut rng = crate::test_support::rand::test_rng();
pk.set_options(Options::Rsa {
padding: RsaPadding::Pkcs1V15,
});
assert_eq!(pk.encrypt(b"test", &mut cipher, &mut rng).unwrap(), cipher.len());
let mut decrypted_data1 = [0u8; 2048 / 8];
let length_with_padding = pk.decrypt(&cipher, &mut decrypted_data1, &mut rng).unwrap();
pk.set_options(Options::Rsa {
padding: RsaPadding::None,
});
let mut decrypted_data2 = [0u8; 2048 / 8];
let length_without_padding = pk.decrypt(&cipher, &mut decrypted_data2, &mut rng).unwrap();
assert_eq!(length_without_padding, decrypted_data2.len());
assert_ne!(length_without_padding, length_with_padding);
assert_eq!(decrypted_data2.len(), cipher.len());
}
#[test]
fn rsa_encrypt_with_no_padding() {
let mut pk = Pk::from_private_key(TEST_DER, None).unwrap();
let mut cipher = [0u8; 2048 / 8];
pk.set_options(Options::Rsa {
padding: RsaPadding::None,
});
assert_eq!(
pk.encrypt(b"test", &mut cipher, &mut crate::test_support::rand::test_rng())
.unwrap_err(),
Error::RsaInvalidPadding
);
}
#[test]
fn rsa_encrypt_decrypt_with_label() {
let mut pk = Pk::from_private_key(TEST_DER, None).unwrap();
let mut cipher = [0u8; 2048 / 8];
pk.set_options(Options::Rsa {
padding: RsaPadding::Pkcs1V21 { mgf: MdType::Sha256 },
});
let plain = b"testing123";
let cipher_len = pk
.encrypt_with_label(plain, &mut cipher, &mut crate::test_support::rand::test_rng(), b"MY_LABEL")
.unwrap();
assert_eq!(cipher_len, cipher.len());
let mut plain_decrypted = [0u8; 10];
let plain_len = pk
.decrypt_with_label(
&cipher,
&mut plain_decrypted,
&mut crate::test_support::rand::test_rng(),
b"MY_LABEL",
)
.unwrap();
assert_eq!(plain_len, plain.len());
assert_eq!(&plain_decrypted, plain);
assert_eq!(
pk.decrypt_with_label(
&cipher,
&mut plain_decrypted,
&mut crate::test_support::rand::test_rng(),
b"WRONG_LABEL"
)
.unwrap_err(),
Error::RsaInvalidPadding
);
}
#[test]
fn rsa_sign_with_none_padding() {
let mut pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
let data = b"SIGNATURE TEST SIGNATURE TEST SI";
let mut signature = vec![0u8; (pk.len() + 7) / 8];
pk.set_options(Options::Rsa {
padding: RsaPadding::None,
});
assert_eq!(
pk.sign(Type::Sha256, data, &mut signature, &mut crate::test_support::rand::test_rng())
.unwrap_err(),
Error::RsaInvalidPadding
);
}
#[test]
fn rsa_verify_with_none_padding() {
let mut pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
let data = b"SIGNATURE TEST SIGNATURE TEST SI";
let mut signature = vec![0u8; (pk.len() + 7) / 8];
let digest = Type::Sha256;
pk.set_options(Options::Rsa {
padding: RsaPadding::Pkcs1V21 { mgf: digest },
});
let len = pk
.sign(digest, data, &mut signature, &mut crate::test_support::rand::test_rng())
.unwrap();
pk.set_options(Options::Rsa {
padding: RsaPadding::None,
});
assert_eq!(
pk.verify(digest, data, &signature[0..len]).unwrap_err(),
Error::RsaInvalidPadding
);
}
#[test]
fn rsa_params() {
let pk = Pk::from_private_key(TEST_DER, None).unwrap();
let n = pk.rsa_public_modulus().unwrap();
let d = pk.rsa_private_exponent().unwrap();
let p = pk.rsa_private_prime1().unwrap();
let q = pk.rsa_private_prime2().unwrap();
let dp = pk.rsa_crt_dp().unwrap();
let dq = pk.rsa_crt_dq().unwrap();
let qp = pk.rsa_crt_qp().unwrap();
let one = Mpi::new(1).unwrap();
let p1 = (&p - &one).unwrap();
let q1 = (&q - &one).unwrap();
assert_eq!(&p * &q, Ok(n));
assert_eq!(&d % &p1, Ok(dp));
assert_eq!(&d % &q1, Ok(dq));
assert_eq!((&qp * &q).unwrap().modulo(&p), Ok(one));
}
#[test]
fn custom_pk_obj() {
let pk = Pk::public_custom_algo(&[8, 0, 2], &[1, 2, 3, 4]).unwrap();
assert_eq!(pk.pk_type(), PkType::Custom);
assert_eq!(pk.custom_algo_id().unwrap(), &[8, 0, 2]);
assert_eq!(pk.custom_public_key().unwrap(), &[1, 2, 3, 4]);
assert!(pk.custom_private_key().is_err());
assert!(!pk.can_do(PkType::Rsa));
let pk = Pk::private_custom_algo(&[23], &[1, 2, 3, 4], &[9, 1, 1]).unwrap();
assert_eq!(pk.pk_type(), PkType::Custom);
assert_eq!(pk.custom_algo_id().unwrap(), &[23]);
assert_eq!(pk.custom_public_key().unwrap(), &[1, 2, 3, 4]);
assert_eq!(pk.custom_private_key().unwrap(), &[9, 1, 1]);
let pk = Pk::from_private_key(TEST_DER, None).unwrap();
assert!(pk.custom_algo_id().is_err());
assert!(pk.custom_public_key().is_err());
assert!(pk.custom_private_key().is_err());
}
#[test]
fn fips_rsadp_bounds() {
let rng = &mut crate::test_support::rand::test_rng();
let (bitlen, exp) = (2048, 0x10001);
let mut pk = Pk::generate_rsa(rng, bitlen, exp).unwrap();
pk.set_options(Options::Rsa {
padding: RsaPadding::None,
});
const LEN: usize = 256;
let expected_err = Error::MpiBadInputData;
let mut pt = [0x00; LEN];
let _0 = Mpi::new(0).unwrap();
let _1 = Mpi::new(1).unwrap();
let _2 = Mpi::new(2).unwrap();
let n = pk.rsa_public_modulus().unwrap();
let nm1 = pk.rsa_public_modulus().unwrap().sub(&Mpi::new(1).unwrap()).unwrap();
let nm2 = pk.rsa_public_modulus().unwrap().sub(&Mpi::new(2).unwrap()).unwrap();
for c in [_0, _1, nm1, n] {
let ct = c.to_binary_padded(LEN).unwrap();
let l = pk.decrypt(&ct, &mut pt, rng);
assert_eq!(l.unwrap_err(), expected_err);
}
for c in [_2, nm2] {
let ct = c.to_binary_padded(LEN).unwrap();
let l = pk.decrypt(&ct, &mut pt, rng);
assert_eq!(l.unwrap(), LEN);
}
}
fn assert_rsa_private_key_eq(pk1: &Pk, pk2: &Pk) {
assert_eq!(pk1.rsa_public_modulus().unwrap(), pk2.rsa_public_modulus().unwrap()); assert_eq!(pk1.rsa_public_exponent().unwrap(), pk2.rsa_public_exponent().unwrap()); assert_eq!(pk1.rsa_private_exponent().unwrap(), pk2.rsa_private_exponent().unwrap()); let p1 = pk1.rsa_private_prime1().unwrap();
let p2 = pk2.rsa_private_prime1().unwrap();
let q1 = pk1.rsa_private_prime2().unwrap();
let q2 = pk2.rsa_private_prime2().unwrap();
assert!(((p1 == p2) && (q1 == q2)) || ((p1 == q2) && (q1 == p2)));
}
#[test]
fn private_from_rsa_components_sanity() {
let pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
let components = RsaPrivateComponents::WithPrimes {
p: &pk.rsa_private_prime1().unwrap(),
q: &pk.rsa_private_prime2().unwrap(),
e: &Mpi::new(pk.rsa_public_exponent().unwrap() as _).unwrap(),
};
let pk2 = Pk::private_from_rsa_components(components).unwrap();
assert_rsa_private_key_eq(&pk, &pk2);
let components = RsaPrivateComponents::WithPrivateExponent {
n: &pk.rsa_public_modulus().unwrap(),
d: &pk.rsa_private_exponent().unwrap(),
e: &Mpi::new(pk.rsa_public_exponent().unwrap() as _).unwrap(),
};
let pk3 = Pk::private_from_rsa_components(components).unwrap();
assert_rsa_private_key_eq(&pk, &pk3);
}
#[test]
fn private_from_rsa_components_wrong_params() {
let pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
let components = RsaPrivateComponents::WithPrimes {
p: &pk.rsa_private_prime1().unwrap(),
q: &pk.rsa_private_prime2().unwrap(),
e: &pk.rsa_public_modulus().unwrap(), };
let err = match Pk::private_from_rsa_components(components) {
Ok(_) => panic!("expected an error, got a Pk"),
Err(e) => e,
};
assert_eq!(err, Error::RsaKeyCheckFailed);
}
#[test]
fn public_from_rsa_components_sanity() {
let mut pk = Pk::generate_rsa(&mut crate::test_support::rand::test_rng(), 2048, 0x10001).unwrap();
let mut pk = Pk::from_public_key(&pk.write_public_der_vec().unwrap()).unwrap();
let components = RsaPublicComponents {
n: &pk.rsa_public_modulus().unwrap(),
e: &Mpi::new(pk.rsa_public_exponent().unwrap() as _).unwrap(),
};
let mut pk2 = Pk::public_from_rsa_components(components).unwrap();
assert_eq!(pk.write_public_der_vec().unwrap(), pk2.write_public_der_vec().unwrap());
}
}