Port ssl3_get_next_proto to CBS.

NPNServerTest in runner.go provides test coverage.

Change-Id: I5503ccbc4270e7f9f42ebc30c21e8077a430cf9f
Reviewed-on: https://boringssl-review.googlesource.com/1162
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 1022464..b7c1072 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -3191,9 +3191,8 @@
 int ssl3_get_next_proto(SSL *s)
 	{
 	int ok;
-	int proto_len, padding_len;
 	long n;
-	const unsigned char *p;
+	CBS next_protocol, selected_protocol, padding;
 
 	/* Clients cannot send a NextProtocol message if we didn't see the
 	 * extension in their ClientHello */
@@ -3222,10 +3221,7 @@
 		return -1;
 		}
 
-	if (n < 2)
-		return 0;  /* The body must be > 1 bytes long */
-
-	p=(unsigned char *)s->init_msg;
+	CBS_init(&next_protocol, (uint8_t *)s->init_msg, n);
 
 	/* The payload looks like:
 	 *   uint8 proto_len;
@@ -3233,21 +3229,15 @@
 	 *   uint8 padding_len;
 	 *   uint8 padding[padding_len];
 	 */
-	proto_len = p[0];
-	if (proto_len + 2 > s->init_num)
-		return 0;
-	padding_len = p[proto_len + 1];
-	if (proto_len + padding_len + 2 != s->init_num)
+	if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
+		!CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
+		CBS_len(&next_protocol) != 0)
 		return 0;
 
-	s->next_proto_negotiated = OPENSSL_malloc(proto_len);
-	if (!s->next_proto_negotiated)
-		{
-		OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, ERR_R_MALLOC_FAILURE);
+	if (!CBS_stow(&selected_protocol,
+			&s->next_proto_negotiated,
+			&s->next_proto_negotiated_len))
 		return 0;
-		}
-	memcpy(s->next_proto_negotiated, p + 1, proto_len);
-	s->next_proto_negotiated_len = proto_len;
 
 	return 1;
 	}
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 21cc5d1..fa2fffc 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1184,7 +1184,7 @@
 						 unsigned int inlen, void *arg),
 				      void *arg);
 void SSL_get0_next_proto_negotiated(const SSL *s,
-				    const unsigned char **data, unsigned *len);
+				    const uint8_t **data, unsigned *len);
 #endif
 
 int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
@@ -1471,8 +1471,8 @@
 	 * For a server, this is the client's selected_protocol from
 	 * NextProtocol and is set when handling the NextProtocol message,
 	 * before the Finished message. */
-	unsigned char *next_proto_negotiated;
-	unsigned char next_proto_negotiated_len;
+	uint8_t *next_proto_negotiated;
+	size_t next_proto_negotiated_len;
 #endif
 
 #define session_ctx initial_ctx
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 28aba46..7036cf9 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1756,7 +1756,7 @@
  * from this function need not be a member of the list of supported protocols
  * provided by the callback.
  */
-void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, unsigned *len)
+void SSL_get0_next_proto_negotiated(const SSL *s, const uint8_t **data, unsigned *len)
 	{
 	*data = s->next_proto_negotiated;
 	if (!*data) {