Skip to content

Commit 9eda340

Browse files
committed
fix(tls): TLS12 ecdh params
1 parent e41bc99 commit 9eda340

File tree

3 files changed

+114
-52
lines changed

3 files changed

+114
-52
lines changed

tls/key_agreement.go

+26-16
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"crypto"
99
"crypto/dsa"
1010
"crypto/ecdsa"
11+
"crypto/elliptic"
1112
"crypto/md5"
1213
"crypto/rand"
1314
"crypto/rsa"
@@ -33,20 +34,6 @@ type keyAgreementAuthentication interface {
3334
verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) ([]byte, error)
3435
}
3536

36-
// nilKeyAgreementAuthentication does not authenticate the key
37-
// agreement parameters.
38-
type nilKeyAgreementAuthentication struct{}
39-
40-
func (ka *nilKeyAgreementAuthentication) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
41-
skx := new(serverKeyExchangeMsg)
42-
skx.key = params
43-
return skx, nil
44-
}
45-
46-
func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) ([]byte, error) {
47-
return nil, nil
48-
}
49-
5037
// signedKeyAgreement signs the ServerKeyExchange parameters with the
5138
// server's private key.
5239
type signedKeyAgreement struct {
@@ -382,7 +369,8 @@ func pickTLS12HashForSignature(sigType uint8, clientList, serverList []SigAndHas
382369
// pre-master secret is then calculated using ECDH. The signature may
383370
// be ECDSA, Ed25519 or RSA.
384371
type ecdheKeyAgreement struct {
385-
auth keyAgreementAuthentication
372+
auth keyAgreementAuthentication
373+
serverParams ecdheParameters
386374

387375
version uint16
388376
isRSA bool
@@ -417,6 +405,7 @@ func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Cer
417405
return nil, err
418406
}
419407
ka.params = params
408+
ka.serverParams.Clone()
420409

421410
// See RFC 4492, Section 5.4.
422411
ecdhePublic := params.PublicKey()
@@ -495,6 +484,20 @@ func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Cert
495484
return nil, errClientKeyExchange
496485
}
497486

487+
// This part is solely for logging purposes. Later in MakeLog(), we only have access to ka.params
488+
// for the client key exchange parameters. We need to store the client's public key here
489+
// to make the log later. The Go TLS library doesn't store the parsed client public key anywhere.
490+
ka.params = nil
491+
if ka.serverParams.CurveID() == X25519 {
492+
ka.params = &x25519Parameters{publicKey: ckx.ciphertext[1:]}
493+
} else {
494+
curve, ok := curveForCurveID(ka.serverParams.CurveID())
495+
if ok {
496+
x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:])
497+
ka.params = &nistParameters{x: x, y: y, curveID: ka.serverParams.CurveID()}
498+
}
499+
}
500+
498501
return preMasterSecret, nil
499502
}
500503

@@ -519,8 +522,15 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
519522
return errServerKeyExchange
520523
}
521524

