Line data Source code
1 : // SPDX-License-Identifier: NONE
2 : /*
3 : * This is part of the libb64 project, and has been placed in the public domain.
4 : * For details, see http://sourceforge.net/projects/libb64
5 : */
6 :
7 : #ifdef HAVE_CONFIG_H
8 : #include "config.h"
9 : #endif
10 :
11 : #include "base64.h"
12 : #include "compiler.h"
13 :
14 : static const int CHARS_PER_LINE = 72;
15 : static const char *ENCODING =
16 : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
17 :
18 0 : void base64_init_encodestate(struct base64_encodestate *state_in)
19 : {
20 0 : state_in->step = step_A;
21 0 : state_in->result = 0;
22 0 : state_in->stepcount = 0;
23 0 : }
24 :
25 0 : char base64_encode_value(char value_in)
26 : {
27 0 : if (value_in > 63)
28 : return '=';
29 0 : return ENCODING[(int)value_in];
30 : }
31 :
32 0 : int base64_encode_block(const char *plaintext_in, int length_in, char *code_out,
33 : struct base64_encodestate *state_in)
34 : {
35 0 : const char *plainchar = plaintext_in;
36 0 : const char *const plaintextend = plaintext_in + length_in;
37 0 : char *codechar = code_out;
38 0 : char result;
39 0 : char fragment;
40 :
41 0 : result = state_in->result;
42 :
43 0 : switch (state_in->step) {
44 0 : while (1) {
45 0 : fallthrough;
46 : case step_A:
47 0 : if (plainchar == plaintextend) {
48 0 : state_in->result = result;
49 0 : state_in->step = step_A;
50 0 : return codechar - code_out;
51 : }
52 0 : fragment = *plainchar++;
53 0 : result = (fragment & 0x0fc) >> 2;
54 0 : *codechar++ = base64_encode_value(result);
55 0 : result = (fragment & 0x003) << 4;
56 0 : fallthrough;
57 0 : case step_B:
58 0 : if (plainchar == plaintextend) {
59 0 : state_in->result = result;
60 0 : state_in->step = step_B;
61 0 : return codechar - code_out;
62 : }
63 0 : fragment = *plainchar++;
64 0 : result |= (fragment & 0x0f0) >> 4;
65 0 : *codechar++ = base64_encode_value(result);
66 0 : result = (fragment & 0x00f) << 2;
67 0 : fallthrough;
68 0 : case step_C:
69 0 : if (plainchar == plaintextend) {
70 0 : state_in->result = result;
71 0 : state_in->step = step_C;
72 0 : return codechar - code_out;
73 : }
74 0 : fragment = *plainchar++;
75 0 : result |= (fragment & 0x0c0) >> 6;
76 0 : *codechar++ = base64_encode_value(result);
77 0 : result = (fragment & 0x03f) >> 0;
78 0 : *codechar++ = base64_encode_value(result);
79 :
80 0 : ++(state_in->stepcount);
81 0 : if (state_in->stepcount == CHARS_PER_LINE/4) {
82 0 : *codechar++ = '\n';
83 0 : state_in->stepcount = 0;
84 : }
85 : }
86 : }
87 : /* control should not reach here */
88 : return codechar - code_out;
89 : }
90 :
91 0 : int base64_encode_blockend(char *code_out, struct base64_encodestate *state_in)
92 : {
93 0 : char *codechar = code_out;
94 :
95 0 : switch (state_in->step) {
96 0 : case step_B:
97 0 : *codechar++ = base64_encode_value(state_in->result);
98 0 : *codechar++ = '=';
99 0 : *codechar++ = '=';
100 0 : break;
101 0 : case step_C:
102 0 : *codechar++ = base64_encode_value(state_in->result);
103 0 : *codechar++ = '=';
104 0 : break;
105 : case step_A:
106 : break;
107 : }
108 0 : *codechar++ = '\n';
109 :
110 0 : return codechar - code_out;
111 : }
112 :
113 :
114 0 : signed char base64_decode_value(signed char value_in)
115 : {
116 0 : static const signed char decoding[] = {
117 : 62, -1, -1, -1, 63, 52, 53, 54,
118 : 55, 56, 57, 58, 59, 60, 61, -1,
119 : -1, -1, -2, -1, -1, -1, 0, 1,
120 : 2, 3, 4, 5, 6, 7, 8, 9,
121 : 10, 11, 12, 13, 14, 15, 16, 17,
122 : 18, 19, 20, 21, 22, 23, 24, 25,
123 : -1, -1, -1, -1, -1, -1, 26, 27,
124 : 28, 29, 30, 31, 32, 33, 34, 35,
125 : 36, 37, 38, 39, 40, 41, 42, 43,
126 : 44, 45, 46, 47, 48, 49, 50, 51
127 : };
128 0 : value_in -= 43;
129 0 : if (value_in < 0 || value_in >= 80)
130 : return -1;
131 0 : return decoding[(int)value_in];
132 : }
133 :
134 0 : void base64_init_decodestate(struct base64_decodestate *state_in)
135 : {
136 0 : state_in->step = step_a;
137 0 : state_in->plainchar = 0;
138 0 : }
139 :
140 0 : int base64_decode_block(const char *code_in, int length_in, char *plaintext_out,
141 : struct base64_decodestate *state_in)
142 : {
143 0 : const char *codec = code_in;
144 0 : char *plainc = plaintext_out;
145 0 : signed char fragmt;
146 :
147 0 : *plainc = state_in->plainchar;
148 :
149 0 : switch (state_in->step) {
150 0 : while (1) {
151 0 : fallthrough;
152 : case step_a:
153 0 : do {
154 0 : if (codec == code_in+length_in) {
155 0 : state_in->step = step_a;
156 0 : state_in->plainchar = *plainc;
157 0 : return plainc - plaintext_out;
158 : }
159 0 : fragmt = base64_decode_value(*codec++);
160 0 : } while (fragmt < 0);
161 0 : *plainc = (fragmt & 0x03f) << 2;
162 0 : fallthrough;
163 0 : case step_b:
164 0 : do {
165 0 : if (codec == code_in+length_in) {
166 0 : state_in->step = step_b;
167 0 : state_in->plainchar = *plainc;
168 0 : return plainc - plaintext_out;
169 : }
170 0 : fragmt = base64_decode_value(*codec++);
171 0 : } while (fragmt < 0);
172 0 : *plainc++ |= (fragmt & 0x030) >> 4;
173 0 : *plainc = (fragmt & 0x00f) << 4;
174 0 : fallthrough;
175 0 : case step_c:
176 0 : do {
177 0 : if (codec == code_in+length_in) {
178 0 : state_in->step = step_c;
179 0 : state_in->plainchar = *plainc;
180 0 : return plainc - plaintext_out;
181 : }
182 0 : fragmt = base64_decode_value(*codec++);
183 0 : } while (fragmt < 0);
184 0 : *plainc++ |= (fragmt & 0x03c) >> 2;
185 0 : *plainc = (fragmt & 0x003) << 6;
186 0 : fallthrough;
187 0 : case step_d:
188 0 : do {
189 0 : if (codec == code_in+length_in) {
190 0 : state_in->step = step_d;
191 0 : state_in->plainchar = *plainc;
192 0 : return plainc - plaintext_out;
193 : }
194 0 : fragmt = base64_decode_value(*codec++);
195 0 : } while (fragmt < 0);
196 0 : *plainc++ |= (fragmt & 0x03f);
197 : }
198 : }
199 : /* control should not reach here */
200 : return plainc - plaintext_out;
201 : }
|