1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2020, Linaro Limited
4 * Copyright (c) 2014, STMicroelectronics International N.V.
5 */
6 #include "base64.h"
7
8 static const char base64_table[] =
9 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
10
_base64_enc_len(size_t size)11 size_t _base64_enc_len(size_t size)
12 {
13 return 4 * ((size + 2) / 3) + 1;
14 }
15
_base64_enc(const void * data,size_t dlen,char * buf,size_t * blen)16 bool _base64_enc(const void *data, size_t dlen, char *buf, size_t *blen)
17 {
18 size_t n = 0;
19 size_t boffs = 0;
20 const unsigned char *d = data;
21
22 n = _base64_enc_len(dlen);
23 if (*blen < n) {
24 *blen = n;
25 return false;
26 }
27
28 for (n = 0; n < dlen; n += 3) {
29 uint32_t igrp;
30
31 igrp = d[n];
32 igrp <<= 8;
33
34 if ((n + 1) < dlen)
35 igrp |= d[n + 1];
36 igrp <<= 8;
37
38 if ((n + 2) < dlen)
39 igrp |= d[n + 2];
40
41 buf[boffs] = base64_table[(igrp >> 18) & 0x3f];
42 buf[boffs + 1] = base64_table[(igrp >> 12) & 0x3f];
43 if ((n + 1) < dlen)
44 buf[boffs + 2] = base64_table[(igrp >> 6) & 0x3f];
45 else
46 buf[boffs + 2] = '=';
47 if ((n + 2) < dlen)
48 buf[boffs + 3] = base64_table[igrp & 0x3f];
49 else
50 buf[boffs + 3] = '=';
51
52 boffs += 4;
53 }
54 buf[boffs++] = '\0';
55
56 *blen = boffs;
57 return true;
58 }
59
get_idx(char ch,uint8_t * idx)60 static bool get_idx(char ch, uint8_t *idx)
61 {
62 size_t n = 0;
63
64 for (n = 0; base64_table[n] != '\0'; n++) {
65 if (ch == base64_table[n]) {
66 *idx = n;
67 return true;
68 }
69 }
70 return false;
71 }
72
_base64_dec(const char * data,size_t size,void * buf,size_t * blen)73 bool _base64_dec(const char *data, size_t size, void *buf, size_t *blen)
74 {
75 bool ret = false;
76 size_t n = 0;
77 uint8_t idx = 0;
78 uint8_t *b = buf;
79 size_t m = 0;
80 size_t s = 0;
81 uint8_t byte = 0;
82
83 for (n = 0; n < size && data[n] != '\0'; n++) {
84 if (data[n] == '=')
85 break; /* Reached pad characters, we're done */
86
87 if (!get_idx(data[n], &idx))
88 continue;
89
90 switch (s) {
91 case 0:
92 byte = idx << 2;
93 s++;
94 break;
95 case 1:
96 if (b && m < *blen)
97 b[m] = byte | (idx >> 4);
98 m++;
99 byte = (idx & 0xf) << 4;
100 s++;
101 break;
102 case 2:
103 if (b && m < *blen)
104 b[m] = byte | (idx >> 2);
105 m++;
106 byte = (idx & 0x3) << 6;
107 s++;
108 break;
109 case 3:
110 if (b && m < *blen)
111 b[m] = byte | idx;
112 m++;
113 s = 0;
114 break;
115 default:
116 return false; /* "Can't happen" */
117 }
118 }
119
120 /*
121 * We don't detect if input was bad, but that's OK with the spec.
122 * We expect that each fully extracted byte is stored in output buffer.
123 */
124 ret = (!m && !*blen) || (b && (m <= *blen));
125 *blen = m;
126
127 return ret;
128 }
129