@@ -11,6 +11,9 @@ import (
1111 "github.com/golang-fips/openssl/v2/internal/ossl"
1212)
1313
14+ const publicKeySizeX25519 = 32
15+ const privateKeySizeX25519 = 32
16+
1417type PublicKeyECDH struct {
1518 _pkey ossl.EVP_PKEY_PTR
1619 bytes []byte
@@ -30,9 +33,14 @@ func (k *PrivateKeyECDH) finalize() {
3033}
3134
3235func NewPublicKeyECDH (curve string , bytes []byte ) (* PublicKeyECDH , error ) {
33- if len (bytes ) != 1 + 2 * curveSize (curve ) {
36+ expectedLen := publicKeySizeX25519
37+ if curve != "X25519" {
38+ expectedLen = 1 + 2 * curveSize (curve )
39+ }
40+ if len (bytes ) != expectedLen {
3441 return nil , errors .New ("NewPublicKeyECDH: wrong key length" )
3542 }
43+
3644 pkey , err := newECDHPkey (curve , bytes , false )
3745 if err != nil {
3846 return nil , err
@@ -45,7 +53,11 @@ func NewPublicKeyECDH(curve string, bytes []byte) (*PublicKeyECDH, error) {
4553func (k * PublicKeyECDH ) Bytes () []byte { return k .bytes }
4654
4755func NewPrivateKeyECDH (curve string , bytes []byte ) (* PrivateKeyECDH , error ) {
48- if len (bytes ) != curveSize (curve ) {
56+ expectedLen := privateKeySizeX25519
57+ if curve != "X25519" {
58+ expectedLen = curveSize (curve )
59+ }
60+ if len (bytes ) != expectedLen {
4961 return nil , errors .New ("NewPrivateKeyECDH: wrong key length" )
5062 }
5163 pkey , err := newECDHPkey (curve , bytes , true )
@@ -65,40 +77,50 @@ func (k *PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) {
6577 }()
6678
6779 var bytes []byte
68- switch vMajor {
69- case 1 :
70- var err error
71- pkey , err = ossl .EVP_PKEY_new ()
72- if err != nil {
73- return nil , err
74- }
75- key := getECKey (k ._pkey )
76- if _ , err := ossl .EVP_PKEY_set1_EC_KEY (pkey , key ); err != nil {
77- return nil , err
78- }
79- pt := ossl .EC_KEY_get0_public_key (key )
80- if pt == nil {
81- return nil , fail ("missing ECDH public key" )
82- }
83- group := ossl .EC_KEY_get0_group (key )
84- if bytes , err = encodeEcPoint (group , pt ); err != nil {
85- return nil , err
86- }
87- case 3 :
80+ if k .curve == "X25519" {
8881 pkey = k ._pkey
8982 if _ , err := ossl .EVP_PKEY_up_ref (pkey ); err != nil {
9083 return nil , err
9184 }
92-
93- var cbytes * byte
94- n , err := ossl .EVP_PKEY_get1_encoded_public_key (k ._pkey , & cbytes )
95- if err != nil {
85+ bytes = make ([]byte , publicKeySizeX25519 )
86+ if err := extractPKEYRawPublic (pkey , bytes ); err != nil {
9687 return nil , err
9788 }
98- bytes = goBytes (unsafe .Pointer (cbytes ), n )
99- cryptoFree (unsafe .Pointer (cbytes ))
100- default :
101- panic (errUnsupportedVersion ())
89+ } else {
90+ switch vMajor {
91+ case 1 :
92+ var err error
93+ pkey , err = ossl .EVP_PKEY_new ()
94+ if err != nil {
95+ return nil , err
96+ }
97+ key := getECKey (k ._pkey )
98+ if _ , err := ossl .EVP_PKEY_set1_EC_KEY (pkey , key ); err != nil {
99+ return nil , err
100+ }
101+ pt := ossl .EC_KEY_get0_public_key (key )
102+ if pt == nil {
103+ return nil , fail ("missing ECDH public key" )
104+ }
105+ group := ossl .EC_KEY_get0_group (key )
106+ if bytes , err = encodeEcPoint (group , pt ); err != nil {
107+ return nil , err
108+ }
109+ case 3 :
110+ pkey = k ._pkey
111+ if _ , err := ossl .EVP_PKEY_up_ref (pkey ); err != nil {
112+ return nil , err
113+ }
114+ var cbytes * byte
115+ n , err := ossl .EVP_PKEY_get1_encoded_public_key (k ._pkey , & cbytes )
116+ if err != nil {
117+ return nil , err
118+ }
119+ bytes = goBytes (unsafe .Pointer (cbytes ), n )
120+ cryptoFree (unsafe .Pointer (cbytes ))
121+ default :
122+ panic (errUnsupportedVersion ())
123+ }
102124 }
103125 pub := & PublicKeyECDH {pkey , bytes }
104126 pkey = nil
@@ -107,6 +129,13 @@ func (k *PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) {
107129}
108130
109131func newECDHPkey (curve string , bytes []byte , isPrivate bool ) (ossl.EVP_PKEY_PTR , error ) {
132+ if curve == "X25519" {
133+ if isPrivate {
134+ return ossl .EVP_PKEY_new_raw_private_key (ossl .EVP_PKEY_X25519 , nil , base (bytes ), len (bytes ))
135+ } else {
136+ return ossl .EVP_PKEY_new_raw_public_key (ossl .EVP_PKEY_X25519 , nil , base (bytes ), len (bytes ))
137+ }
138+ }
110139 nid := curveNID (curve )
111140 switch vMajor {
112141 case 1 :
@@ -260,7 +289,7 @@ func ECDH(priv *PrivateKeyECDH, pub *PublicKeyECDH) ([]byte, error) {
260289}
261290
262291func GenerateKeyECDH (curve string ) (* PrivateKeyECDH , []byte , error ) {
263- pkey , err := generateEVPPKey (ossl . EVP_PKEY_EC , 0 , curve )
292+ pkey , err := generateEVPPKey (curveID ( curve ) , 0 , curve )
264293 if err != nil {
265294 return nil , nil , err
266295 }
@@ -270,34 +299,43 @@ func GenerateKeyECDH(curve string) (*PrivateKeyECDH, []byte, error) {
270299 ossl .EVP_PKEY_free (pkey )
271300 }
272301 }()
273- var priv ossl.BIGNUM_PTR
274- switch vMajor {
275- case 1 :
276- key := getECKey (pkey )
277- priv = ossl .EC_KEY_get0_private_key (key )
278- if priv == nil {
279- return nil , nil , fail ("missing ECDH private key" )
302+ var bytes []byte
303+ if curve == "X25519" {
304+ bytes = make ([]byte , privateKeySizeX25519 )
305+ keylen := len (bytes )
306+ if _ , err := ossl .EVP_PKEY_get_raw_private_key (pkey , base (bytes ), & keylen ); err != nil {
307+ return nil , nil , err
280308 }
281- case 3 :
282- if _ , err := ossl .EVP_PKEY_get_bn_param (pkey , _OSSL_PKEY_PARAM_PRIV_KEY .ptr (), & priv ); err != nil {
309+ } else {
310+ var priv ossl.BIGNUM_PTR
311+ switch vMajor {
312+ case 1 :
313+ key := getECKey (pkey )
314+ priv = ossl .EC_KEY_get0_private_key (key )
315+ if priv == nil {
316+ return nil , nil , fail ("missing ECDH private key" )
317+ }
318+ case 3 :
319+ if _ , err := ossl .EVP_PKEY_get_bn_param (pkey , _OSSL_PKEY_PARAM_PRIV_KEY .ptr (), & priv ); err != nil {
320+ return nil , nil , err
321+ }
322+ defer ossl .BN_clear_free (priv )
323+ default :
324+ panic (errUnsupportedVersion ())
325+ }
326+ // We should not leak bit length of the secret scalar in the key.
327+ // For this reason, we use BN_bn2binpad instead of BN_bn2bin with fixed length.
328+ // The fixed length is the order of the large prime subgroup of the curve,
329+ // returned by EVP_PKEY_get_bits, which is generally the upper bound for
330+ // generating a private ECDH key.
331+ bits , err := ossl .EVP_PKEY_get_bits (pkey )
332+ if err != nil {
333+ return nil , nil , err
334+ }
335+ bytes = make ([]byte , (bits + 7 )/ 8 )
336+ if err := bnToBinPad (priv , bytes ); err != nil {
283337 return nil , nil , err
284338 }
285- defer ossl .BN_clear_free (priv )
286- default :
287- panic (errUnsupportedVersion ())
288- }
289- // We should not leak bit length of the secret scalar in the key.
290- // For this reason, we use BN_bn2binpad instead of BN_bn2bin with fixed length.
291- // The fixed length is the order of the large prime subgroup of the curve,
292- // returned by EVP_PKEY_get_bits, which is generally the upper bound for
293- // generating a private ECDH key.
294- bits , err := ossl .EVP_PKEY_get_bits (pkey )
295- if err != nil {
296- return nil , nil , err
297- }
298- bytes := make ([]byte , (bits + 7 )/ 8 )
299- if err := bnToBinPad (priv , bytes ); err != nil {
300- return nil , nil , err
301339 }
302340 k = & PrivateKeyECDH {pkey , curve }
303341 runtime .SetFinalizer (k , (* PrivateKeyECDH ).finalize )
0 commit comments