summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/base64.c104
-rw-r--r--common/build.mk1
-rw-r--r--include/base64.h24
-rw-r--r--include/config.h3
-rw-r--r--test/base64.c57
-rw-r--r--test/base64.tasklist9
-rw-r--r--test/build.mk2
-rw-r--r--test/test_config.h4
8 files changed, 204 insertions, 0 deletions
diff --git a/common/base64.c b/common/base64.c
new file mode 100644
index 0000000000..e3f979cce2
--- /dev/null
+++ b/common/base64.c
@@ -0,0 +1,104 @@
+/* Copyright 2022 The Chromium OS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Yet another from scratch implementation of base64 encoding. */
+
+#include "base64.h"
+#include "common.h"
+#include "console.h"
+
+/*
+ * Translation Table as described in RFC1113
+ */
+static const char cb64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* Number of bytes converted into the output block of characters. */
+#define BASE64_BYTE_SIZE 3
+
+/* Number of characters in a single encoded block. */
+#define BASE64_CHAR_SIZE 4
+
+/*
+ * encodeblock
+ *
+ * encode up to 3 bytes 6-bit characters, pad output with '=' if input is
+ * shorter than 3 bytes.
+ *
+ * @param in: pointer to the input bytes
+ * @param out: pointer to the output, guaranteed to be 4 bytes long.
+ * @param len: number of input bytes to process, guaranteed to be in 1..3
+ * range.
+ */
+static void encodeblock(const uint8_t *in, uint8_t *out, size_t len)
+{
+ uint32_t input;
+ int i;
+ int limit;
+
+ /* Place input bytes into a 32 bit value in big endian format. */
+ input = 0;
+ for (i = 0; i < len; i++)
+ ((uint8_t *)&input)[3 - i] = in[i];
+
+ /*
+ * Map each 6 bit quantity of the input into an output character, make
+ * sure partial bit quantities are mapped too in case input is shorter
+ * than 3 bytes.
+ */
+ limit = ((len * 8) + 7) / 6;
+ for (i = 0; i < limit; i++) {
+ int index = (input >> (26 - i * 6)) & 0x3f;
+
+ out[i] = cb64[index];
+ }
+
+ while (i < BASE64_CHAR_SIZE)
+ out[i++] = '=';
+}
+
+/* Pass one output character to the caller. */
+static void printit(char c, void (*f)(char c))
+{
+ if (f)
+ f(c);
+ else
+ ccprintf("%c", c);
+}
+
+#define LINE_SIZE 64
+void base64_encode_to_console(const uint8_t *data, size_t size,
+ void (*func)(char c))
+{
+ uint8_t out[4];
+ int blocksout;
+
+ blocksout = 0;
+ while (size) {
+ int i;
+ int in_length;
+
+ if (size > BASE64_BYTE_SIZE)
+ in_length = BASE64_BYTE_SIZE;
+ else
+ in_length = size;
+
+ encodeblock(data, out, in_length);
+ for (i = 0; i < sizeof(out); i++)
+ printit(out[i], func);
+
+ blocksout++;
+ data += in_length;
+ size -= in_length;
+ if (blocksout >= (LINE_SIZE / BASE64_CHAR_SIZE)) {
+ printit('\n', func);
+ blocksout = 0;
+ if (!func)
+ cflush();
+ }
+ }
+ if (blocksout)
+ printit('\n', func);
+}
diff --git a/common/build.mk b/common/build.mk
index 9d484bcb1b..771b75da1a 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -35,6 +35,7 @@ common-$(CONFIG_AUDIO_CODEC_I2S_RX)+=audio_codec_i2s_rx.o
common-$(CONFIG_AUDIO_CODEC_WOV)+=audio_codec_wov.o
common-$(CONFIG_BACKLIGHT_LID)+=backlight_lid.o
common-$(CONFIG_BASE32)+=base32.o
+common-$(CONFIG_BASE64)+=base64.o
common-$(CONFIG_DETACHABLE_BASE)+=base_state.o
common-$(CONFIG_CAPSENSE)+=capsense.o
common-$(CONFIG_CASE_CLOSED_DEBUG_V1)+=ccd_config.o
diff --git a/include/base64.h b/include/base64.h
new file mode 100644
index 0000000000..f64c78ebee
--- /dev/null
+++ b/include/base64.h
@@ -0,0 +1,24 @@
+#ifndef __CR50_INCLUDE_B64_H
+#define __CR50_INCLUDE_B64_H
+/* Copyright 2022 The Chromium OS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#include "util.h"
+
+/*
+ * A function to print base64 encoding of a binary blob on the console.
+ *
+ * For testing purposed an alternative output function could be supplied.
+ *
+ * @param data - pointer to data to encode.
+ * @param size - size of the data area
+ * @param func - optional, function to pass to the characters to print. If
+ * NULL the output is printed on the console.
+ */
+void base64_encode_to_console(const uint8_t *data, size_t size,
+ void (*func)(char c));
+
+#endif /* ! __CR50_INCLUDE_B64_H */
diff --git a/include/config.h b/include/config.h
index f48a640d68..19a4552f2a 100644
--- a/include/config.h
+++ b/include/config.h
@@ -323,6 +323,9 @@
/* Support base32 text encoding */
#undef CONFIG_BASE32
+/* Support base64 text encoding */
+#undef CONFIG_BASE64
+
/*****************************************************************************/
/* Battery config */
diff --git a/test/base64.c b/test/base64.c
new file mode 100644
index 0000000000..9ded346c5d
--- /dev/null
+++ b/test/base64.c
@@ -0,0 +1,57 @@
+/* Copyright 2022 The Chromium OS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Test Base-64 encoding.
+ */
+
+#include <stdio.h>
+#include "base64.h"
+#include "common.h"
+#include "test_util.h"
+#include "util.h"
+
+static char results[100];
+static size_t index;
+
+static void printer(char c)
+{
+ if (index < sizeof(results))
+ results[index++] = c;
+}
+
+static int test_encode(void)
+{
+ const char *data = "\x00\x01\x02\x80\xf0\ffabcdefghij "
+ "random text to wrap at 64 characters at most";
+ const struct {
+ size_t len; /* Length of input. */
+ const char *encoding; /* Expected encoding. */
+ } cases[] = {
+ { 1, "AA==\n" },
+ { 2, "AAE=\n" },
+ { 3, "AAEC\n" },
+ { 4, "AAECgA==\n" },
+ { 60, "AAECgPAMZmFiY2RlZmdoaWogcmFuZG9tIHRleHQg"
+ "dG8gd3JhcCBhdCA2NCBjaGFy\nYWN0ZXJzIGF0IG1v\n" },
+ };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(cases); i++) {
+ index = 0;
+ base64_encode_to_console(data, cases[i].len, printer);
+ TEST_ASSERT(index == strlen(cases[i].encoding));
+ TEST_ASSERT(memcmp(cases[i].encoding, results, index) == 0);
+ }
+
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ test_reset();
+
+ RUN_TEST(test_encode);
+
+ test_print_result();
+}
diff --git a/test/base64.tasklist b/test/base64.tasklist
new file mode 100644
index 0000000000..243a3b683f
--- /dev/null
+++ b/test/base64.tasklist
@@ -0,0 +1,9 @@
+/* Copyright 2022 The Chromium OS Authors.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST /* No test task */
diff --git a/test/build.mk b/test/build.mk
index 4072459707..16638acaae 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -13,6 +13,7 @@ test-list-host=$(TEST_LIST_HOST)
else
test-list-host = aes
test-list-host += base32
+test-list-host += base64
test-list-host += button
test-list-host += cec
test-list-host += console_edit
@@ -58,6 +59,7 @@ endif
aes-y=aes.o
base32-y=base32.o
+base64-y=base64.o
button-y=button.o
cec-y=cec.o
console_edit-y=console_edit.o
diff --git a/test/test_config.h b/test/test_config.h
index f7b222302f..493d255626 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -27,6 +27,10 @@
#define CONFIG_BASE32
#endif
+#ifdef TEST_BASE64
+#define CONFIG_BASE64
+#endif
+
#ifdef TEST_FLASH_LOG
#define CONFIG_CRC8
#define CONFIG_FLASH_ERASED_VALUE32 (-1U)