From f7c257c94b0ba9258a1f7a5ec03099db9586b791 Mon Sep 17 00:00:00 2001
From: doug <>
Date: Sat, 25 Apr 2015 15:28:47 +0000
Subject: Check for invalid leading zeros in CBS_get_asn1_uint64.

ASN.1 integers cannot have all zeros or all ones for the first 9 bits.
This rule ensures the numbers are encoded with the smallest number of
content octets (see ITU-T Rec X.690 section 8.3.2).

Based on BoringSSL commit 5933723b7b592e9914f703d630b596e140c93e16

ok deraadt@ jsing@
---
 src/lib/libssl/bs_cbs.c                            | 11 ++++++++---
 src/lib/libssl/src/ssl/bs_cbs.c                    | 11 ++++++++---
 src/regress/lib/libssl/bytestring/bytestringtest.c |  6 ++++--
 3 files changed, 20 insertions(+), 8 deletions(-)

(limited to 'src')

diff --git a/src/lib/libssl/bs_cbs.c b/src/lib/libssl/bs_cbs.c
index c3d3a8abf2..d7c0977cf3 100644
--- a/src/lib/libssl/bs_cbs.c
+++ b/src/lib/libssl/bs_cbs.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: bs_cbs.c,v 1.2 2015/02/06 22:22:33 doug Exp $	*/
+/*	$OpenBSD: bs_cbs.c,v 1.3 2015/04/25 15:28:47 doug Exp $	*/
 /*
  * Copyright (c) 2014, Google Inc.
  *
@@ -317,6 +317,7 @@ CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value)
 	return CBS_data(cbs)[0] == tag_value;
 }
 
+/* Encoding details are in ASN.1: X.690 section 8.3 */
 int
 CBS_get_asn1_uint64(CBS *cbs, uint64_t *out)
 {
@@ -332,11 +333,15 @@ CBS_get_asn1_uint64(CBS *cbs, uint64_t *out)
 	len = CBS_len(&bytes);
 
 	if (len == 0)
-		/* An INTEGER is encoded with at least one octet. */
+		/* An INTEGER is encoded with at least one content octet. */
 		return 0;
 
 	if ((data[0] & 0x80) != 0)
-		/* negative number */
+		/* Negative number. */
+		return 0;
+
+	if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0)
+		/* Violates smallest encoding rule: excessive leading zeros. */
 		return 0;
 
 	for (i = 0; i < len; i++) {
diff --git a/src/lib/libssl/src/ssl/bs_cbs.c b/src/lib/libssl/src/ssl/bs_cbs.c
index c3d3a8abf2..d7c0977cf3 100644
--- a/src/lib/libssl/src/ssl/bs_cbs.c
+++ b/src/lib/libssl/src/ssl/bs_cbs.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: bs_cbs.c,v 1.2 2015/02/06 22:22:33 doug Exp $	*/
+/*	$OpenBSD: bs_cbs.c,v 1.3 2015/04/25 15:28:47 doug Exp $	*/
 /*
  * Copyright (c) 2014, Google Inc.
  *
@@ -317,6 +317,7 @@ CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value)
 	return CBS_data(cbs)[0] == tag_value;
 }
 
+/* Encoding details are in ASN.1: X.690 section 8.3 */
 int
 CBS_get_asn1_uint64(CBS *cbs, uint64_t *out)
 {
@@ -332,11 +333,15 @@ CBS_get_asn1_uint64(CBS *cbs, uint64_t *out)
 	len = CBS_len(&bytes);
 
 	if (len == 0)
-		/* An INTEGER is encoded with at least one octet. */
+		/* An INTEGER is encoded with at least one content octet. */
 		return 0;
 
 	if ((data[0] & 0x80) != 0)
-		/* negative number */
+		/* Negative number. */
+		return 0;
+
+	if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0)
+		/* Violates smallest encoding rule: excessive leading zeros. */
 		return 0;
 
 	for (i = 0; i < len; i++) {
diff --git a/src/regress/lib/libssl/bytestring/bytestringtest.c b/src/regress/lib/libssl/bytestring/bytestringtest.c
index 8269151127..7ae9397a35 100644
--- a/src/regress/lib/libssl/bytestring/bytestringtest.c
+++ b/src/regress/lib/libssl/bytestring/bytestringtest.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: bytestringtest.c,v 1.3 2015/02/16 06:48:17 doug Exp $	*/
+/*	$OpenBSD: bytestringtest.c,v 1.4 2015/04/25 15:28:47 doug Exp $	*/
 /*
  * Copyright (c) 2014, Google Inc.
  *
@@ -607,8 +607,10 @@ static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = {
 	{"\x02\x00", 2},
 	/* Negative number. */
 	{"\x02\x01\x80", 3},
-	/* Overflow */
+	/* Overflow. */
 	{"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
+	/* Leading zeros. */
+	{"\x02\x02\x00\x01", 4},
 };
 
 static int
-- 
cgit v1.2.3-55-g6feb