@@ -23,13 +23,22 @@ import (
2323 "sync/atomic"
2424 "time"
2525
26+ "github_com/cloudflare/p751sidh"
2627 "golang_org/x/crypto/curve25519"
2728)
2829
2930// numSessionTickets is the number of different session tickets the
3031// server sends to a TLS 1.3 client, who will use each only once.
3132const numSessionTickets = 2
3233
34+ // In SIDH, the computations done by Alice are different from Bob's.
35+ type dhRole bool
36+
37+ const (
38+ dhRoleServer dhRole = true
39+ dhRoleClient dhRole = false
40+ )
41+
3342func (hs * serverHandshakeState ) doTLS13Handshake () error {
3443 config := hs .c .config
3544 c := hs .c
@@ -61,7 +70,7 @@ CurvePreferenceLoop:
6170 }
6271 }
6372
64- privateKey , serverKS , err := config .generateKeyShare (ks .group )
73+ privateKey , serverKS , err := config .generateKeyShare (ks .group , dhRoleServer )
6574 if err != nil {
6675 c .sendAlert (alertInternalError )
6776 return err
@@ -93,8 +102,8 @@ CurvePreferenceLoop:
93102 handshakeCtx := hs .finishedHash13 .Sum (nil )
94103 earlyClientCipher , _ := hs .suite .prepareCipher (handshakeCtx , earlySecret , "client early traffic secret" )
95104
96- ecdheSecret := deriveECDHESecret (ks , privateKey )
97- if ecdheSecret == nil {
105+ dheSecret := deriveDHESecret (ks , privateKey , dhRoleServer )
106+ if dheSecret == nil {
98107 c .sendAlert (alertIllegalParameter )
99108 return errors .New ("tls: bad ECDHE client share" )
100109 }
@@ -104,7 +113,7 @@ CurvePreferenceLoop:
104113 return err
105114 }
106115
107- handshakeSecret := hkdfExtract (hash , ecdheSecret , earlySecret )
116+ handshakeSecret := hkdfExtract (hash , dheSecret , earlySecret )
108117 handshakeCtx = hs .finishedHash13 .Sum (nil )
109118 clientCipher , cTrafficSecret := hs .suite .prepareCipher (handshakeCtx , handshakeSecret , "client handshake traffic secret" )
110119 hs .hsClientCipher = clientCipher
@@ -367,7 +376,38 @@ func prepareDigitallySigned(hash crypto.Hash, context string, data []byte) []byt
367376 return h .Sum (nil )
368377}
369378
370- func (c * Config ) generateKeyShare (curveID CurveID ) ([]byte , keyShare , error ) {
379+ func (c * Config ) generateKeyShare (curveID CurveID , role dhRole ) ([]byte , keyShare , error ) {
380+ if curveID == SIDHP751AndX25519 {
381+ var scalarX25519 , publicX25519 [32 ]byte
382+ if _ , err := io .ReadFull (c .rand (), scalarX25519 [:]); err != nil {
383+ return nil , keyShare {}, err
384+ }
385+ curve25519 .ScalarBaseMult (& publicX25519 , & scalarX25519 )
386+
387+ var secret [32 + p751sidh .SecretKeySize ]byte
388+ var public [32 + p751sidh .PublicKeySize ]byte
389+ copy (secret [:32 ], scalarX25519 [:])
390+ copy (public [:32 ], publicX25519 [:])
391+
392+ // Alice's computations are slightly cheaper, so we use them on the server.
393+ if role == dhRoleServer {
394+ var publicSIDH , secretSIDH , err = p751sidh .GenerateAliceKeypair (c .rand ())
395+ if err != nil {
396+ return nil , keyShare {}, err
397+ }
398+ copy (secret [32 :], secretSIDH .Scalar [:])
399+ publicSIDH .ToBytes (public [32 :])
400+ } else {
401+ var publicSIDH , secretSIDH , err = p751sidh .GenerateBobKeypair (c .rand ())
402+ if err != nil {
403+ return nil , keyShare {}, err
404+ }
405+ copy (secret [32 :], secretSIDH .Scalar [:])
406+ publicSIDH .ToBytes (public [32 :])
407+ }
408+
409+ return secret [:], keyShare {group : curveID , data : public [:]}, nil
410+ }
371411 if curveID == X25519 {
372412 var scalar , public [32 ]byte
373413 if _ , err := io .ReadFull (c .rand (), scalar [:]); err != nil {
@@ -392,7 +432,48 @@ func (c *Config) generateKeyShare(curveID CurveID) ([]byte, keyShare, error) {
392432 return privateKey , keyShare {group : curveID , data : ecdhePublic }, nil
393433}
394434
395- func deriveECDHESecret (ks keyShare , secretKey []byte ) []byte {
435+ func deriveDHESecret (ks keyShare , secretKey []byte , role dhRole ) []byte {
436+ if ks .group == SIDHP751AndX25519 {
437+ if len (ks .data ) != 32 + p751sidh .PublicKeySize {
438+ return nil
439+ }
440+ if len (secretKey ) != 32 + p751sidh .SecretKeySize {
441+ return nil
442+ }
443+
444+ var theirX25519Public , sharedX25519Secret , ourX25519Secret [32 ]byte
445+ copy (theirX25519Public [:], ks .data [:32 ])
446+ copy (ourX25519Secret [:], secretKey [:32 ])
447+ curve25519 .ScalarMult (& sharedX25519Secret , & ourX25519Secret , & theirX25519Public )
448+
449+ var sharedSIDHSecret [p751sidh .SharedSecretSize ]byte
450+
451+ // Alice's computations are slightly cheaper, so we use them on the server.
452+ if role == dhRoleServer {
453+ var theirSIDHPublic p751sidh.SIDHPublicKeyBob
454+ theirSIDHPublic .FromBytes (ks .data [32 :])
455+
456+ var ourSIDHSecret p751sidh.SIDHSecretKeyAlice
457+ copy (ourSIDHSecret .Scalar [:], secretKey [32 :])
458+
459+ sharedSIDHSecret = ourSIDHSecret .SharedSecret (& theirSIDHPublic )
460+ } else {
461+ var theirSIDHPublic p751sidh.SIDHPublicKeyAlice
462+ theirSIDHPublic .FromBytes (ks .data [32 :])
463+
464+ var ourSIDHSecret p751sidh.SIDHSecretKeyBob
465+ copy (ourSIDHSecret .Scalar [:], secretKey [32 :])
466+
467+ sharedSIDHSecret = ourSIDHSecret .SharedSecret (& theirSIDHPublic )
468+ }
469+
470+ var sharedSecret [32 + p751sidh .SharedSecretSize ]byte
471+ copy (sharedSecret [:32 ], sharedX25519Secret [:])
472+ copy (sharedSecret [32 :], sharedSIDHSecret [:])
473+
474+ return sharedSecret [:]
475+ }
476+
396477 if ks .group == X25519 {
397478 if len (ks .data ) != 32 {
398479 return nil
@@ -730,7 +811,7 @@ func (hs *clientHandshakeState) startTLS13ClientHandshake() error {
730811 // forces handling the case of an extra round trip
731812
732813 var preferredCurve = hello .supportedCurves [0 ]
733- privateKey , clientKeyShare , err := config .generateKeyShare (preferredCurve )
814+ privateKey , clientKeyShare , err := config .generateKeyShare (preferredCurve , dhRoleClient )
734815 if err != nil {
735816 return err
736817 }
@@ -783,15 +864,15 @@ func (hs *clientHandshakeState) doTLS13ClientHandshake() error {
783864 earlySecret := hkdfExtract (hash , nil , nil )
784865
785866 serverKeyShare := hs .serverHello13 .keyShare
786- ecdheSecret := deriveECDHESecret (serverKeyShare , hs .keySharePrivateKey )
787- if ecdheSecret == nil {
867+ dheSecret := deriveDHESecret (serverKeyShare , hs .keySharePrivateKey , dhRoleClient )
868+ if dheSecret == nil {
788869 c .sendAlert (alertIllegalParameter )
789870 return errors .New ("tls: bad ECDHE client share" )
790871 }
791872
792873 hs .finishedHash13 .Write (hs .serverHello13 .marshal ())
793874
794- handshakeSecret := hkdfExtract (hash , ecdheSecret , earlySecret )
875+ handshakeSecret := hkdfExtract (hash , dheSecret , earlySecret )
795876 handshakeCtx := hs .finishedHash13 .Sum (nil )
796877 clientCipher , cTrafficSecret := suite .prepareCipher (handshakeCtx , handshakeSecret , "client handshake traffic secret" )
797878 serverCipher , sTrafficSecret := suite .prepareCipher (handshakeCtx , handshakeSecret , "server handshake traffic secret" )
0 commit comments