Clear the error queue when dropping a bad DTLS packet.

This regressed in e95d20dcb80523bf9bc6a9c5682856c8371e0a96. EVP_AEAD will push
errors on the error queue (unlike the EVP_CIPHER codepath which checked
everything internally to ssl/ and didn't bother pushing anything). This meant
that a dropped packet would leave junk in the error queue.

Later, when SSL_read returns <= 0 (EOF or EWOULDBLOCK), the non-empty error
queue check in SSL_get_error kicks in and SSL_read looks to have failed.

BUG=https://code.google.com/p/webrtc/issues/detail?id=4214

Change-Id: I1e5e41c77a3e5b71e9eb0c72294abf0da677f840
Reviewed-on: https://boringssl-review.googlesource.com/2982
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 1d3236f..a77ad4e 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -357,7 +357,9 @@
   rr->data = rr->input;
 
   if (!s->enc_method->enc(s, 0)) {
-    /* For DTLS we simply ignore bad packets. */
+    /* Bad packets are silently dropped in DTLS. Clear the error queue of any
+     * errors decryption may have added. */
+    ERR_clear_error();
     rr->length = 0;
     s->packet_length = 0;
     goto err;
diff --git a/ssl/test/runner/packet_adapter.go b/ssl/test/runner/packet_adapter.go
index 4f36eb1..671b413 100644
--- a/ssl/test/runner/packet_adapter.go
+++ b/ssl/test/runner/packet_adapter.go
@@ -76,3 +76,26 @@
 
 	return n, err
 }
+
+type damageAdaptor struct {
+	net.Conn
+	damage bool
+}
+
+// newDamageAdaptor wraps a packeted net.Conn. It transforms it into one which
+// optionally damages the final byte of every Write() call.
+func newDamageAdaptor(conn net.Conn) *damageAdaptor {
+	return &damageAdaptor{Conn: conn}
+}
+
+func (d *damageAdaptor) setDamage(damage bool) {
+	d.damage = damage
+}
+
+func (d *damageAdaptor) Write(b []byte) (int, error) {
+	if d.damage && len(b) > 0 {
+		b = append([]byte{}, b...)
+		b[len(b)-1]++
+	}
+	return d.Conn.Write(b)
+}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 3e1e7b4..e298725 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -178,6 +178,9 @@
 	// replayWrites, if true, configures the underlying transport
 	// to replay every write it makes in DTLS tests.
 	replayWrites bool
+	// damageFirstWrite, if true, configures the underlying transport to
+	// damage the final byte of the first application data write.
+	damageFirstWrite bool
 	// flags, if not empty, contains a list of command-line flags that will
 	// be passed to the shim program.
 	flags []string
@@ -612,10 +615,28 @@
 		shouldFail:    true,
 		expectedError: ":WRONG_CERTIFICATE_TYPE:",
 	},
+	{
+		name:             "TLSFatalBadPackets",
+		damageFirstWrite: true,
+		shouldFail:       true,
+		expectedError:    ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	},
+	{
+		protocol:         dtls,
+		name:             "DTLSIgnoreBadPackets",
+		damageFirstWrite: true,
+	},
+	{
+		protocol:         dtls,
+		name:             "DTLSIgnoreBadPackets-Async",
+		damageFirstWrite: true,
+		flags:            []string{"-async"},
+	},
 }
 
 func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
 	var connDebug *recordingConn
+	var connDamage *damageAdaptor
 	if *flagDebug {
 		connDebug = &recordingConn{Conn: conn}
 		conn = connDebug
@@ -631,6 +652,11 @@
 		}
 	}
 
+	if test.damageFirstWrite {
+		connDamage = newDamageAdaptor(conn)
+		conn = connDamage
+	}
+
 	if test.sendPrefix != "" {
 		if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
 			return err
@@ -718,6 +744,12 @@
 		panic("renegotiateCiphers without renegotiate")
 	}
 
+	if test.damageFirstWrite {
+		connDamage.setDamage(true)
+		tlsConn.Write([]byte("DAMAGED WRITE"))
+		connDamage.setDamage(false)
+	}
+
 	if messageLen < 0 {
 		if test.protocol == dtls {
 			return fmt.Errorf("messageLen < 0 not supported for DTLS tests")