From 3f6877b440d5d44fc0c6d366d1b5d5fdeead626c Mon Sep 17 00:00:00 2001
From: jsing <>
Date: Wed, 15 Dec 2021 17:36:49 +0000
Subject: Provide various CBS_peek_* functions.

These will be used in libcrypto.

With input from and ok tb@
---
 src/lib/libssl/bs_cbs.c     | 79 ++++++++++++++++++++++++++++++++++++++++++++-
 src/lib/libssl/bytestring.h | 32 +++++++++++++++++-
 2 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/src/lib/libssl/bs_cbs.c b/src/lib/libssl/bs_cbs.c
index 97b0163f3f..63c078c9b0 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.23 2021/12/15 17:30:20 jsing Exp $	*/
+/*	$OpenBSD: bs_cbs.c,v 1.24 2021/12/15 17:36:49 jsing Exp $	*/
 /*
  * Copyright (c) 2014, Google Inc.
  *
@@ -47,6 +47,16 @@ cbs_get(CBS *cbs, const uint8_t **p, size_t n)
 	return 1;
 }
 
+static int
+cbs_peek(CBS *cbs, const uint8_t **p, size_t n)
+{
+	if (cbs->len < n)
+		return 0;
+
+	*p = cbs->data;
+	return 1;
+}
+
 size_t
 CBS_offset(const CBS *cbs)
 {
@@ -259,6 +269,73 @@ CBS_get_u24_length_prefixed(CBS *cbs, CBS *out)
 	return cbs_get_length_prefixed(cbs, out, 3);
 }
 
+static int
+cbs_peek_u(CBS *cbs, uint32_t *out, size_t len)
+{
+	uint32_t result = 0;
+	size_t i;
+	const uint8_t *data;
+
+	if (len < 1 || len > 4)
+		return 0;
+
+	if (!cbs_peek(cbs, &data, len))
+		return 0;
+
+	for (i = 0; i < len; i++) {
+		result <<= 8;
+		result |= data[i];
+	}
+	*out = result;
+	return 1;
+}
+
+int
+CBS_peek_u8(CBS *cbs, uint8_t *out)
+{
+	const uint8_t *v;
+
+	if (!cbs_peek(cbs, &v, 1))
+		return 0;
+
+	*out = *v;
+	return 1;
+}
+
+int
+CBS_peek_u16(CBS *cbs, uint16_t *out)
+{
+	uint32_t v;
+
+	if (!cbs_peek_u(cbs, &v, 2))
+		return 0;
+
+	*out = v;
+	return 1;
+}
+
+int
+CBS_peek_u24(CBS *cbs, uint32_t *out)
+{
+	return cbs_peek_u(cbs, out, 3);
+}
+
+int
+CBS_peek_u32(CBS *cbs, uint32_t *out)
+{
+	return cbs_peek_u(cbs, out, 4);
+}
+
+int
+CBS_peek_last_u8(CBS *cbs, uint8_t *out)
+{
+	if (cbs->len == 0)
+		return 0;
+
+	*out = cbs->data[cbs->len - 1];
+	return 1;
+}
+
 int
 CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag,
     size_t *out_header_len)
diff --git a/src/lib/libssl/bytestring.h b/src/lib/libssl/bytestring.h
index fa5e05fa27..ce933f3f7b 100644
--- a/src/lib/libssl/bytestring.h
+++ b/src/lib/libssl/bytestring.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: bytestring.h,v 1.21 2021/12/15 17:30:20 jsing Exp $	*/
+/*	$OpenBSD: bytestring.h,v 1.22 2021/12/15 17:36:49 jsing Exp $	*/
 /*
  * Copyright (c) 2014, Google Inc.
  *
@@ -172,6 +172,36 @@ int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out);
  */
 int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
 
+/*
+ * CBS_peek_u8 sets |*out| to the next uint8_t from |cbs|, but does not advance
+ * |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_u8(CBS *cbs, uint8_t *out);
+
+/*
+ * CBS_peek_u16 sets |*out| to the next, big-endian uint16_t from |cbs|, but
+ * does not advance |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_u16(CBS *cbs, uint16_t *out);
+
+/*
+ * CBS_peek_u24 sets |*out| to the next, big-endian 24-bit value from |cbs|, but
+ * does not advance |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_u24(CBS *cbs, uint32_t *out);
+
+/*
+ * CBS_peek_u32 sets |*out| to the next, big-endian uint32_t value from |cbs|,
+ * but does not advance |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_u32(CBS *cbs, uint32_t *out);
+
+/*
+ * CBS_peek_last_u8 sets |*out| to the last uint8_t from |cbs|, but does not
+ * shorten |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_last_u8(CBS *cbs, uint8_t *out);
+
 
 /* Parsing ASN.1 */
 
-- 
cgit v1.2.3-55-g6feb