@@ -20,6 +20,87 @@ pub struct Ed25519PrivateKey {
2020 algo : SignatureAlgorithm ,
2121}
2222
23+ impl Ed25519PrivateKey {
24+ /// Extract ED25519 private and if available public key values from a PKCS#8 DER formatted key
25+ fn extract_key_pair ( input_key : & [ u8 ] ) -> Result < ( [ u8 ; 32 ] , Option < [ u8 ; 32 ] > ) , rustls:: Error > {
26+ let mut public_key_raw: [ u8 ; 32 ] = [ 0 ; ED25519_PUB_KEY_SIZE as usize ] ;
27+ let mut private_key_raw: [ u8 ; 32 ] = [ 0 ; ED25519_KEY_SIZE as usize ] ;
28+ let mut skip_bytes: usize ;
29+ let mut key_sub_slice = input_key;
30+
31+ const SHORT_FORM_LEN_MAX : u8 = 127 ;
32+ const TAG_SEQUENCE : u8 = 0x30 ;
33+ const TAG_OCTET_SEQUENCE : u8 = 0x04 ;
34+ const TAG_OPTIONAL_SET_OF_ATTRIBUTES : u8 = 0x80 ; //Implicit, context-specific, and primitive underlying type (SET OF)
35+ const TAG_OPTIONAL_PUBLIC_KEY_BIT_STRING : u8 = 0x81 ; //Implicit, context-specific, and primitive underlying type (BIT STRING)
36+
37+ // The input key is encoded in PKCS#8 DER format with a structure as in
38+ // https://www.rfc-editor.org/rfc/rfc5958.html
39+ //
40+ // AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey
41+
42+ // OneAsymmetricKey ::= SEQUENCE {
43+ // version Version,
44+ // privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
45+ // privateKey PrivateKey,
46+ // attributes [0] Attributes OPTIONAL,
47+ // ...,
48+ // [[2: publicKey [1] PublicKey OPTIONAL ]],
49+ // ...
50+ // }
51+
52+ // The key structure must begin with a SEQUENCE tag with at least 2 bytes length if short
53+ // length format is used
54+ if key_sub_slice[ 0 ] != TAG_SEQUENCE || key_sub_slice. len ( ) < 2 {
55+ return Err ( rustls:: Error :: General (
56+ "Faulty PKCS#8 ED25519 private key structure" . into ( ) ,
57+ ) ) ;
58+ }
59+ // Check which length format and skip tag and length encoding bytes
60+ if key_sub_slice[ 1 ] > SHORT_FORM_LEN_MAX {
61+ skip_bytes = ( 2 + ( key_sub_slice[ 1 ] & 0x7F ) ) as usize ;
62+ } else {
63+ skip_bytes = 2 ;
64+ }
65+
66+ // Skip version (3 bytes), algorithm ID sequence (0x30 + length encoding bytes + 5 ID bytes),
67+ skip_bytes += 3 + 7 ;
68+ key_sub_slice = input_key. get ( skip_bytes..) . unwrap ( ) ;
69+
70+ // Check if next bytes are 0x04, 0x22, 0x04, 0x20
71+ if !matches ! (
72+ key_sub_slice,
73+ [ TAG_OCTET_SEQUENCE , 0x22 , TAG_OCTET_SEQUENCE , 0x20 , ..]
74+ ) {
75+ return Err ( rustls:: Error :: General (
76+ "Faulty PKCS#8 ED25519 private key structure" . into ( ) ,
77+ ) ) ;
78+ }
79+
80+ // Copy private key value
81+ skip_bytes += 4 ;
82+ key_sub_slice = input_key. get ( skip_bytes..) . unwrap ( ) ;
83+ private_key_raw. copy_from_slice ( & key_sub_slice[ ..ED25519_KEY_SIZE as usize ] ) ;
84+ skip_bytes += ED25519_KEY_SIZE as usize ;
85+ key_sub_slice = input_key. get ( skip_bytes..) . unwrap ( ) ;
86+
87+ // Check if optional SET OF attributes exists and skip
88+ if key_sub_slice[ 0 ] == TAG_OPTIONAL_SET_OF_ATTRIBUTES {
89+ skip_bytes += ( 2 + ( key_sub_slice[ 1 ] ) ) as usize ;
90+ key_sub_slice = input_key. get ( skip_bytes..) . unwrap ( ) ;
91+ }
92+
93+ // Check if optional public key value exists. If exists, skip tag, length encoding byte,
94+ // and bits-used byte
95+ if key_sub_slice[ 0 ] == TAG_OPTIONAL_PUBLIC_KEY_BIT_STRING {
96+ public_key_raw. copy_from_slice ( & key_sub_slice[ 3 ..( 3 + ED25519_KEY_SIZE as usize ) ] ) ;
97+ Ok ( ( private_key_raw, Some ( public_key_raw) ) )
98+ } else {
99+ Ok ( ( private_key_raw, None ) )
100+ }
101+ }
102+ }
103+
23104impl TryFrom < & PrivateKeyDer < ' _ > > for Ed25519PrivateKey {
24105 type Error = rustls:: Error ;
25106
@@ -28,57 +109,35 @@ impl TryFrom<&PrivateKeyDer<'_>> for Ed25519PrivateKey {
28109 PrivateKeyDer :: Pkcs8 ( der) => {
29110 let mut ed25519_c_type: ed25519_key = unsafe { mem:: zeroed ( ) } ;
30111 let ed25519_key_object = ED25519KeyObject :: new ( & mut ed25519_c_type) ;
31- let mut priv_key_raw: [ u8 ; 32 ] = [ 0 ; 32 ] ;
32- let mut priv_key_raw_len: word32 = priv_key_raw. len ( ) as word32 ;
33- let mut pub_key_raw: [ u8 ; 32 ] = [ 0 ; 32 ] ;
34- let pub_key_raw_len: word32 = pub_key_raw. len ( ) as word32 ;
112+ let mut pub_raw: [ u8 ; 32 ] = [ 0 ; 32 ] ;
113+ let pub_key_raw_len: word32 = pub_raw. len ( ) as word32 ;
35114 let pkcs8: & [ u8 ] = der. secret_pkcs8_der ( ) ;
36- let pkcs8_sz: word32 = pkcs8. len ( ) as word32 ;
37- let mut ret;
115+ let ( priv_key_raw, pub_key_raw) = match Ed25519PrivateKey :: extract_key_pair ( pkcs8) {
116+ Ok ( ( priv_raw, pub_raw) ) => ( priv_raw, pub_raw) ,
117+
118+ Err ( error) => return Err ( error) ,
119+ } ;
38120
39121 // This function initiliazes an ed25519_key object for
40122 // using it to sign a message.
41123 ed25519_key_object. init ( ) ;
42124
43- let mut idx: u32 = 0 ;
44-
45- // This function reads in an ED25519 private key from the input buffer, input,
46- // parses the private key, and uses it to generate an ed25519_key object,
47- // which it stores in key.
48- ret = unsafe {
49- wc_Ed25519PrivateKeyDecode (
50- pkcs8. as_ptr ( ) as * mut u8 ,
51- & mut idx,
52- ed25519_key_object. as_ptr ( ) ,
53- pkcs8_sz,
54- )
55- } ;
56- check_if_zero ( ret)
57- . map_err ( |_| rustls:: Error :: General ( "FFI function failed" . into ( ) ) ) ?;
58-
59- ret = unsafe {
60- wc_ed25519_make_public (
61- ed25519_key_object. as_ptr ( ) ,
62- pub_key_raw. as_mut_ptr ( ) ,
63- pub_key_raw_len,
64- )
65- } ;
66- check_if_zero ( ret)
67- . map_err ( |_| rustls:: Error :: General ( "FFI function failed" . into ( ) ) ) ?;
68-
69- ret = unsafe {
70- wc_ed25519_export_private_only (
71- ed25519_key_object. as_ptr ( ) ,
72- priv_key_raw. as_mut_ptr ( ) ,
73- & mut priv_key_raw_len,
74- )
75- } ;
76- check_if_zero ( ret)
77- . map_err ( |_| rustls:: Error :: General ( "FFI function failed" . into ( ) ) ) ?;
125+ // Generate pub key part if not given
126+ if pub_key_raw. is_none ( ) {
127+ let ret = unsafe {
128+ wc_ed25519_make_public (
129+ ed25519_key_object. as_ptr ( ) ,
130+ pub_raw. as_mut_ptr ( ) ,
131+ pub_key_raw_len,
132+ )
133+ } ;
134+ check_if_zero ( ret)
135+ . map_err ( |_| rustls:: Error :: General ( "FFI function failed" . into ( ) ) ) ?;
136+ }
78137
79138 Ok ( Self {
80139 priv_key : Arc :: new ( priv_key_raw. to_vec ( ) ) ,
81- pub_key : Arc :: new ( pub_key_raw . to_vec ( ) ) ,
140+ pub_key : Arc :: new ( pub_raw . to_vec ( ) ) ,
82141 algo : SignatureAlgorithm :: ED25519 ,
83142 } )
84143 }
0 commit comments