DeterministicESPAsyncWebServer 1.2.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
base64.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file base64.cpp
6 * @brief Base64 encoder/decoder implementation.
7 *
8 * On Arduino (ESP32) targets, delegates to mbedtls_base64_encode/decode()
9 * which is part of the ESP-IDF mbedTLS bundle — same SDK path as SHA-1.
10 *
11 * On native (x86) test targets, uses a portable software implementation so
12 * unit tests run without mbedTLS installed.
13 */
14
15#include "base64.h"
16
17#ifdef ARDUINO
18
19// --- ESP32 / Arduino: use mbedTLS -------------------------------------------
20#include "mbedtls/base64.h"
21#include <string.h>
22
23void base64_encode(const uint8_t *src, size_t src_len, char *dst)
24{
25 size_t olen;
26 size_t dlen = ((src_len + 2) / 3) * 4 + 1;
27 mbedtls_base64_encode((unsigned char *)dst, dlen, &olen, src, src_len);
28 dst[olen] = '\0';
29}
30
31size_t base64_decode(const char *src, uint8_t *dst)
32{
33 size_t src_len = strlen(src);
34 size_t olen;
35 size_t dlen = (src_len / 4) * 3 + 3;
36 int ret = mbedtls_base64_decode(dst, dlen, &olen,
37 (const unsigned char *)src, src_len);
38 return (ret == 0) ? olen : 0;
39}
40
41#else
42
43// --- Native / test: software Base64, no external dependencies ---------------
44#include <stddef.h>
45
46static const char B64_TABLE[] =
47 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
48
49void base64_encode(const uint8_t *src, size_t src_len, char *dst)
50{
51 size_t i = 0, j = 0;
52
53 while (i + 2 < src_len)
54 {
55 uint32_t v = ((uint32_t)src[i] << 16)
56 | ((uint32_t)src[i+1] << 8)
57 | (uint32_t)src[i+2];
58 dst[j++] = B64_TABLE[(v >> 18) & 0x3F];
59 dst[j++] = B64_TABLE[(v >> 12) & 0x3F];
60 dst[j++] = B64_TABLE[(v >> 6) & 0x3F];
61 dst[j++] = B64_TABLE[(v ) & 0x3F];
62 i += 3;
63 }
64
65 if (i < src_len)
66 {
67 uint32_t v = (uint32_t)src[i] << 16;
68 if (i + 1 < src_len)
69 v |= (uint32_t)src[i+1] << 8;
70
71 dst[j++] = B64_TABLE[(v >> 18) & 0x3F];
72 dst[j++] = B64_TABLE[(v >> 12) & 0x3F];
73 dst[j++] = (i + 1 < src_len) ? B64_TABLE[(v >> 6) & 0x3F] : '=';
74 dst[j++] = '=';
75 }
76
77 dst[j] = '\0';
78}
79
80static int b64_val(char c)
81{
82 if (c >= 'A' && c <= 'Z') return c - 'A';
83 if (c >= 'a' && c <= 'z') return c - 'a' + 26;
84 if (c >= '0' && c <= '9') return c - '0' + 52;
85 if (c == '+') return 62;
86 if (c == '/') return 63;
87 if (c == '=') return 0;
88 return -1;
89}
90
91size_t base64_decode(const char *src, uint8_t *dst)
92{
93 size_t out = 0;
94
95 while (*src)
96 {
97 int a = b64_val(src[0]);
98 int b = (src[1]) ? b64_val(src[1]) : -1;
99 int c = (src[2]) ? b64_val(src[2]) : -1;
100 int d = (src[3]) ? b64_val(src[3]) : -1;
101
102 if (a < 0 || b < 0 || c < 0 || d < 0)
103 return 0;
104
105 dst[out++] = (uint8_t)((a << 2) | (b >> 4));
106 if (src[2] && src[2] != '=')
107 dst[out++] = (uint8_t)((b << 4) | (c >> 2));
108 if (src[3] && src[3] != '=')
109 dst[out++] = (uint8_t)((c << 6) | d);
110
111 src += 4;
112 }
113
114 return out;
115}
116
117#endif // ARDUINO
void base64_encode(const uint8_t *src, size_t src_len, char *dst)
Encode src_len bytes of src as Base64.
Definition base64.cpp:23
size_t base64_decode(const char *src, uint8_t *dst)
Decode a null-terminated Base64 string.
Definition base64.cpp:31
Base64 encoder/decoder.