use crate::interface_types::ecc::EccCurve;
use crate::structures::Public;
use crate::utils::PublicKey as TpmPublicKey;
use crate::{Error, WrapperErrorKind};
use core::convert::TryFrom;
use elliptic_curve::{
AffinePoint, CurveArithmetic, FieldBytesSize, PublicKey,
generic_array::typenum::Unsigned,
sec1::{EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint},
};
use x509_cert::spki::SubjectPublicKeyInfoOwned;
#[cfg(feature = "rsa")]
use {
crate::structures::RsaExponent,
rsa::{BigUint, RsaPublicKey},
};
#[cfg(any(
feature = "p192",
feature = "p224",
feature = "p256",
feature = "p384",
feature = "p521",
feature = "rsa",
feature = "sm2"
))]
use pkcs8::EncodePublicKey;
#[cfg(feature = "rsa")]
const RSA_DEFAULT_EXP: u64 = 65537;
impl<C> TryFrom<&Public> for PublicKey<C>
where
C: CurveArithmetic + AssociatedTpmCurve,
FieldBytesSize<C>: ModulusSize,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
{
type Error = Error;
fn try_from(value: &Public) -> Result<Self, Self::Error> {
match value {
Public::Ecc {
parameters, unique, ..
} => {
if parameters.ecc_curve() != C::TPM_CURVE {
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
}
let x = unique.x().as_bytes();
let y = unique.y().as_bytes();
if x.len() != FieldBytesSize::<C>::USIZE {
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
}
if y.len() != FieldBytesSize::<C>::USIZE {
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
}
let encoded_point =
EncodedPoint::<C>::from_affine_coordinates(x.into(), y.into(), false);
let public_key = PublicKey::<C>::try_from(&encoded_point)
.map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?;
Ok(public_key)
}
_ => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
}
}
}
#[cfg(feature = "rsa")]
impl TryFrom<&Public> for RsaPublicKey {
type Error = Error;
fn try_from(value: &Public) -> Result<Self, Self::Error> {
match value {
Public::Rsa {
unique, parameters, ..
} => {
let exponent = match parameters.exponent() {
RsaExponent::ZERO_EXPONENT => BigUint::from(RSA_DEFAULT_EXP),
_ => BigUint::from(parameters.exponent().value()),
};
let modulus = BigUint::from_bytes_be(unique.as_bytes());
let public_key = RsaPublicKey::new(modulus, exponent)
.map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?;
Ok(public_key)
}
_ => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
}
}
}
impl TryFrom<&Public> for SubjectPublicKeyInfoOwned {
type Error = Error;
fn try_from(value: &Public) -> Result<Self, Self::Error> {
match value {
#[cfg(feature = "rsa")]
Public::Rsa { .. } => {
let public_key = RsaPublicKey::try_from(value)?;
Ok(public_key
.to_public_key_der()
.map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?
.decode_msg::<Self>()
.map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?)
}
#[allow(unused)]
Public::Ecc { parameters, .. } => {
macro_rules! read_key {
($key_type:ty) => {
if parameters.ecc_curve() == <$key_type>::TPM_CURVE {
let public_key = PublicKey::<$key_type>::try_from(value)?;
return public_key
.to_public_key_der()
.map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?
.decode_msg::<Self>()
.map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam));
}
};
}
#[cfg(feature = "p192")]
read_key!(p192::NistP192);
#[cfg(feature = "p224")]
read_key!(p224::NistP224);
#[cfg(feature = "p256")]
read_key!(p256::NistP256);
#[cfg(feature = "p384")]
read_key!(p384::NistP384);
#[cfg(feature = "p521")]
read_key!(p521::NistP521);
#[cfg(feature = "sm2")]
read_key!(sm2::Sm2);
Err(Error::local_error(WrapperErrorKind::UnsupportedParam))
}
_ => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
}
}
}
impl<C> TryFrom<&TpmPublicKey> for PublicKey<C>
where
C: CurveArithmetic + AssociatedTpmCurve,
FieldBytesSize<C>: ModulusSize,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
{
type Error = Error;
fn try_from(value: &TpmPublicKey) -> Result<Self, Self::Error> {
match value {
TpmPublicKey::Ecc { x, y } => {
let x = x.as_slice();
let y = y.as_slice();
if x.len() != FieldBytesSize::<C>::USIZE {
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
}
if y.len() != FieldBytesSize::<C>::USIZE {
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
}
let encoded_point =
EncodedPoint::<C>::from_affine_coordinates(x.into(), y.into(), false);
let public_key = PublicKey::<C>::try_from(&encoded_point)
.map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?;
Ok(public_key)
}
_ => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
}
}
}
#[cfg(feature = "rsa")]
impl TryFrom<&TpmPublicKey> for RsaPublicKey {
type Error = Error;
fn try_from(value: &TpmPublicKey) -> Result<Self, Self::Error> {
match value {
TpmPublicKey::Rsa(modulus) => {
let exponent = BigUint::from(RSA_DEFAULT_EXP);
let modulus = BigUint::from_bytes_be(modulus.as_slice());
let public_key = RsaPublicKey::new(modulus, exponent)
.map_err(|_| Error::local_error(WrapperErrorKind::InvalidParam))?;
Ok(public_key)
}
_ => Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
}
}
}
pub trait AssociatedTpmCurve {
const TPM_CURVE: EccCurve;
}
#[cfg(feature = "p192")]
impl AssociatedTpmCurve for p192::NistP192 {
const TPM_CURVE: EccCurve = EccCurve::NistP192;
}
#[cfg(feature = "p224")]
impl AssociatedTpmCurve for p224::NistP224 {
const TPM_CURVE: EccCurve = EccCurve::NistP224;
}
#[cfg(feature = "p256")]
impl AssociatedTpmCurve for p256::NistP256 {
const TPM_CURVE: EccCurve = EccCurve::NistP256;
}
#[cfg(feature = "p384")]
impl AssociatedTpmCurve for p384::NistP384 {
const TPM_CURVE: EccCurve = EccCurve::NistP384;
}
#[cfg(feature = "p521")]
impl AssociatedTpmCurve for p521::NistP521 {
const TPM_CURVE: EccCurve = EccCurve::NistP521;
}
#[cfg(feature = "sm2")]
impl AssociatedTpmCurve for sm2::Sm2 {
const TPM_CURVE: EccCurve = EccCurve::Sm2P256;
}