crypto/tls: peek at unencrypted alerts to give better errors
This commit is contained in:
parent
740fc926aa
commit
44df381ccb
23
conn.go
23
conn.go
@ -703,6 +703,7 @@ func (c *Conn) readRecord(want recordType) error {
|
|||||||
|
|
||||||
// Process message.
|
// Process message.
|
||||||
b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
|
b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
|
||||||
|
peekedAlert := peekAlert(b) // peek at a possible alert before decryption
|
||||||
ok, off, alertValue := c.in.decrypt(b)
|
ok, off, alertValue := c.in.decrypt(b)
|
||||||
switch {
|
switch {
|
||||||
case !ok && c.phase == discardingEarlyData:
|
case !ok && c.phase == discardingEarlyData:
|
||||||
@ -713,8 +714,15 @@ func (c *Conn) readRecord(want recordType) error {
|
|||||||
case ok && c.phase == discardingEarlyData:
|
case ok && c.phase == discardingEarlyData:
|
||||||
c.phase = waitingClientFinished
|
c.phase = waitingClientFinished
|
||||||
case !ok:
|
case !ok:
|
||||||
|
c.in.traceErr, c.out.traceErr = nil, nil // not that interesting
|
||||||
c.in.freeBlock(b)
|
c.in.freeBlock(b)
|
||||||
return c.in.setErrorLocked(c.sendAlert(alertValue))
|
err := c.sendAlert(alertValue)
|
||||||
|
// If decryption failed because the message is an unencrypted
|
||||||
|
// alert, return a more meaningful error message
|
||||||
|
if alertValue == alertBadRecordMAC && peekedAlert != nil {
|
||||||
|
err = peekedAlert
|
||||||
|
}
|
||||||
|
return c.in.setErrorLocked(err)
|
||||||
}
|
}
|
||||||
b.off = off
|
b.off = off
|
||||||
data := b.data[b.off:]
|
data := b.data[b.off:]
|
||||||
@ -821,6 +829,19 @@ func (c *Conn) readRecord(want recordType) error {
|
|||||||
return c.in.err
|
return c.in.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// peekAlert looks at a message to spot an unencrypted alert. It must be
|
||||||
|
// called before decryption to avoid a side channel, and its result must
|
||||||
|
// only be used if decryption fails, to avoid false positives.
|
||||||
|
func peekAlert(b *block) error {
|
||||||
|
if len(b.data) < 7 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if recordType(b.data[0]) != recordTypeAlert {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &net.OpError{Op: "remote error", Err: alert(b.data[6])}
|
||||||
|
}
|
||||||
|
|
||||||
// sendAlert sends a TLS alert message.
|
// sendAlert sends a TLS alert message.
|
||||||
// c.out.Mutex <= L.
|
// c.out.Mutex <= L.
|
||||||
func (c *Conn) sendAlertLocked(err alert) error {
|
func (c *Conn) sendAlertLocked(err alert) error {
|
||||||
|
Loading…
Reference in New Issue
Block a user