Reject unknown fields in d2i_SSL_SESSION.

The original OpenSSL implementation did the same. M_ASN1_D2I_Finish checks
this. Forwards compatibility with future sessions with unknown fields is
probably not desirable.

Change-Id: I116a8c482cbcc47c3fcc31515c4a3718f66cf268
Reviewed-on: https://boringssl-review.googlesource.com/4941
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index 4de50fd..c0085aa 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -335,6 +335,18 @@
     "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
     "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
 
+// kBadSessionExtraField is a custom serialized SSL_SESSION generated by replacing
+// the final (optional) element of |kCustomSession| with tag number 30.
+static const char kBadSessionExtraField[] =
+    "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+    "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
+    "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
+    "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
+    "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
+    "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
+    "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
+    "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBL4DBAEF";
+
 static bool DecodeBase64(std::vector<uint8_t> *out, const char *in) {
   size_t len;
   if (!EVP_DecodedLength(&len, strlen(in))) {
@@ -416,6 +428,23 @@
   return true;
 }
 
+static bool TestBadSSL_SESSIONEncoding(const char *input_b64) {
+  std::vector<uint8_t> input;
+  if (!DecodeBase64(&input, input_b64)) {
+    return false;
+  }
+
+  // Verify that the SSL_SESSION fails to decode.
+  const uint8_t *ptr = bssl::vector_data(&input);
+  ScopedSSL_SESSION session(d2i_SSL_SESSION(NULL, &ptr, input.size()));
+  if (session) {
+    fprintf(stderr, "d2i_SSL_SESSION unexpectedly succeeded\n");
+    return false;
+  }
+  ERR_clear_error();
+  return true;
+}
+
 static bool TestDefaultVersion(uint16_t version,
                                const SSL_METHOD *(*method)(void)) {
   ScopedSSL_CTX ctx(SSL_CTX_new(method()));
@@ -494,6 +523,7 @@
   if (!TestCipherRules() ||
       !TestSSL_SESSIONEncoding(kOpenSSLSession) ||
       !TestSSL_SESSIONEncoding(kCustomSession) ||
+      !TestBadSSL_SESSIONEncoding(kBadSessionExtraField) ||
       !TestDefaultVersion(0, &TLS_method) ||
       !TestDefaultVersion(SSL3_VERSION, &SSLv3_method) ||
       !TestDefaultVersion(TLS1_VERSION, &TLSv1_method) ||