From adfa8e1265f6155d1a582baa9929af198bb5d4de Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 1 May 2026 17:45:39 +0200 Subject: Misc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- librecrypt_encode.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'librecrypt_encode.c') diff --git a/librecrypt_encode.c b/librecrypt_encode.c index 2199ac1..51a0a2e 100644 --- a/librecrypt_encode.c +++ b/librecrypt_encode.c @@ -22,16 +22,29 @@ librecrypt_encode(char *out_buffer, size_t size, const void *binary, size_t len, unsigned char a, b, c; size_t q, r, i, j, n; + /* 1 byte (8 bits) requires 2 base-64 characters (12 bits), + * 2 bytes (16 bits) requires 3 base-64 characters (18 bits), and + * 3 bytes (24 bits) requires 4 base-64 characters (24 bits) exactly */ q = len / 3u; r = len % 3u; n = q * 4u + (!r ? 0u : pad ? 4u : r + 1u); + /* Just return the encoding length if no output is requested */ if (!size) return n; + /* We right backwards to ensure `out_buffer` and `binary` may alias each other + * (the output is at least as long as the input (actually always longer + * unless `len` is 0)) */ + + /* NUL-terminate output */ size -= 1u; out_buffer[n < size ? n : size] = '\0'; + /* Deal with situation where number of bytes is not divisible + * byte there, and set excess bits to 0; padding characters are + * appended if required (they are probably optional since padding + * is only useful to allow base-64 strings to be concatenated) */ if (r == 1u) { a = data[q * 3u + 0u]; switch (size > q * 4u ? size - q * 4u : 0u) { /* fall-through */ @@ -66,8 +79,11 @@ librecrypt_encode(char *out_buffer, size_t size, const void *binary, size_t len, } } + /* Encode multiples of 3 bytes as multiples of 4 ASCII characters, */ i = q * 4u; j = q * 3u; + /* however, first we may have to truncate the output to a non-multiple + * of 4 ASCII characters the output buffer is too small, */ if (i > size) { q = size / 4u; r = size % 4u; @@ -87,6 +103,7 @@ librecrypt_encode(char *out_buffer, size_t size, const void *binary, size_t len, break; } } + /* then we can efficiently write the multiple of 4 characters */ while (i) { i -= 4u; j -= 3u; @@ -120,6 +137,7 @@ check(const char *binary, size_t binary_len, const char *ascii, size_t ascii_len char buf[256u]; size_t i, j, n; + /* Check internal test correctness */ if (padded_ascii_len & 3u) { padded_ascii_len |= 3u; padded_ascii_len += 1u; @@ -128,12 +146,15 @@ check(const char *binary, size_t binary_len, const char *ascii, size_t ascii_len assert(padded_ascii_len / 4u == (ascii_len + 3u) / 4u); assert(padded_ascii_len >= ascii_len); + /* Check length-only request without padding */ EXPECT(librecrypt_encode(NULL, 0u, binary, binary_len, lut, '\0') == ascii_len); EXPECT(librecrypt_encode(buf, 0u, binary, binary_len, lut, '\0') == ascii_len); + /* Check length-only request with padding */ EXPECT(librecrypt_encode(NULL, 0u, binary, binary_len, lut, '=') == padded_ascii_len); EXPECT(librecrypt_encode(buf, 0u, binary, binary_len, lut, '=') == padded_ascii_len); + /* Check encoding requests, with and without truncation, without padding */ for (i = 0u; i <= ascii_len; i++) { memset(buf, 99, sizeof(buf)); EXPECT(librecrypt_encode(buf, i + 1u, binary, binary_len, lut, '\0') == ascii_len); @@ -143,6 +164,7 @@ check(const char *binary, size_t binary_len, const char *ascii, size_t ascii_len EXPECT(buf[j] == 99); } + /* Check encoding requests, with and without truncation, with padding */ for (i = 0u; i <= padded_ascii_len; i++) { memset(buf, 99, sizeof(buf)); EXPECT(librecrypt_encode(buf, i + 1u, binary, binary_len, lut, '=') == padded_ascii_len); -- cgit v1.2.3-70-g09d2