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