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