]> git.proxmox.com Git - mirror_frr.git/blame - lib/base64.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / base64.c
CommitLineData
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
13static const int CHARS_PER_LINE = 72;
14static const char *ENCODING =
15 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
16
17void 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
24char base64_encode_value(char value_in)
25{
26 if (value_in > 63)
27 return '=';
28 return ENCODING[(int)value_in];
29}
30
31int 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
89int 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
112signed 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
132void base64_init_decodestate(struct base64_decodestate *state_in)
133{
134 state_in->step = step_a;
135 state_in->plainchar = 0;
136}
137
138int 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}