New upstream release:
[debian/iodine.git] / src / base32.c
1 /*
2  * Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "encoding.h"
22 #include "base32.h"
23
24 static const char cb32[] = 
25         "abcdefghijklmnopqrstuvwxyz0123456789";
26 static unsigned char rev32[128];
27 static int reverse_init = 0;
28
29 static struct encoder base32_encoder =
30 {
31         "BASE32",
32         base32_encode,
33         base32_decode,
34         base32_handles_dots,
35         base32_handles_dots
36 };
37
38 struct encoder
39 *get_base32_encoder()
40 {
41         return &base32_encoder;
42 }
43
44 int 
45 base32_handles_dots()
46 {
47         return 0;
48 }
49
50 int 
51 base32_encode(char *buf, size_t *buflen, const void *data, size_t size)
52 {
53         size_t newsize;
54         size_t maxsize;
55         unsigned char *s;
56         unsigned char *p;
57         unsigned char *q;
58         int i;
59
60         memset(buf, 0, *buflen);
61
62         /* how many chars can we encode within the buf */
63         maxsize = 5 * (*buflen / 8 - 1) - 1;
64         /* how big will the encoded data be */
65         newsize = 8 * (size / 5 + 1) + 1;
66         /* if the buffer is too small, eat some of the data */
67         if (*buflen < newsize) {
68                 size = maxsize;
69         }
70
71         p = s = (unsigned char *) buf;
72         q = (unsigned char *)data;
73
74         for(i=0;i<size;i+=5) {
75                 p[0] = cb32[((q[0] & 0xf8) >> 3)];
76                 p[1] = cb32[(((q[0] & 0x07) << 2) | ((q[1] & 0xc0) >> 6))];
77                 p[2] = (i+1 < size) ? cb32[((q[1] & 0x3e) >> 1)] : '\0';
78                 p[3] = (i+1 < size) ? cb32[((q[1] & 0x01) << 4) | ((q[2] & 0xf0) >> 4)] : '\0';
79                 p[4] = (i+2 < size) ? cb32[((q[2] & 0x0f) << 1) | ((q[3] & 0x80) >> 7)] : '\0';
80                 p[5] = (i+3 < size) ? cb32[((q[3] & 0x7c) >> 2)] : '\0';
81                 p[6] = (i+3 < size) ? cb32[((q[3] & 0x03) << 3) | ((q[4] & 0xe0) >> 5)] : '\0';
82                 p[7] = (i+4 < size) ? cb32[((q[4] & 0x1f))] : '\0';
83                 
84                 q += 5;
85                 p += 8;
86         }       
87         *p = 0;
88
89         /* store number of bytes from data that was used */
90         *buflen = size;
91
92         return strlen(buf) - 1;
93 }
94
95 #define DECODE_ERROR 0xffffffff
96 #define REV32(x) rev32[(int) (x)]
97
98 static int
99 decode_token(const unsigned char *t, unsigned char *data, size_t len) 
100 {
101         if (len < 2)
102                 return 0;
103
104         data[0] = ((REV32(t[0]) & 0x1f) << 3) | 
105                           ((REV32(t[1]) & 0x1c) >> 2);
106         
107         if (len < 4)
108                 return 1;
109
110         data[1] = ((REV32(t[1]) & 0x03) << 6) | 
111                           ((REV32(t[2]) & 0x1f) << 1) | 
112                           ((REV32(t[3]) & 0x10) >> 4);
113
114         if (len < 5)
115                 return 2;
116
117         data[2] = ((REV32(t[3]) & 0x0f) << 4) |
118                           ((REV32(t[4]) & 0x1e) >> 1);
119
120         if (len < 7)
121                 return 3;
122
123         data[3] = ((REV32(t[4]) & 0x01) << 7) |
124                           ((REV32(t[5]) & 0x1f) << 2) |
125                           ((REV32(t[6]) & 0x18) >> 3);
126
127         if (len < 8)
128                 return 4;
129
130         data[4] = ((REV32(t[6]) & 0x07) << 5) |
131                           ((REV32(t[7]) & 0x1f));
132
133         return 5;
134 }
135
136 int
137 base32_decode(void *buf, size_t *buflen, const char *str, size_t slen)
138 {
139         unsigned char *q;
140         size_t newsize;
141         size_t maxsize;
142         const char *p;
143         unsigned char c;
144         int len;
145         int i;
146
147         if (!reverse_init) {
148                 for (i = 0; i < 32; i++) {
149                         c = cb32[i];
150                         rev32[(int) c] = i;
151                 }
152                 reverse_init = 1;
153         }
154         
155         /* chars needed to decode slen */
156         newsize = 5 * (slen / 8 + 1) + 1;
157         /* encoded chars that fit in buf */
158         maxsize = 8 * (*buflen / 5 + 1) + 1;
159         /* if the buffer is too small, eat some of the data */
160         if (*buflen < newsize) {
161                 slen = maxsize;
162         }
163
164         q = buf;
165         for (p = str; *p && strchr(cb32, *p); p += 8) {
166                 len = decode_token((unsigned char *) p, (unsigned char *) q, slen);     
167                 q += len;
168                 slen -= 8;
169                 
170                 if (len < 5)
171                         break;
172         }
173         *q = '\0';
174         
175         return q - (unsigned char *) buf;
176 }
177