@@ -6,123 +6,176 @@ use crate::structures::{Public, RsaExponent};
66use crate :: { Error , WrapperErrorKind } ;
77
88use core:: convert:: TryFrom ;
9- use oid:: ObjectIdentifier ;
10- use picky_asn1:: bit_string:: BitString ;
11- use picky_asn1:: wrapper:: { IntegerAsn1 , OctetStringAsn1 } ;
12- use picky_asn1_x509:: {
13- AlgorithmIdentifier , EcParameters , EcPoint , PublicKey , RsaPublicKey , SubjectPublicKeyInfo ,
9+ use elliptic_curve:: {
10+ // See TODO below, you're upgrading from 0.13 to 0.14 and
11+ // that moved the implementation from generic-array to
12+ // hybrid-array, you can now use TryFrom
13+ generic_array:: typenum:: Unsigned ,
14+ sec1:: { EncodedPoint , FromEncodedPoint , ModulusSize , ToEncodedPoint } ,
15+ AffinePoint ,
16+ CurveArithmetic ,
17+ FieldBytesSize ,
18+ PublicKey ,
1419} ;
20+ use rsa:: { pkcs8:: EncodePublicKey , BigUint , RsaPublicKey } ;
21+ use x509_cert:: spki:: SubjectPublicKeyInfoOwned ;
1522
16- /// Can be converted from [`crate::structures::Public`] when not a fully constructed
17- /// [`picky_asn1_x509::SubjectPublicKeyInfo`] is required.
18- ///
19- /// # Details
20- /// Holds either [`picky_asn1_x509::RsaPublicKey`] for [`crate::structures::Public::Rsa`] or
21- /// [`picky_asn1_x509::EcPoint`] for [`crate::structures::Public::Ecc`].
22- ///
23- /// This object can be serialized and deserialized
24- /// using serde if the `serde` feature is enabled.
25- #[ derive( Debug , PartialEq , Eq , Clone ) ]
26- #[ cfg_attr( feature = "serde" , derive( serde:: Deserialize , serde:: Serialize ) ) ]
27- pub enum DecodedKey {
28- RsaPublicKey ( RsaPublicKey ) ,
29- EcPoint ( EcPoint ) ,
23+ impl < C > TryFrom < & Public > for PublicKey < C >
24+ where
25+ C : CurveArithmetic + AssociatedTpmCurve ,
26+ FieldBytesSize < C > : ModulusSize ,
27+ AffinePoint < C > : FromEncodedPoint < C > + ToEncodedPoint < C > ,
28+ {
29+ type Error = Error ;
30+
31+ fn try_from ( value : & Public ) -> Result < Self , Self :: Error > {
32+ match value {
33+ Public :: Ecc {
34+ parameters, unique, ..
35+ } => {
36+ if parameters. ecc_curve ( ) != C :: TPM_CURVE {
37+ return Err ( Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ;
38+ }
39+
40+ let x = unique. x ( ) . as_bytes ( ) ;
41+ let y = unique. y ( ) . as_bytes ( ) ;
42+
43+ // TODO: When elliptic_curve bumps to 0.14, we can use the TryFrom implementation instead
44+ // of checking lengths manually
45+ if x. len ( ) != FieldBytesSize :: < C > :: USIZE {
46+ return Err ( Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ;
47+ }
48+ if y. len ( ) != FieldBytesSize :: < C > :: USIZE {
49+ return Err ( Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ;
50+ }
51+
52+ let encoded_point =
53+ EncodedPoint :: < C > :: from_affine_coordinates ( x. into ( ) , y. into ( ) , false ) ;
54+ let public_key = PublicKey :: < C > :: try_from ( & encoded_point)
55+ . map_err ( |_| Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ?;
56+
57+ Ok ( public_key)
58+ }
59+ _ => Err ( Error :: local_error ( WrapperErrorKind :: UnsupportedParam ) ) ,
60+ }
61+ }
3062}
3163
32- impl TryFrom < Public > for DecodedKey {
64+ impl TryFrom < & Public > for RsaPublicKey {
3365 type Error = Error ;
3466
35- fn try_from ( value : Public ) -> Result < Self , Self :: Error > {
36- public_to_decoded_key ( & value)
67+ fn try_from ( value : & Public ) -> Result < Self , Self :: Error > {
68+ match value {
69+ Public :: Rsa {
70+ unique, parameters, ..
71+ } => {
72+ let exponent = match parameters. exponent ( ) {
73+ RsaExponent :: ZERO_EXPONENT => BigUint :: from ( 65537u32 ) ,
74+ _ => BigUint :: from ( parameters. exponent ( ) . value ( ) ) ,
75+ } ;
76+ let modulus = BigUint :: from_bytes_be ( unique. as_bytes ( ) ) ;
77+
78+ let public_key = RsaPublicKey :: new ( modulus, exponent)
79+ . map_err ( |_| Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ?;
80+
81+ Ok ( public_key)
82+ }
83+ _ => Err ( Error :: local_error ( WrapperErrorKind :: UnsupportedParam ) ) ,
84+ }
3785 }
3886}
3987
40- impl TryFrom < Public > for SubjectPublicKeyInfo {
88+ impl TryFrom < & Public > for SubjectPublicKeyInfoOwned {
4189 type Error = Error ;
4290
43- /// Converts [`crate::structures::Public::Rsa`] and [`crate::structures::Public::Ecc`] to [`picky_asn1_x509::SubjectPublicKeyInfo `].
91+ /// Converts [`crate::structures::Public::Rsa`] and [`crate::structures::Public::Ecc`] to [`x509_cert::spki::SubjectPublicKeyInfoOwned `].
4492 ///
4593 /// # Details
46- /// The result can be used to convert TPM public keys to DER using `picky_asn1_der `.
94+ /// The result can be used to convert TPM public keys to DER using `x509-cert `.
4795 ///
4896 /// # Errors
4997 /// * if other instances of [`crate::structures::Public`] are used `UnsupportedParam` will be returned.
50- fn try_from ( value : Public ) -> Result < Self , Self :: Error > {
51- let decoded_key = public_to_decoded_key ( & value) ?;
52-
53- match ( value, decoded_key) {
54- ( Public :: Rsa { .. } , DecodedKey :: RsaPublicKey ( key) ) => Ok ( SubjectPublicKeyInfo {
55- algorithm : AlgorithmIdentifier :: new_rsa_encryption ( ) ,
56- subject_public_key : PublicKey :: Rsa ( key. into ( ) ) ,
57- } ) ,
58- ( Public :: Ecc { parameters, .. } , DecodedKey :: EcPoint ( point) ) => {
59- Ok ( SubjectPublicKeyInfo {
60- algorithm : AlgorithmIdentifier :: new_elliptic_curve ( EcParameters :: NamedCurve (
61- curve_oid ( parameters. ecc_curve ( ) ) ?. into ( ) ,
62- ) ) ,
63- subject_public_key : PublicKey :: Ec ( BitString :: with_bytes ( point) . into ( ) ) ,
64- } )
98+ fn try_from ( value : & Public ) -> Result < Self , Self :: Error > {
99+ match value {
100+ Public :: Rsa { .. } => {
101+ let public_key = RsaPublicKey :: try_from ( value) ?;
102+
103+ Ok ( public_key
104+ . to_public_key_der ( )
105+ . map_err ( |_| Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ?
106+ . decode_msg :: < Self > ( )
107+ . map_err ( |_| Error :: local_error ( WrapperErrorKind :: InvalidParam ) ) ?)
108+ }
109+ #[ allow( unused) ]
110+ Public :: Ecc { parameters, .. } => {
111+ macro_rules! read_key {
112+ ( $curve: expr, $key_type: ty) => {
113+ if parameters. ecc_curve( ) == <$key_type>:: TPM_CURVE {
114+ let public_key = PublicKey :: <$key_type>:: try_from( value) ?;
115+
116+ return Ok ( public_key
117+ . to_public_key_der( )
118+ . map_err( |_| Error :: local_error( WrapperErrorKind :: InvalidParam ) ) ?
119+ . decode_msg:: <Self >( )
120+ . map_err( |_| {
121+ Error :: local_error( WrapperErrorKind :: InvalidParam )
122+ } ) ?) ;
123+ }
124+ } ;
125+ }
126+
127+ #[ cfg( feature = "p192" ) ]
128+ read_key ! ( EccCurve :: NistP192 , p192:: NistP192 ) ;
129+ #[ cfg( feature = "p224" ) ]
130+ read_key ! ( EccCurve :: NistP224 , p224:: NistP224 ) ;
131+ #[ cfg( feature = "p256" ) ]
132+ read_key ! ( EccCurve :: NistP256 , p256:: NistP256 ) ;
133+ #[ cfg( feature = "p384" ) ]
134+ read_key ! ( EccCurve :: NistP384 , p384:: NistP384 ) ;
135+ #[ cfg( feature = "p521" ) ]
136+ read_key ! ( EccCurve :: NistP521 , p521:: NistP521 ) ;
137+ #[ cfg( feature = "sm2" ) ]
138+ read_key ! ( EccCurve :: Sm2P256 , sm2:: Sm2 ) ;
139+
140+ Err ( Error :: local_error ( WrapperErrorKind :: UnsupportedParam ) )
65141 }
66142 _ => Err ( Error :: local_error ( WrapperErrorKind :: UnsupportedParam ) ) ,
67143 }
68144 }
69145}
70146
71- /// Converts [`crate::structures::Public::Rsa`] and [`crate::structures::Public::Ecc`] to [DecodedKey].
72- ///
73- /// # Details
74- /// Does basic key conversion to either RSA or ECC. In RSA conversion the TPM zero exponent is replaced with `65537`.
75- ///
76- /// # Errors
77- /// * if other instances of [`crate::structures::Public`] are used `UnsupportedParam` will be returned.
78- fn public_to_decoded_key ( public : & Public ) -> Result < DecodedKey , Error > {
79- match public {
80- Public :: Rsa {
81- unique, parameters, ..
82- } => {
83- let exponent = match parameters. exponent ( ) {
84- RsaExponent :: ZERO_EXPONENT => 65537 ,
85- _ => parameters. exponent ( ) . value ( ) ,
86- }
87- . to_be_bytes ( ) ;
88- Ok ( DecodedKey :: RsaPublicKey ( RsaPublicKey {
89- modulus : IntegerAsn1 :: from_bytes_be_unsigned ( unique. as_bytes ( ) . to_vec ( ) ) ,
90- public_exponent : IntegerAsn1 :: from_bytes_be_signed ( exponent. to_vec ( ) ) ,
91- } ) )
92- }
93- Public :: Ecc { unique, .. } => {
94- let x = unique. x ( ) . as_bytes ( ) . to_vec ( ) ;
95- let y = unique. y ( ) . as_bytes ( ) . to_vec ( ) ;
96- Ok ( DecodedKey :: EcPoint ( OctetStringAsn1 (
97- elliptic_curve_point_to_octet_string ( x, y) ,
98- ) ) )
99- }
147+ /// Provides the value of the curve used in this crate for the specific curve.
148+ pub trait AssociatedTpmCurve {
149+ /// Value of the curve when interacting with the TPM.
150+ const TPM_CURVE : EccCurve ;
151+ }
100152
101- _ => Err ( Error :: local_error ( WrapperErrorKind :: UnsupportedParam ) ) ,
102- }
153+ #[ cfg( feature = "p192" ) ]
154+ impl AssociatedTpmCurve for p192:: NistP192 {
155+ const TPM_CURVE : EccCurve = EccCurve :: NistP192 ;
103156}
104157
105- // Taken from https://github.com/parallaxsecond/parsec/blob/561235f3cc37bcff3d9a6cb29c84eeae5d55100b/src/providers/tpm/utils.rs#L319
106- // Points on elliptic curves are represented as defined in section 2.3.3 of https://www.secg.org/sec1-v2.pdf
107- // The (uncompressed) representation is [ 0x04 || x || y ] where x and y are the coordinates of the point
108- fn elliptic_curve_point_to_octet_string ( mut x : Vec < u8 > , mut y : Vec < u8 > ) -> Vec < u8 > {
109- let mut octet_string = vec ! [ 0x04 ] ;
110- octet_string. append ( & mut x) ;
111- octet_string. append ( & mut y) ;
112- octet_string
158+ #[ cfg( feature = "p224" ) ]
159+ impl AssociatedTpmCurve for p224:: NistP224 {
160+ const TPM_CURVE : EccCurve = EccCurve :: NistP224 ;
113161}
114162
115- // Map TPM supported ECC curves to their respective OIDs
116- fn curve_oid ( ecc_curve : EccCurve ) -> Result < ObjectIdentifier , Error > {
117- match ecc_curve {
118- EccCurve :: NistP192 => Ok ( picky_asn1_x509:: oids:: secp192r1 ( ) ) ,
119- EccCurve :: NistP224 => Ok ( picky_asn1_x509:: oids:: secp256r1 ( ) ) ,
120- EccCurve :: NistP256 => Ok ( picky_asn1_x509:: oids:: secp256r1 ( ) ) ,
121- EccCurve :: NistP384 => Ok ( picky_asn1_x509:: oids:: secp384r1 ( ) ) ,
122- EccCurve :: NistP521 => Ok ( picky_asn1_x509:: oids:: secp521r1 ( ) ) ,
123- // Barreto-Naehrig curves seem to not have any OIDs
124- EccCurve :: BnP256 => Err ( Error :: local_error ( WrapperErrorKind :: UnsupportedParam ) ) ,
125- EccCurve :: BnP638 => Err ( Error :: local_error ( WrapperErrorKind :: UnsupportedParam ) ) ,
126- EccCurve :: Sm2P256 => Ok ( ObjectIdentifier :: try_from ( "1.2.156.10197.1.301" ) . unwrap ( ) ) ,
127- }
163+ #[ cfg( feature = "p256" ) ]
164+ impl AssociatedTpmCurve for p256:: NistP256 {
165+ const TPM_CURVE : EccCurve = EccCurve :: NistP256 ;
166+ }
167+
168+ #[ cfg( feature = "p384" ) ]
169+ impl AssociatedTpmCurve for p384:: NistP384 {
170+ const TPM_CURVE : EccCurve = EccCurve :: NistP384 ;
171+ }
172+
173+ #[ cfg( feature = "p521" ) ]
174+ impl AssociatedTpmCurve for p521:: NistP521 {
175+ const TPM_CURVE : EccCurve = EccCurve :: NistP521 ;
176+ }
177+
178+ #[ cfg( feature = "sm2" ) ]
179+ impl AssociatedTpmCurve for sm2:: Sm2 {
180+ const TPM_CURVE : EccCurve = EccCurve :: Sm2P256 ;
128181}
0 commit comments