@@ -55,11 +55,11 @@ use crate::ec::encoding::sec1::{
55
55
marshal_sec1_private_key, marshal_sec1_public_point, marshal_sec1_public_point_into_buffer,
56
56
parse_sec1_private_bn,
57
57
} ;
58
+ use crate :: ec:: evp_key_generate;
58
59
#[ cfg( feature = "fips" ) ]
59
60
use crate :: ec:: validate_ec_evp_key;
60
61
#[ cfg( not( feature = "fips" ) ) ]
61
62
use crate :: ec:: verify_evp_key_nid;
62
- use crate :: ec:: { encoding, evp_key_generate} ;
63
63
use crate :: error:: { KeyRejected , Unspecified } ;
64
64
use crate :: hex;
65
65
pub use ephemeral:: { agree_ephemeral, EphemeralPrivateKey } ;
@@ -71,6 +71,7 @@ use crate::aws_lc::{
71
71
72
72
use crate :: buffer:: Buffer ;
73
73
use crate :: ec;
74
+ use crate :: ec:: encoding:: parse_ec_public_key;
74
75
use crate :: ec:: encoding:: rfc5915:: parse_rfc5915_private_key;
75
76
use crate :: encoding:: {
76
77
AsBigEndian , AsDer , Curve25519SeedBin , EcPrivateKeyBin , EcPrivateKeyRfc5915Der ,
@@ -663,6 +664,118 @@ impl<B: AsRef<[u8]>> UnparsedPublicKey<B> {
663
664
}
664
665
}
665
666
667
+ #[ derive( Debug ) ]
668
+ /// TODO
669
+ pub struct ParsedPublicKey {
670
+ format : ParsedPublicKeyFormat ,
671
+ nid : i32 ,
672
+ key : LcPtr < EVP_PKEY > ,
673
+ }
674
+
675
+ unsafe impl Send for ParsedPublicKey { }
676
+ unsafe impl Sync for ParsedPublicKey { }
677
+
678
+ #[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
679
+ /// The format of a parsed public key.
680
+ ///
681
+ /// This is used to distinguish between different types of public key formats
682
+ /// supported by *aws-lc-rs*.
683
+ #[ non_exhaustive]
684
+ pub enum ParsedPublicKeyFormat {
685
+ /// The key is in an X.509 SubjectPublicKeyInfo format.
686
+ X509 ,
687
+ /// The key is in an uncompressed form (X9.62).
688
+ Uncompressed ,
689
+ /// The key is in a compressed form (SEC 1: Elliptic Curve Cryptography, Version 2.0).
690
+ Compressed ,
691
+ /// The key is in a raw form.
692
+ Raw ,
693
+ }
694
+
695
+ /// A parsed public key for key agreement.
696
+ impl ParsedPublicKey {
697
+ fn nid ( & self ) -> i32 {
698
+ self . nid
699
+ }
700
+
701
+ #[ allow( unused) ]
702
+ fn format ( & self ) -> ParsedPublicKeyFormat {
703
+ self . format
704
+ }
705
+
706
+ pub ( crate ) fn key ( & self ) -> & LcPtr < EVP_PKEY > {
707
+ & self . key
708
+ }
709
+
710
+ /// The algorithm of the public key.
711
+ #[ must_use]
712
+ #[ allow( non_upper_case_globals) ]
713
+ pub fn alg ( & self ) -> & ' static Algorithm {
714
+ match self . nid ( ) {
715
+ NID_X25519 => & X25519 ,
716
+ NID_X9_62_prime256v1 => & ECDH_P256 ,
717
+ NID_secp384r1 => & ECDH_P384 ,
718
+ NID_secp521r1 => & ECDH_P521 ,
719
+ _ => unreachable ! ( "Unreachable agreement algorithm nid: {}" , self . nid( ) ) ,
720
+ }
721
+ }
722
+ }
723
+
724
+ impl ParsedPublicKey {
725
+ #[ allow( non_upper_case_globals) ]
726
+ pub ( crate ) fn new ( bytes : impl AsRef < [ u8 ] > , nid : i32 ) -> Result < Self , KeyRejected > {
727
+ let key_bytes = bytes. as_ref ( ) ;
728
+ if key_bytes. is_empty ( ) {
729
+ return Err ( KeyRejected :: unspecified ( ) ) ;
730
+ }
731
+ let format = match key_bytes[ 0 ] {
732
+ 0x04 => ParsedPublicKeyFormat :: Uncompressed ,
733
+ 0x02 | 0x03 => ParsedPublicKeyFormat :: Compressed ,
734
+ _ => ParsedPublicKeyFormat :: X509 ,
735
+ } ;
736
+ match nid {
737
+ NID_X25519 => {
738
+ let pub_key = try_parse_x25519_public_key_bytes ( key_bytes) ?;
739
+ Ok ( ParsedPublicKey {
740
+ format,
741
+ nid,
742
+ key : pub_key,
743
+ } )
744
+ }
745
+ NID_X9_62_prime256v1 | NID_secp384r1 | NID_secp521r1 => {
746
+ let pub_key = parse_ec_public_key ( key_bytes, nid) ?;
747
+ Ok ( ParsedPublicKey {
748
+ format,
749
+ nid,
750
+ key : pub_key,
751
+ } )
752
+ }
753
+ _ => Err ( KeyRejected :: unspecified ( ) ) ,
754
+ }
755
+ }
756
+ }
757
+
758
+ impl < B : AsRef < [ u8 ] > > UnparsedPublicKey < B > {
759
+ #[ allow( dead_code) ]
760
+ fn parse ( & self ) -> Result < ParsedPublicKey , KeyRejected > {
761
+ ParsedPublicKey :: new ( & self . bytes , self . alg . id . nid ( ) )
762
+ }
763
+ }
764
+
765
+ impl < B : AsRef < [ u8 ] > > TryFrom < & UnparsedPublicKey < B > > for ParsedPublicKey {
766
+ type Error = KeyRejected ;
767
+ fn try_from ( upk : & UnparsedPublicKey < B > ) -> Result < Self , Self :: Error > {
768
+ upk. parse ( )
769
+ }
770
+ }
771
+
772
+ impl < B : AsRef < [ u8 ] > > TryFrom < UnparsedPublicKey < B > > for ParsedPublicKey {
773
+ type Error = KeyRejected ;
774
+ fn try_from ( upk : UnparsedPublicKey < B > ) -> Result < Self , Self :: Error > {
775
+ upk. parse ( )
776
+ }
777
+ }
778
+
666
779
/// Performs a key agreement with a private key and the given public key.
667
780
///
668
781
/// `my_private_key` is the private key to use. Only a reference to the key
@@ -692,36 +805,27 @@ impl<B: AsRef<[u8]>> UnparsedPublicKey<B> {
692
805
/// `error_value` on internal failure.
693
806
#[ inline]
694
807
#[ allow( clippy:: missing_panics_doc) ]
695
- pub fn agree < B : AsRef < [ u8 ] > , F , R , E > (
808
+ pub fn agree < B : TryInto < ParsedPublicKey > , F , R , E > (
696
809
my_private_key : & PrivateKey ,
697
- peer_public_key : & UnparsedPublicKey < B > ,
810
+ peer_public_key : B ,
698
811
error_value : E ,
699
812
kdf : F ,
700
813
) -> Result < R , E >
701
814
where
702
815
F : FnOnce ( & [ u8 ] ) -> Result < R , E > ,
703
816
{
704
817
let expected_alg = my_private_key. algorithm ( ) ;
705
- let expected_nid = expected_alg. id . nid ( ) ;
706
-
707
- if peer_public_key. alg != expected_alg {
708
- return Err ( error_value) ;
709
- }
710
818
711
- let peer_pub_bytes = peer_public_key. bytes . as_ref ( ) ;
712
-
713
- let parse_result = match & my_private_key. inner_key {
714
- KeyInner :: X25519 ( _) => try_parse_x25519_public_key_bytes ( peer_pub_bytes) ,
715
- KeyInner :: ECDH_P256 ( _) | KeyInner :: ECDH_P384 ( _) | KeyInner :: ECDH_P521 ( _) => {
716
- encoding:: parse_ec_public_key ( peer_pub_bytes, expected_nid)
717
- }
718
- } ;
819
+ let parse_result = peer_public_key. try_into ( ) ;
719
820
720
821
if let Ok ( peer_pub_key) = parse_result {
822
+ if peer_pub_key. alg ( ) != expected_alg {
823
+ return Err ( error_value) ;
824
+ }
721
825
let secret = my_private_key
722
826
. inner_key
723
827
. get_evp_pkey ( )
724
- . agree ( & peer_pub_key)
828
+ . agree ( peer_pub_key. key ( ) )
725
829
. or ( Err ( error_value) ) ?;
726
830
727
831
kdf ( secret. as_ref ( ) )
@@ -824,7 +928,7 @@ mod tests {
824
928
assert ! ( PrivateKey :: from_private_key_der( alg, test_key) . is_err( ) ) ;
825
929
assert ! ( agree(
826
930
my_private_key,
827
- & UnparsedPublicKey :: new( alg, test_key) ,
931
+ UnparsedPublicKey :: new( alg, test_key) ,
828
932
( ) ,
829
933
|_| Ok ( ( ) )
830
934
)
0 commit comments