1 /*
2  * Copyright (c) 2015 by Farsight Security, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Copyright (c) 2006 Christian Biere <christianbiere@gmx.de>
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions
23  * are met:
24  *
25  * 1. Redistributions of source code must retain the above copyright
26  *	notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *	notice, this list of conditions and the following disclaimer in the
29  *	documentation and/or other materials provided with the distribution.
30  * 3. Neither the name of the authors nor the names of its contributors
31  *	may be used to endorse or promote products derived from this software
32  *	without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37  * ARE DISCLAIMED.	IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  */
46 
47 /*
48  * See RFC 4648 for details about Base 32 hex encoding:
49  *     http://tools.ietf.org/html/rfc4648
50  */
51 
52 #include <stdint.h>
53 #include <string.h>
54 
55 #include "b32_decode.h"
56 
57 #ifndef G_N_ELEMENTS
58 #define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
59 #endif
60 
61 #define ZERO(x)         memset((x), 0, sizeof *(x))
62 
63 static inline void *
ptr_add_offset(void * p,size_t offset)64 ptr_add_offset(void *p, size_t offset)
65 {
66         /* Using size_t instead of 'char *' because pointers don't wrap. */
67         return (void *) ((size_t) p + offset);
68 }
69 
70 static inline const void *
cast_to_constpointer(const void * p)71 cast_to_constpointer(const void *p)
72 {
73         return p;
74 }
75 
76 static inline bool
is_ascii_lower(int c)77 is_ascii_lower(int c)
78 {
79         return c >= 97 && c <= 122;             /* a-z */
80 }
81 
82 static inline int
ascii_toupper(int c)83 ascii_toupper(int c)
84 {
85         return is_ascii_lower(c) ? c - 32 : c;
86 }
87 
88 static inline size_t
ptr_diff(const void * a,const void * b)89 ptr_diff(const void *a, const void *b)
90 {
91         return (const char *) a - (const char *) b;
92 }
93 
94 static const char base32_alphabet[32] = {
95 	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
96 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
97 	'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
98 	'U', 'V'
99 };
100 
101 static char base32_map[(size_t) (unsigned char) -1 + 1];
102 
103 /**
104  * Decode a base32 encoding of `len' bytes of `data' into the buffer `dst'.
105  *
106  * @param dst		destination buffer
107  * @param size		length of destination
108  * @param data		start of data to decode
109  * @param len		amount of encoded data to decode
110  *
111  * @return the amount of bytes decoded into the destination.
112  */
113 size_t
base32_decode(void * dst,size_t size,const char * data,size_t len)114 base32_decode(void *dst, size_t size, const char *data, size_t len)
115 {
116 	const char *end = ptr_add_offset(dst, size);
117 	const unsigned char *p = cast_to_constpointer(data);
118 	char s[8];
119 	char *q = dst;
120 	int pad = 0;
121 	size_t i, si;
122 
123 	if (0 == base32_map[0]) {
124 		for (i = 0; i < G_N_ELEMENTS(base32_map); i++) {
125 			const char *x;
126 
127 			x = memchr(base32_alphabet, ascii_toupper(i),
128 					   sizeof base32_alphabet);
129 			base32_map[i] = x ? (x - base32_alphabet) : (unsigned char) -1;
130 		}
131 	}
132 
133 	ZERO(&s);
134 	si = 0;
135 	i = 0;
136 
137 	while (i < len) {
138 		unsigned char c;
139 
140 		c = p[i++];
141 		if ('=' == c) {
142 			pad++;
143 			c = 0;
144 		} else {
145 			c = base32_map[c];
146 			if ((unsigned char) -1 == c) {
147 				return -1;
148 			}
149 		}
150 
151 		s[si++] = c;
152 
153 		if (G_N_ELEMENTS(s) == si || pad > 0 || i == len) {
154 			char b[5];
155 			size_t bi;
156 
157 			memset(&s[si], 0, G_N_ELEMENTS(s) - si);
158 			si = 0;
159 
160 			b[0] =
161 				((s[0] << 3) & 0xf8) |
162 				((s[1] >> 2) & 0x07);
163 			b[1] =
164 				((s[1] & 0x03) << 6) |
165 				((s[2] & 0x1f) << 1) |
166 				((s[3] >> 4) & 1);
167 			b[2] =
168 				((s[3] & 0x0f) << 4) |
169 				((s[4] >> 1) & 0x0f);
170 			b[3] =
171 				((s[4] & 1) << 7) |
172 				((s[5] & 0x1f) << 2) |
173 				((s[6] >> 3) & 0x03);
174 			b[4] =
175 				((s[6] & 0x07) << 5) |
176 				(s[7] & 0x1f);
177 
178 			for (bi = 0; bi < G_N_ELEMENTS(b) && q != end; bi++) {
179 				*q++ = b[bi];
180 			}
181 		}
182 
183 		if (end == q) {
184 			break;
185 		}
186 	}
187 
188 	return ptr_diff(q, dst);
189 }
190