runner: Parse CertificateRequest with byteReader.

Bug: 212
Change-Id: I0ad4df330360789b16fc9db70565abdb3ae42a8f
Reviewed-on: https://boringssl-review.googlesource.com/23448
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 37a8c53..22eb013 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -593,6 +593,22 @@
 	return m.raw
 }
 
+func parseSignatureAlgorithms(reader *byteReader, out *[]signatureAlgorithm) bool {
+	var sigAlgs byteReader
+	if !reader.readU16LengthPrefixed(&sigAlgs) {
+		return false
+	}
+	*out = make([]signatureAlgorithm, 0, len(sigAlgs)/2)
+	for len(sigAlgs) > 0 {
+		var v uint16
+		if !sigAlgs.readU16(&v) {
+			return false
+		}
+		*out = append(*out, signatureAlgorithm(v))
+	}
+	return true
+}
+
 func (m *clientHelloMsg) unmarshal(data []byte) bool {
 	m.raw = data
 	reader := byteReader(data[4:])
@@ -765,18 +781,9 @@
 			}
 		case extensionSignatureAlgorithms:
 			// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
-			var sigAlgs byteReader
-			if !body.readU16LengthPrefixed(&sigAlgs) || len(body) != 0 {
+			if !parseSignatureAlgorithms(&body, &m.signatureAlgorithms) || len(body) != 0 {
 				return false
 			}
-			m.signatureAlgorithms = make([]signatureAlgorithm, 0, len(sigAlgs)/2)
-			for len(sigAlgs) > 0 {
-				var v uint16
-				if !sigAlgs.readU16(&v) {
-					return false
-				}
-				m.signatureAlgorithms = append(m.signatureAlgorithms, signatureAlgorithm(v))
-			}
 		case extensionSupportedVersions:
 			var versions byteReader
 			if !body.readU8LengthPrefixed(&versions) || len(body) != 0 {
@@ -1898,167 +1905,72 @@
 	return m.raw
 }
 
-func parseSignatureAlgorithms(data []byte) ([]signatureAlgorithm, []byte, bool) {
-	if len(data) < 2 {
-		return nil, nil, false
+func parseCAs(reader *byteReader, out *[][]byte) bool {
+	var cas byteReader
+	if !reader.readU16LengthPrefixed(&cas) {
+		return false
 	}
-	sigAlgsLen := int(data[0])<<8 | int(data[1])
-	data = data[2:]
-	if sigAlgsLen&1 != 0 {
-		return nil, nil, false
-	}
-	if len(data) < int(sigAlgsLen) {
-		return nil, nil, false
-	}
-	numSigAlgs := sigAlgsLen / 2
-	signatureAlgorithms := make([]signatureAlgorithm, numSigAlgs)
-	for i := range signatureAlgorithms {
-		signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
-		data = data[2:]
-	}
-
-	return signatureAlgorithms, data, true
-}
-
-func parseCAs(data []byte) ([][]byte, []byte, bool) {
-	if len(data) < 2 {
-		return nil, nil, false
-	}
-	casLength := uint16(data[0])<<8 | uint16(data[1])
-	data = data[2:]
-	if len(data) < int(casLength) {
-		return nil, nil, false
-	}
-
-	cas := data[:casLength]
-	data = data[casLength:]
-
-	var certificateAuthorities [][]byte
 	for len(cas) > 0 {
-		if len(cas) < 2 {
-			return nil, nil, false
+		var ca []byte
+		if !cas.readU16LengthPrefixedBytes(&ca) {
+			return false
 		}
-		caLen := uint16(cas[0])<<8 | uint16(cas[1])
-		cas = cas[2:]
-
-		if len(cas) < int(caLen) {
-			return nil, nil, false
-		}
-
-		certificateAuthorities = append(certificateAuthorities, cas[:caLen])
-		cas = cas[caLen:]
+		*out = append(*out, ca)
 	}
-	return certificateAuthorities, data, true
+	return true
 }
 
 func (m *certificateRequestMsg) unmarshal(data []byte) bool {
 	m.raw = data
+	reader := byteReader(data[4:])
 
-	if len(data) < 5 {
-		return false
-	}
-	data = data[4:]
-
-	if m.hasRequestContext {
-		contextLen := int(data[0])
-		if len(data) < 1+contextLen {
+	if isDraft21(m.vers) {
+		var extensions byteReader
+		if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
+			!reader.readU16LengthPrefixed(&extensions) ||
+			len(reader) != 0 {
 			return false
 		}
-		m.requestContext = make([]byte, contextLen)
-		copy(m.requestContext, data[1:])
-		data = data[1+contextLen:]
-		if isDraft21(m.vers) {
-			if len(data) < 2 {
+		for len(extensions) > 0 {
+			var extension uint16
+			var body byteReader
+			if !extensions.readU16(&extension) ||
+				!extensions.readU16LengthPrefixed(&body) {
 				return false
 			}
-			extensionsLen := int(data[0])<<8 | int(data[1])
-			if len(data) < 2+extensionsLen {
-				return false
-			}
-			extensions := data[2 : 2+extensionsLen]
-			data = data[2+extensionsLen:]
-			for len(extensions) != 0 {
-				if len(extensions) < 4 {
+			switch extension {
+			case extensionSignatureAlgorithms:
+				if !parseSignatureAlgorithms(&body, &m.signatureAlgorithms) || len(body) != 0 {
 					return false
 				}
-				extension := uint16(extensions[0])<<8 | uint16(extensions[1])
-				length := int(extensions[2])<<8 | int(extensions[3])
-				if len(extensions) < 4+length {
+			case extensionCertificateAuthorities:
+				if !parseCAs(&body, &m.certificateAuthorities) || len(body) != 0 {
 					return false
 				}
-				contents := extensions[4 : 4+length]
-				extensions = extensions[4+length:]
-				switch extension {
-				case extensionSignatureAlgorithms:
-					sigAlgs, rest, ok := parseSignatureAlgorithms(contents)
-					if !ok || len(rest) != 0 {
-						return false
-					}
-					m.signatureAlgorithms = sigAlgs
-				case extensionCertificateAuthorities:
-					cas, rest, ok := parseCAs(contents)
-					if !ok || len(rest) != 0 {
-						return false
-					}
-					m.hasCAExtension = true
-					m.certificateAuthorities = cas
-				}
+				m.hasCAExtension = true
 			}
-		} else {
-			if m.hasSignatureAlgorithm {
-				sigAlgs, rest, ok := parseSignatureAlgorithms(data)
-				if !ok {
-					return false
-				}
-				m.signatureAlgorithms = sigAlgs
-				data = rest
-			}
-
-			cas, rest, ok := parseCAs(data)
-			if !ok {
-				return false
-			}
-			m.certificateAuthorities = cas
-			data = rest
-
-			// Ignore certificate extensions.
-			if len(data) < 2 {
-				return false
-			}
-			extsLength := int(data[0])<<8 | int(data[1])
-			if len(data) < 2+extsLength {
-				return false
-			}
-			data = data[2+extsLength:]
 		}
+	} else if m.hasRequestContext {
+		var extensions byteReader
+		if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
+			!parseSignatureAlgorithms(&reader, &m.signatureAlgorithms) ||
+			!parseCAs(&reader, &m.certificateAuthorities) ||
+			!reader.readU16LengthPrefixed(&extensions) ||
+			len(reader) != 0 {
+			return false
+		}
+		// Ignore certificate extensions.
 	} else {
-		numCertTypes := int(data[0])
-		if len(data) < 1+numCertTypes {
+		if !reader.readU8LengthPrefixedBytes(&m.certificateTypes) {
 			return false
 		}
-		m.certificateTypes = make([]byte, numCertTypes)
-		copy(m.certificateTypes, data[1:])
-		data = data[1+numCertTypes:]
-
-		if m.hasSignatureAlgorithm {
-			sigAlgs, rest, ok := parseSignatureAlgorithms(data)
-			if !ok {
-				return false
-			}
-			m.signatureAlgorithms = sigAlgs
-			data = rest
-		}
-
-		cas, rest, ok := parseCAs(data)
-		if !ok {
+		if m.hasSignatureAlgorithm && !parseSignatureAlgorithms(&reader, &m.signatureAlgorithms) {
 			return false
 		}
-		m.certificateAuthorities = cas
-		data = rest
-	}
-
-	if len(data) > 0 {
-		return false
+		if !parseCAs(&reader, &m.certificateAuthorities) ||
+			len(reader) != 0 {
+			return false
+		}
 	}
 
 	return true