1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <b64_decode.h>
4 #include <console/console.h>
7 * Translation Table to decode base64 ASCII stream into binary. Borrowed from
9 * http://base64.sourceforge.net/b64.c.
12 static const char cd64
[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMN"
13 "OPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
15 struct buffer_descriptor
{
16 const uint8_t *input_buffer
;
21 #define isalnum(c) ((((c) >= 'a') && ((c) <= 'z')) || \
22 (((c) >= 'A') && ((c) <= 'Z')) || \
23 (((c) >= '0') && ((c) <= '9')))
26 * On each invocation this function returns the next valid base64 character
27 * from the encoded message, ignoring padding and line breaks.
29 * Once all input is consumed, 0 is returned on all following invocations. In
30 * case any other than expected characters is found in the encoded message, -1
31 * is returned for error.
33 static int get_next_char(struct buffer_descriptor
*bd
)
38 * The canonical base64 encoded messages include the following
40 * - '0..9A..Za..z+/' to represent 64 values
42 * - '<CR><LF>' to split the message into lines.
44 while (bd
->input_index
< bd
->data_size
) {
45 c
= bd
->input_buffer
[bd
->input_index
++];
57 if (!isalnum(c
) && (c
!= '+') && (c
!= '/'))
69 ** decode a base64 encoded stream discarding padding and line breaks.
71 size_t b64_decode(const uint8_t *input_data
,
75 struct buffer_descriptor bd
;
76 unsigned int interim
= 0;
77 size_t output_size
= 0;
78 /* count of processed input bits, modulo log2(64) */
79 unsigned int bit_count
= 0;
82 * Keep the context on the stack to make things easier if this needs
85 bd
.input_buffer
= input_data
;
86 bd
.data_size
= input_length
;
89 while (1) { /* Until input is exhausted. */
90 int v
= get_next_char(&bd
);
94 "Incompatible character at offset %zd.\n",
103 * v is guaranteed to be in the proper range for cd64, the
104 * result is a 6 bit number.
106 v
= cd64
[v
- 43] - 62;
108 if (bit_count
>= 2) {
110 * Once 6 more bits are added to the output, there is
111 * going to be at least a full byte.
113 * 'remaining_bits' is the exact number of bits which
114 * need to be added to the output to have another full
117 int remaining_bits
= 8 - bit_count
;
119 interim
<<= remaining_bits
;
120 interim
|= v
>> (6 - remaining_bits
);
122 /* Pass the new full byte to the output. */
123 output_data
[output_size
++] = interim
& 0xff;