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