522-
if _, ok := curveForCurveID(curveID); curveID != X25519 && !ok {
525+
if curve, ok := curveForCurveID(curveID); curveID != X25519 && !ok {
523526
return errors.New("tls: server selected unsupported curve")
527+
} else {
528+
if curveID == X25519 {
529+
ka.serverParams = &x25519Parameters{publicKey: publicKey}
530+
} else {
531+
x, y := elliptic.Unmarshal(curve, publicKey)
532+
ka.serverParams = &nistParameters{x: x, y: y, curveID: curveID}
533+
}
524534
}
525535

526536
params, err := generateECDHEParameters(config.rand(), curveID)

tls/key_schedule.go

+82
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"io"
1313
"math/big"
1414

15+
jsonKeys "github.com/zmap/zcrypto/json"
1516
"golang.org/x/crypto/cryptobyte"
1617
"golang.org/x/crypto/curve25519"
1718
"golang.org/x/crypto/hkdf"
@@ -107,6 +108,9 @@ type ecdheParameters interface {
107108
CurveID() CurveID
108109
PublicKey() []byte
109110
SharedKey(peerPublicKey []byte) []byte
111+
112+
Clone() ecdheParameters
113+
MakeLog() (*jsonKeys.ECPoint, *jsonKeys.ECDHPrivateParams)
110114
}
111115

112116
func generateECDHEParameters(rand io.Reader, curveID CurveID) (ecdheParameters, error) {
@@ -177,6 +181,49 @@ func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte {
177181
return xShared.FillBytes(sharedKey)
178182
}
179183

184+
func (p *nistParameters) Clone() ecdheParameters {
185+
clone := *p
186+
187+
if p.privateKey != nil {
188+
clone.privateKey = make([]byte, len(p.privateKey))
189+
copy(clone.privateKey, p.privateKey)
190+
}
191+
192+
if p.x != nil {
193+
clone.x = new(big.Int).Set(p.x)
194+
}
195+
196+
if p.y != nil {
197+
clone.y = new(big.Int).Set(p.y)
198+
}
199+
200+
return &clone
201+
}
202+
203+
func (p *nistParameters) MakeLog() (*jsonKeys.ECPoint, *jsonKeys.ECDHPrivateParams) {
204+
public := new(jsonKeys.ECPoint)
205+
206+
if p.x != nil {
207+
public.X = new(big.Int)
208+
public.X.Set(p.x)
209+
}
210+
211+
if p.y != nil {
212+
public.Y = new(big.Int)
213+
public.Y.Set(p.y)
214+
}
215+
216+
var private *jsonKeys.ECDHPrivateParams
217+
if len(p.privateKey) > 0 {
218+
private = new(jsonKeys.ECDHPrivateParams)
219+
private.Length = len(p.privateKey)
220+
private.Value = make([]byte, len(p.privateKey))
221+
copy(private.Value, p.privateKey)
222+
}
223+
224+
return public, private
225+
}
226+
180227
type x25519Parameters struct {
181228
privateKey []byte
182229
publicKey []byte
@@ -197,3 +244,38 @@ func (p *x25519Parameters) SharedKey(peerPublicKey []byte) []byte {
197244
}
198245
return sharedKey
199246
}
247+
248+
func (p *x25519Parameters) Clone() ecdheParameters {
249+
clone := *p
250+
251+
if p.privateKey != nil {
252+
clone.privateKey = make([]byte, len(p.privateKey))
253+
copy(clone.privateKey, p.privateKey)
254+
}
255+
256+
if p.publicKey != nil {
257+
clone.publicKey = make([]byte, len(p.publicKey))
258+
copy(clone.publicKey, p.publicKey)
259+
}
260+
261+
return &clone
262+
}
263+
264+
func (p *x25519Parameters) MakeLog() (*jsonKeys.ECPoint, *jsonKeys.ECDHPrivateParams) {
265+
public := new(jsonKeys.ECPoint)
266+
267+
if p.publicKey != nil {
268+
public.X = new(big.Int)
269+
public.X.SetBytes(p.publicKey)
270+
}
271+
272+
var private *jsonKeys.ECDHPrivateParams
273+
if len(p.privateKey) > 0 {
274+
private = new(jsonKeys.ECDHPrivateParams)
275+
private.Length = len(p.privateKey)
276+
private.Value = make([]byte, len(p.privateKey))
277+
copy(private.Value, p.privateKey)
278+
}
279+
280+
return public, private
281+
}

tls/tls_ka.go

+6-36
Original file line numberDiff line numberDiff line change
@@ -90,54 +90,24 @@ func (ka *signedKeyAgreement) Signature() *DigitalSignature {
9090

9191
func (ka *rsaKeyAgreement) RSAParams() *jsonKeys.RSAPublicKey {
9292
out := new(jsonKeys.RSAPublicKey)
93-
//out.PublicKey = ka.publicKey
9493
return out
9594
}
9695

9796
func (ka *ecdheKeyAgreement) ECDHParams() *jsonKeys.ECDHParams {
9897
out := new(jsonKeys.ECDHParams)
99-
out.TLSCurveID = jsonKeys.TLSCurveID(ka.params.CurveID())
100-
out.ServerPublic = &jsonKeys.ECPoint{}
101-
/*
102-
if ka.x != nil {
103-
out.ServerPublic.X = new(big.Int)
104-
out.ServerPublic.X.Set(ka.x)
105-
}
106-
if ka.y != nil {
107-
out.ServerPublic.Y = new(big.Int)
108-
out.ServerPublic.Y.Set(ka.y)
109-
}
110-
if len(ka.serverPrivKey) > 0 {
111-
out.ServerPrivate = new(jsonKeys.ECDHPrivateParams)
112-
out.ServerPrivate.Length = len(ka.serverPrivKey)
113-
out.ServerPrivate.Value = make([]byte, len(ka.serverPrivKey))
114-
copy(out.ServerPrivate.Value, ka.serverPrivKey)
115-
}
116-
*/
98+
out.TLSCurveID = jsonKeys.TLSCurveID(ka.serverParams.CurveID())
99+
100+
out.ServerPublic, out.ServerPrivate = ka.serverParams.MakeLog()
101+
117102
return out
118103
}
119104

120105
func (ka *ecdheKeyAgreement) ClientECDHParams() *jsonKeys.ECDHParams {
121106
out := new(jsonKeys.ECDHParams)
122107
out.TLSCurveID = jsonKeys.TLSCurveID(ka.params.CurveID())
123-
out.ClientPublic = &jsonKeys.ECPoint{}
124-
/*
125-
if ka.clientX != nil {
126-
out.ClientPublic.X = new(big.Int)
127-
out.ClientPublic.X.Set(ka.clientX)
128-
}
129-
if ka.clientY != nil {
130-
out.ClientPublic.Y = new(big.Int)
131-
out.ClientPublic.Y.Set(ka.clientY)
132-
}
133108

134-
if len(ka.clientPrivKey) > 0 {
135-
out.ClientPrivate = new(jsonKeys.ECDHPrivateParams)
136-
out.ClientPrivate.Length = len(ka.clientPrivKey)
137-
out.ClientPrivate.Value = make([]byte, len(ka.clientPrivKey))
138-
copy(out.ClientPrivate.Value, ka.clientPrivKey)
139-
}
140-
*/
109+
out.ClientPublic, out.ClientPrivate = ka.params.MakeLog()
110+
141111
return out
142112
}
143113

0 commit comments

Comments
 (0)