Enforce the SSL 3.0 no_certificate alert in tests. As long as we still have this code, we should make sure it doesn't regress. Change-Id: I0290792aedcf667ec49b251d747ffbc141c0cec4 Reviewed-on: https://boringssl-review.googlesource.com/13053 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/alert.go b/ssl/test/runner/alert.go index 93de4b5..652e9ee 100644 --- a/ssl/test/runner/alert.go +++ b/ssl/test/runner/alert.go
@@ -23,7 +23,7 @@ alertRecordOverflow alert = 22 alertDecompressionFailure alert = 30 alertHandshakeFailure alert = 40 - alertNoCertficate alert = 41 + alertNoCertificate alert = 41 alertBadCertificate alert = 42 alertUnsupportedCertificate alert = 43 alertCertificateRevoked alert = 44 @@ -56,6 +56,7 @@ alertRecordOverflow: "record overflow", alertDecompressionFailure: "decompression failure", alertHandshakeFailure: "handshake failure", + alertNoCertificate: "no certificate", alertBadCertificate: "bad certificate", alertUnsupportedCertificate: "unsupported certificate", alertCertificateRevoked: "revoked certificate",
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go index 510bcf7..3e22465 100644 --- a/ssl/test/runner/conn.go +++ b/ssl/test/runner/conn.go
@@ -21,6 +21,8 @@ "time" ) +var errNoCertificateAlert = errors.New("tls: no certificate alert") + // A Conn represents a secured connection. // It implements the net.Conn interface. type Conn struct { @@ -895,6 +897,11 @@ } switch data[0] { case alertLevelWarning: + if alert(data[1]) == alertNoCertificate { + c.in.freeBlock(b) + return errNoCertificateAlert + } + // drop on the floor c.in.freeBlock(b) goto Again @@ -963,7 +970,7 @@ // L < c.out.Mutex. func (c *Conn) sendAlert(err alert) error { level := byte(alertLevelError) - if err == alertNoRenegotiation || err == alertCloseNotify || err == alertNoCertficate { + if err == alertNoRenegotiation || err == alertCloseNotify || err == alertNoCertificate { level = alertLevelWarning } return c.SendAlert(level, err) @@ -1195,6 +1202,13 @@ // c.in.Mutex < L; c.out.Mutex < L. func (c *Conn) readHandshake() (interface{}, error) { data, err := c.doReadHandshake() + if err == errNoCertificateAlert { + if c.hand.Len() != 0 { + // The warning alert may not interleave with a handshake message. + return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) + } + return new(ssl3NoCertificateMsg), nil + } if err != nil { return nil, err }
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go index 4e715b5..507ea40 100644 --- a/ssl/test/runner/handshake_client.go +++ b/ssl/test/runner/handshake_client.go
@@ -1028,7 +1028,7 @@ // no_certificate warning alert. if certRequested { if c.vers == VersionSSL30 && chainToSend == nil { - c.sendAlert(alertNoCertficate) + c.sendAlert(alertNoCertificate) } else if !c.config.Bugs.SkipClientCertificate { certMsg := new(certificateMsg) if chainToSend != nil {
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go index 0d4d161..01f673b 100644 --- a/ssl/test/runner/handshake_messages.go +++ b/ssl/test/runner/handshake_messages.go
@@ -2275,6 +2275,10 @@ return m.keyUpdateRequest == keyUpdateNotRequested || m.keyUpdateRequest == keyUpdateRequested } +// ssl3NoCertificateMsg is a dummy message to handle SSL 3.0 using a warning +// alert in the handshake. +type ssl3NoCertificateMsg struct{} + func eqUint16s(x, y []uint16) bool { if len(x) != len(y) { return false
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go index 8f4e97b..1116d6c 100644 --- a/ssl/test/runner/handshake_server.go +++ b/ssl/test/runner/handshake_server.go
@@ -1452,7 +1452,13 @@ for _, cert := range certMsg.certificates { certificates = append(certificates, cert.data) } - } else if c.vers != VersionSSL30 { + } else if c.vers == VersionSSL30 { + // In SSL 3.0, no certificate is signaled by a warning + // alert which we translate to ssl3NoCertificateMsg. + if _, ok := msg.(*ssl3NoCertificateMsg); !ok { + return errors.New("tls: client provided neither a certificate nor no_certificate warning alert") + } + } else { // In TLS, the Certificate message is required. In SSL // 3.0, the peer skips it when sending no certificates. c.sendAlert(alertUnexpectedMessage) @@ -1473,11 +1479,9 @@ return err } - if ok { - msg, err = c.readHandshake() - if err != nil { - return err - } + msg, err = c.readHandshake() + if err != nil { + return err } }