2 Copyright 2015, 2016, 2017 IoT.bzh
4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
24 #include "wgtpkg-base64.h"
26 static char tob64(char x)
29 return (char)('A' + x);
31 return (char)('a' + x - 26);
33 return (char)('0' + x - 52);
34 return x == 62 ? '+' : '/';
37 char *base64encw(const char *buffer, size_t length, unsigned width)
39 size_t remain, in, out;
42 if (width == 0 || (width & 3) != 0) {
43 ERROR("bad width in base64enc");
46 result = malloc(2 + 4 * ((length + 2) / 3) + (length / width));
48 ERROR("malloc failed in base64enc");
54 if (out % (width + 1) == width)
56 result[out] = tob64((buffer[in] >> 2) & '\x3f');
57 result[out+1] = tob64((char)(((buffer[in] << 4) & '\x30')
58 | ((buffer[in+1] >> 4) & '\x0f')));
59 result[out+2] = tob64((char)(((buffer[in+1] << 2) & '\x3c')
60 | ((buffer[in+2] >> 6) & '\x03')));
61 result[out+3] = tob64(buffer[in+2] & '\x3f');
67 if (out % (width + 1) == width)
69 result[out] = tob64((buffer[in] >> 2) & '\x3f');
71 result[out+1] = tob64((buffer[in] << 4) & '\x30');
74 result[out+1] = tob64((char)(((buffer[in] << 4) & '\x30')
75 | ((buffer[in+1] >> 4) & '\x0f')));
76 result[out+2] = tob64((buffer[in+1] << 2) & '\x3c');
85 char *base64enc(const char *buffer, size_t length)
87 return base64encw(buffer, length, 76);
90 static char fromb64(char x)
92 if ('A' <= x && x <= 'Z')
93 return (char)(x - 'A');
94 if ('a' <= x && x <= 'z')
95 return (char)(x - 'a' + 26);
96 if ('0' <= x && x <= '9')
97 return (char)(x - '0' + 52);
107 ssize_t base64dec(const char *buffer, char **output)
112 unsigned char x0, x1, x2, x3;
114 len = strlen(buffer);
115 result = malloc(3 * ((3 + len) / 4));
116 if (result == NULL) {
117 ERROR("malloc failed in base64dec");
122 while (buffer[in] == '\r' || buffer[in] == '\n')
126 ERROR("unexpected input size in base64dec");
130 x0 = (unsigned char)fromb64(buffer[in]);
131 x1 = (unsigned char)fromb64(buffer[in+1]);
132 x2 = (unsigned char)fromb64(buffer[in+2]);
133 x3 = (unsigned char)fromb64(buffer[in+3]);
135 if (x0 == 'E' || x1 == 'E' || x2 == 'E' || x3 == 'E') {
136 ERROR("unexpected input character in base64dec");
140 if (x0 == '@' || x1 == '@' || (x2 == '@' && x3 != '@')) {
141 ERROR("unexpected termination character in base64dec");
145 result[out] = (char)((x0 << 2) | (x1 >> 4));
146 result[out+1] = (char)((x1 << 4) | ((x2 >> 2) & 15));
147 result[out+2] = (char)((x2 << 6) | (x3 & 63));
148 while (buffer[in] == '\r' || buffer[in] == '\n')
152 else if (!buffer[in])
153 out += 1 + (unsigned)(x2 != '@');
155 ERROR("unexpected continuation in base64dec");
160 ERROR("output too big in base64dec");
169 int base64eq(const char *buf1, const char *buf2)
172 while(*buf1 == '\n' || *buf1 == '\r')
174 while(*buf2 == '\n' || *buf2 == '\r')
189 int main(int ac, char **av)
196 fd = open(*av, O_RDONLY);
197 if (fd < 0) continue;
198 l0 = read(fd, buffer, sizeof buffer);
199 if (l0 <= 0) continue;
201 p1 = base64enc(buffer, l0);
204 l2 = base64dec(p1, &p2);
205 if (l2 <= 0) continue;
206 printf("[[[%.*s]]]\n",l2,p2);
207 if (l0 != l2) printf("length mismatch\n");
208 else if (memcmp(buffer, p2, l0)) printf("content mismatch\n");