* New upstream release:
[debian/iodine.git] / src / base32.c
1 /*
2  * Copyright (c) 2006-2009 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
3  * Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "encoding.h"
23 #include "base32.h"
24
25 #define BLKSIZE_RAW 5
26 #define BLKSIZE_ENC 8
27
28 static const char cb32[] = 
29         "abcdefghijklmnopqrstuvwxyz012345";
30 static const char cb32_ucase[] = 
31         "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
32 static unsigned char rev32[256];
33 static int reverse_init = 0;
34
35 static int base32_encode(char *, size_t *, const void *, size_t);
36 static int base32_decode(void *, size_t *, const char *, size_t);
37 static int base32_handles_dots();
38 static int base32_blksize_raw();
39 static int base32_blksize_enc();
40
41 static struct encoder base32_encoder =
42 {
43         "Base32",
44         base32_encode,
45         base32_decode,
46         base32_handles_dots,
47         base32_handles_dots,
48         base32_blksize_raw,
49         base32_blksize_enc
50 };
51
52 struct encoder
53 *get_base32_encoder()
54 {
55         return &base32_encoder;
56 }
57
58 static int 
59 base32_handles_dots()
60 {
61         return 0;
62 }
63
64 static int 
65 base32_blksize_raw()
66 {
67         return BLKSIZE_RAW;
68 }
69
70 static int 
71 base32_blksize_enc()
72 {
73         return BLKSIZE_ENC;
74 }
75
76 inline static void
77 base32_reverse_init()
78 {
79         int i;
80         unsigned char c;
81
82         if (!reverse_init) {
83                 memset (rev32, 0, 256);
84                 for (i = 0; i < 32; i++) {
85                         c = cb32[i];
86                         rev32[(int) c] = i;
87                         c = cb32_ucase[i];
88                         rev32[(int) c] = i;
89                 }
90                 reverse_init = 1;
91         }
92 }
93
94 int
95 b32_5to8(int in)
96 {
97         return cb32[in & 31];
98 }
99
100 int
101 b32_8to5(int in)
102 {
103         base32_reverse_init();
104         return rev32[in];
105 }
106
107 static int 
108 base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
109 /*
110  * Fills *buf with max. *buflen characters, encoding size bytes of *data.
111  *
112  * NOTE: *buf space should be at least 1 byte _more_ than *buflen
113  * to hold the trailing '\0'.
114  *
115  * return value    : #bytes filled in buf   (excluding \0)
116  * sets *buflen to : #bytes encoded from data
117  */
118 {
119         unsigned char *udata = (unsigned char *) data;
120         int iout = 0;   /* to-be-filled output char */
121         int iin = 0;    /* one more than last input byte that can be
122                            successfully decoded */
123
124         /* Note: Don't bother to optimize manually. GCC optimizes
125            better(!) when using simplistic array indexing. */
126
127         while (1) {
128                 if (iout >= *buflen || iin >= size)
129                         break;
130                 buf[iout] = cb32[((udata[iin] & 0xf8) >> 3)];
131                 iout++;
132
133                 if (iout >= *buflen || iin >= size) {
134                         iout--;         /* previous char is useless */
135                         break;
136                 }
137                 buf[iout] = cb32[((udata[iin] & 0x07) << 2) |
138                                   ((iin + 1 < size) ?
139                                    ((udata[iin + 1] & 0xc0) >> 6) : 0)];
140                 iin++;                  /* 0 complete, iin=1 */
141                 iout++;
142
143                 if (iout >= *buflen || iin >= size)
144                         break;
145                 buf[iout] = cb32[((udata[iin] & 0x3e) >> 1)];
146                 iout++;
147
148                 if (iout >= *buflen || iin >= size) {
149                         iout--;         /* previous char is useless */
150                         break;
151                 }
152                 buf[iout] = cb32[((udata[iin] & 0x01) << 4) |
153                                   ((iin + 1 < size) ?
154                                    ((udata[iin + 1] & 0xf0) >> 4) : 0)];
155                 iin++;                  /* 1 complete, iin=2 */
156                 iout++;
157
158                 if (iout >= *buflen || iin >= size)
159                         break;
160                 buf[iout] = cb32[((udata[iin] & 0x0f) << 1) |
161                                   ((iin + 1 < size) ?
162                                    ((udata[iin + 1] & 0x80) >> 7) : 0)];
163                 iin++;                  /* 2 complete, iin=3 */
164                 iout++;
165
166                 if (iout >= *buflen || iin >= size)
167                         break;
168                 buf[iout] = cb32[((udata[iin] & 0x7c) >> 2)];
169                 iout++;
170
171                 if (iout >= *buflen || iin >= size) {
172                         iout--;         /* previous char is useless */
173                         break;
174                 }
175                 buf[iout] = cb32[((udata[iin] & 0x03) << 3) |
176                                   ((iin + 1 < size) ?
177                                    ((udata[iin + 1] & 0xe0) >> 5) : 0)];
178                 iin++;                  /* 3 complete, iin=4 */
179                 iout++;
180
181                 if (iout >= *buflen || iin >= size)
182                         break;
183                 buf[iout] = cb32[((udata[iin] & 0x1f))];
184                 iin++;                  /* 4 complete, iin=5 */
185                 iout++;
186         }
187
188         buf[iout] = '\0';
189
190         /* store number of bytes from data that was used */
191         *buflen = iin;
192
193         return iout;
194 }
195
196 #define REV32(x) rev32[(int) (x)]
197
198 static int
199 base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
200 /*
201  * Fills *buf with max. *buflen bytes, decoded from slen chars in *str.
202  * Decoding stops early when *str contains \0.
203  * Illegal encoded chars are assumed to decode to zero.
204  *
205  * NOTE: *buf space should be at least 1 byte _more_ than *buflen
206  * to hold a trailing '\0' that is added (though *buf will usually
207  * contain full-binary data).
208  *
209  * return value    : #bytes filled in buf   (excluding \0)
210  */
211 {
212         unsigned char *ubuf = (unsigned char *) buf;
213         int iout = 0;   /* to-be-filled output byte */
214         int iin = 0;    /* next input char to use in decoding */
215
216         base32_reverse_init ();
217
218         /* Note: Don't bother to optimize manually. GCC optimizes
219            better(!) when using simplistic array indexing. */
220
221         while (1) {
222                 if (iout >= *buflen || iin + 1 >= slen ||
223                     str[iin] == '\0' || str[iin + 1] == '\0')
224                         break;
225                 ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) | 
226                              ((REV32(str[iin + 1]) & 0x1c) >> 2);
227                 iin++;                  /* 0 used up, iin=1 */
228                 iout++;
229
230                 if (iout >= *buflen || iin + 2 >= slen ||
231                     str[iin] == '\0' || str[iin + 1] == '\0' ||
232                     str[iin + 2] == '\0')
233                         break;
234                 ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) | 
235                              ((REV32(str[iin + 1]) & 0x1f) << 1) | 
236                              ((REV32(str[iin + 2]) & 0x10) >> 4);
237                 iin += 2;               /* 1,2 used up, iin=3 */
238                 iout++;
239
240                 if (iout >= *buflen || iin + 1 >= slen ||
241                     str[iin] == '\0' || str[iin + 1] == '\0')
242                         break;
243                 ubuf[iout] = ((REV32(str[iin]) & 0x0f) << 4) |
244                              ((REV32(str[iin + 1]) & 0x1e) >> 1);
245                 iin++;                  /* 3 used up, iin=4 */
246                 iout++;
247
248                 if (iout >= *buflen || iin + 2 >= slen ||
249                     str[iin] == '\0' || str[iin + 1] == '\0' ||
250                     str[iin + 2] == '\0')
251                         break;
252                 ubuf[iout] = ((REV32(str[iin]) & 0x01) << 7) |
253                              ((REV32(str[iin + 1]) & 0x1f) << 2) |
254                              ((REV32(str[iin + 2]) & 0x18) >> 3);
255                 iin += 2;               /* 4,5 used up, iin=6 */
256                 iout++;
257
258                 if (iout >= *buflen || iin + 1 >= slen ||
259                     str[iin] == '\0' || str[iin + 1] == '\0')
260                         break;
261                 ubuf[iout] = ((REV32(str[iin]) & 0x07) << 5) |
262                              ((REV32(str[iin + 1]) & 0x1f));
263                 iin += 2;               /* 6,7 used up, iin=8 */
264                 iout++;
265         }
266
267         ubuf[iout] = '\0';
268
269         return iout;
270 }