Skip to content

Commit e296a6b

Browse files
committed
crypto/tls: add cipher suites TLS_ECDHE_PSK
1 parent 160414c commit e296a6b

8 files changed

+376
-68
lines changed

src/crypto/tls/cipher_suites.go

+45-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"crypto/rc4"
1515
"crypto/sha1"
1616
"crypto/sha256"
17+
"crypto/sha512"
1718
"fmt"
1819
"hash"
1920
"internal/cpu"
@@ -69,8 +70,12 @@ func CipherSuites() []*CipherSuite {
6970
{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false},
7071
{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false},
7172
{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false},
73+
{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", supportedOnlyTLS12, false},
74+
{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", supportedOnlyTLS12, false},
75+
{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", supportedOnlyTLS12, false},
7276
{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false},
7377
{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false},
78+
{TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false},
7479
}
7580
}
7681

@@ -91,6 +96,7 @@ func InsecureCipherSuites() []*CipherSuite {
9196
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true},
9297
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true},
9398
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true},
99+
{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true},
94100
}
95101
}
96102

@@ -128,6 +134,9 @@ const (
128134
// suiteSHA384 indicates that the cipher suite uses SHA384 as the
129135
// handshake hash.
130136
suiteSHA384
137+
// suiteNoCerts indicates that the cipher suite doesn't use certificate exchange
138+
// (anonymous ciphersuites or pre-shared-secret)
139+
suiteNoCerts
131140
)
132141

133142
// A cipherSuite is a TLS 1.0–1.2 cipher suite, and defines the key exchange
@@ -169,6 +178,12 @@ var cipherSuites = []*cipherSuite{ // TODO: replace with a map, since the order
169178
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil},
170179
{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil},
171180
{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherRC4, macSHA1, nil},
181+
182+
{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdhePSKKA, suiteECDHE | suiteTLS12 | suiteNoCerts, cipherAES, macSHA1, nil},
183+
{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdhePSKKA, suiteECDHE | suiteTLS12 | suiteNoCerts, cipherAES, macSHA256, nil},
184+
{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdhePSKKA, suiteECDHE | suiteTLS12 | suiteNoCerts, cipherAES, macSHA1, nil},
185+
{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdhePSKKA, suiteECDHE | suiteTLS12 | suiteSHA384 | suiteNoCerts, cipherAES, macSHA384, nil},
186+
{TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdhePSKKA, suiteECDHE | suiteTLS12 | suiteNoCerts, nil, nil, aeadChaCha20Poly1305},
172187
}
173188

