diff options
-rw-r--r-- | common/base64.c | 104 | ||||
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | include/base64.h | 24 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | test/base64.c | 57 | ||||
-rw-r--r-- | test/base64.tasklist | 9 | ||||
-rw-r--r-- | test/build.mk | 2 | ||||
-rw-r--r-- | test/test_config.h | 4 |
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) |