174189
// selectCipherSuite returns the first TLS 1.0–1.2 cipher suite from ids which
@@ -272,11 +287,12 @@ var cipherSuitesPreferenceOrder = []uint16{
272287
// AEADs w/ ECDHE
273288
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
274289
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
275-
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
290+
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
276291

277292
// CBC w/ ECDHE
278-
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
279-
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
293+
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
294+
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
295+
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
280296

281297
// AEADs w/o ECDHE
282298
TLS_RSA_WITH_AES_128_GCM_SHA256,
@@ -292,6 +308,7 @@ var cipherSuitesPreferenceOrder = []uint16{
292308

293309
// CBC_SHA256
294310
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
311+
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
295312
TLS_RSA_WITH_AES_128_CBC_SHA256,
296313

297314
// RC4
@@ -301,22 +318,27 @@ var cipherSuitesPreferenceOrder = []uint16{
301318

302319
var cipherSuitesPreferenceOrderNoAES = []uint16{
303320
// ChaCha20Poly1305
304-
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
321+
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
305322

306323
// AES-GCM w/ ECDHE
307324
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
308325
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
309326

310327
// The rest of cipherSuitesPreferenceOrder.
311-
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
312-
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
328+
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
329+
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
330+
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
331+
313332
TLS_RSA_WITH_AES_128_GCM_SHA256,
314333
TLS_RSA_WITH_AES_256_GCM_SHA384,
315334
TLS_RSA_WITH_AES_128_CBC_SHA,
316335
TLS_RSA_WITH_AES_256_CBC_SHA,
336+
317337
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
318338
TLS_RSA_WITH_3DES_EDE_CBC_SHA,
339+
319340
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
341+
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
320342
TLS_RSA_WITH_AES_128_CBC_SHA256,
321343
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA,
322344
TLS_RSA_WITH_RC4_128_SHA,
@@ -327,6 +349,7 @@ var cipherSuitesPreferenceOrderNoAES = []uint16{
327349
var disabledCipherSuites = []uint16{
328350
// CBC_SHA256
329351
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
352+
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
330353
TLS_RSA_WITH_AES_128_CBC_SHA256,
331354

332355
// RC4
@@ -437,6 +460,11 @@ func macSHA256(key []byte) hash.Hash {
437460
return hmac.New(sha256.New, key)
438461
}
439462

463+
// macSHA384 returns a SHA-384 based MAC.
464+
func macSHA384(key []byte) hash.Hash {
465+
return hmac.New(sha512.New384, key)
466+
}
467+
440468
type aead interface {
441469
cipher.AEAD
442470

@@ -619,6 +647,12 @@ func ecdheRSAKA(version uint16) keyAgreement {
619647
}
620648
}
621649

650+
func ecdhePSKKA(version uint16) keyAgreement {
651+
return &ecdhePskKeyAgreement{
652+
version: version,
653+
}
654+
}
655+
622656
// mutualCipherSuite returns a cipherSuite given a list of supported
623657
// ciphersuites and the id requested by the peer.
624658
func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
@@ -683,8 +717,13 @@ const (
683717
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
684718
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
685719
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c
720+
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xc035
721+
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xc036
722+
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xc037
723+
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xc038
686724
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca8
687725
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca9
726+
TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xccac
688727

689728
// TLS 1.3 cipher suites.
690729
TLS_AES_128_GCM_SHA256 uint16 = 0x1301

src/crypto/tls/common.go

+4
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,9 @@ type Config struct {
723723
// used for debugging.
724724
KeyLogWriter io.Writer
725725

726+
// Extra is used to hold extra configuration for external cipher-suites
727+
Extra interface{}
728+
726729
// mutex protects sessionTicketKeys and autoSessionTicketKeys.
727730
mutex sync.RWMutex
728731
// sessionTicketKeys contains zero or more ticket keys. If set, it means the
@@ -812,6 +815,7 @@ func (c *Config) Clone() *Config {
812815
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
813816
Renegotiation: c.Renegotiation,
814817
KeyLogWriter: c.KeyLogWriter,
818+
Extra: c.Extra,
815819
sessionTicketKeys: c.sessionTicketKeys,
816820
autoSessionTicketKeys: c.autoSessionTicketKeys,
817821
}

src/crypto/tls/handshake_client.go

+59-43
Original file line numberDiff line numberDiff line change
@@ -477,57 +477,63 @@ func (hs *clientHandshakeState) doFullHandshake() error {
477477
if err != nil {
478478
return err
479479
}
480-
certMsg, ok := msg.(*certificateMsg)
481-
if !ok || len(certMsg.certificates) == 0 {
482-
c.sendAlert(alertUnexpectedMessage)
483-
return unexpectedMessageError(certMsg, msg)
484-
}
485-
hs.finishedHash.Write(certMsg.marshal())
486480

487-
msg, err = c.readHandshake()
488-
if err != nil {
489-
return err
490-
}
491-
492-
cs, ok := msg.(*certificateStatusMsg)
493-
if ok {
494-
// RFC4366 on Certificate Status Request:
495-
// The server MAY return a "certificate_status" message.
496-
497-
if !hs.serverHello.ocspStapling {
498-
// If a server returns a "CertificateStatus" message, then the
499-
// server MUST have included an extension of type "status_request"
500-
// with empty "extension_data" in the extended server hello.
481+
cipherSuite := cipherSuiteByID(c.cipherSuite)
482+
useCerts := (cipherSuite.flags & suiteNoCerts) == 0
501483

484+
if useCerts {
485+
certMsg, ok := msg.(*certificateMsg)
486+
if !ok || len(certMsg.certificates) == 0 {
502487
c.sendAlert(alertUnexpectedMessage)
503-
return errors.New("tls: received unexpected CertificateStatus message")
488+
return unexpectedMessageError(certMsg, msg)
504489
}
505-
hs.finishedHash.Write(cs.marshal())
506-
507-
c.ocspResponse = cs.response
490+
hs.finishedHash.Write(certMsg.marshal())
508491

509492
msg, err = c.readHandshake()
510493
if err != nil {
511494
return err
512495
}
513-
}
514496

515-
if c.handshakes == 0 {
516-
// If this is the first handshake on a connection, process and
517-
// (optionally) verify the server's certificates.
518-
if err := c.verifyServerCertificate(certMsg.certificates); err != nil {
519-
return err
497+
cs, ok := msg.(*certificateStatusMsg)
498+
if ok {
499+
// RFC4366 on Certificate Status Request:
500+
// The server MAY return a "certificate_status" message.
501+
502+
if !hs.serverHello.ocspStapling {
503+
// If a server returns a "CertificateStatus" message, then the
504+
// server MUST have included an extension of type "status_request"
505+
// with empty "extension_data" in the extended server hello.
506+
507+
c.sendAlert(alertUnexpectedMessage)
508+
return errors.New("tls: received unexpected CertificateStatus message")
509+
}
510+
hs.finishedHash.Write(cs.marshal())
511+
512+
c.ocspResponse = cs.response
513+
514+
msg, err = c.readHandshake()
515+
if err != nil {
516+
return err
517+
}
520518
}
521-
} else {
522-
// This is a renegotiation handshake. We require that the
523-
// server's identity (i.e. leaf certificate) is unchanged and
524-
// thus any previous trust decision is still valid.
525-
//
526-
// See https://mitls.org/pages/attacks/3SHAKE for the
527-
// motivation behind this requirement.
528-
if !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) {
529-
c.sendAlert(alertBadCertificate)
530-
return errors.New("tls: server's identity changed during renegotiation")
519+
520+
if c.handshakes == 0 {
521+
// If this is the first handshake on a connection, process and
522+
// (optionally) verify the server's certificates.
523+
if err := c.verifyServerCertificate(certMsg.certificates); err != nil {
524+
return err
525+
}
526+
} else {
527+
// This is a renegotiation handshake. We require that the
528+
// server's identity (i.e. leaf certificate) is unchanged and
529+
// thus any previous trust decision is still valid.
530+
//
531+
// See https://mitls.org/pages/attacks/3SHAKE for the
532+
// motivation behind this requirement.
533+
if !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) {
534+
c.sendAlert(alertBadCertificate)
535+
return errors.New("tls: server's identity changed during renegotiation")
536+
}
531537
}
532538
}
533539

@@ -536,7 +542,11 @@ func (hs *clientHandshakeState) doFullHandshake() error {
536542
skx, ok := msg.(*serverKeyExchangeMsg)
537543
if ok {
538544
hs.finishedHash.Write(skx.marshal())
539-
err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx)
545+
if useCerts {
546+
err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx)
547+
} else {
548+
err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, nil, skx)
549+
}
540550
if err != nil {
541551
c.sendAlert(alertUnexpectedMessage)
542552
return err
@@ -578,15 +588,21 @@ func (hs *clientHandshakeState) doFullHandshake() error {
578588
// Certificate message, even if it's empty because we don't have a
579589
// certificate to send.
580590
if certRequested {
581-
certMsg = new(certificateMsg)
591+
certMsg := new(certificateMsg)
582592
certMsg.certificates = chainToSend.Certificate
583593
hs.finishedHash.Write(certMsg.marshal())
584594
if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
585595
return err
586596
}
587597
}
588598

589-
preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[0])
599+
var preMasterSecret []byte
600+
var ckx *clientKeyExchangeMsg
601+
if useCerts {
602+
preMasterSecret, ckx, err = keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[0])
603+
} else {
604+
preMasterSecret, ckx, err = keyAgreement.generateClientKeyExchange(c.config, hs.hello, nil)
605+
}
590606
if err != nil {
591607
c.sendAlert(alertInternalError)
592608
return err

src/crypto/tls/handshake_server.go

+20-16
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,14 @@ func (hs *serverHandshakeState) cipherSuiteOk(c *cipherSuite) bool {
370370
if !hs.ecdheOk {
371371
return false
372372
}
373-
if c.flags&suiteECSign != 0 {
374-
if !hs.ecSignOk {
373+
if c.flags&suiteNoCerts == 0 {
374+
if c.flags&suiteECSign != 0 {
375+
if !hs.ecSignOk {
376+
return false
377+
}
378+
} else if !hs.rsaSignOk {
375379
return false
376380
}
377-
} else if !hs.rsaSignOk {
378-
return false
379381
}
380382
} else if !hs.rsaDecryptOk {
381383
return false
@@ -502,20 +504,22 @@ func (hs *serverHandshakeState) doFullHandshake() error {
502504
return err
503505
}
504506

505-
certMsg := new(certificateMsg)
506-
certMsg.certificates = hs.cert.Certificate
507-
hs.finishedHash.Write(certMsg.marshal())
508-
if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
509-
return err
510-
}
511-
512-
if hs.hello.ocspStapling {
513-
certStatus := new(certificateStatusMsg)
514-
certStatus.response = hs.cert.OCSPStaple
515-
hs.finishedHash.Write(certStatus.marshal())
516-
if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil {
507+
if hs.suite.flags&suiteNoCerts == 0 { // this suite requires certificate handshake
508+
certMsg := new(certificateMsg)
509+
certMsg.certificates = hs.cert.Certificate
510+
hs.finishedHash.Write(certMsg.marshal())
511+
if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
517512
return err
518513
}
514+
515+
if hs.hello.ocspStapling {
516+
certStatus := new(certificateStatusMsg)
517+
certStatus.response = hs.cert.OCSPStaple
518+
hs.finishedHash.Write(certStatus.marshal())
519+
if _, err := c.writeRecord(recordTypeHandshake, certStatus.marshal()); err != nil {
520+
return err
521+
}
522+
}
519523
}
520524

521525
keyAgreement := hs.suite.ka(c.vers)

src/crypto/tls/handshake_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,9 @@ func (zeroSource) Read(b []byte) (n int, err error) {
320320
func allCipherSuites() []uint16 {
321321
ids := make([]uint16, len(cipherSuites))
322322
for i, suite := range cipherSuites {
323-
ids[i] = suite.id
323+
if suite.flags&suiteNoCerts == 0 {
324+
ids[i] = suite.id
325+
}
324326
}
325327

326328
return ids

0 commit comments

Comments
 (0)