1*ae8c6e27Sflorian /*
2*ae8c6e27Sflorian  * parseutil.c - parse utilities for string and wire conversion
3*ae8c6e27Sflorian  *
4*ae8c6e27Sflorian  * (c) NLnet Labs, 2004-2006
5*ae8c6e27Sflorian  *
6*ae8c6e27Sflorian  * See the file LICENSE for the license
7*ae8c6e27Sflorian  */
8*ae8c6e27Sflorian /**
9*ae8c6e27Sflorian  * \file
10*ae8c6e27Sflorian  *
11*ae8c6e27Sflorian  * Utility functions for parsing, base32(DNS variant) and base64 encoding
12*ae8c6e27Sflorian  * and decoding, Hex, Time units, Escape codes.
13*ae8c6e27Sflorian  */
14*ae8c6e27Sflorian 
15*ae8c6e27Sflorian #include "config.h"
16*ae8c6e27Sflorian #include "sldns/parseutil.h"
17*ae8c6e27Sflorian #include <sys/time.h>
18*ae8c6e27Sflorian #include <time.h>
19*ae8c6e27Sflorian #include <ctype.h>
20*ae8c6e27Sflorian 
21*ae8c6e27Sflorian sldns_lookup_table *
22*ae8c6e27Sflorian sldns_lookup_by_name(sldns_lookup_table *table, const char *name)
23*ae8c6e27Sflorian {
24*ae8c6e27Sflorian         while (table->name != NULL) {
25*ae8c6e27Sflorian                 if (strcasecmp(name, table->name) == 0)
26*ae8c6e27Sflorian                         return table;
27*ae8c6e27Sflorian                 table++;
28*ae8c6e27Sflorian         }
29*ae8c6e27Sflorian         return NULL;
30*ae8c6e27Sflorian }
31*ae8c6e27Sflorian 
32*ae8c6e27Sflorian sldns_lookup_table *
33*ae8c6e27Sflorian sldns_lookup_by_id(sldns_lookup_table *table, int id)
34*ae8c6e27Sflorian {
35*ae8c6e27Sflorian         while (table->name != NULL) {
36*ae8c6e27Sflorian                 if (table->id == id)
37*ae8c6e27Sflorian                         return table;
38*ae8c6e27Sflorian                 table++;
39*ae8c6e27Sflorian         }
40*ae8c6e27Sflorian         return NULL;
41*ae8c6e27Sflorian }
42*ae8c6e27Sflorian 
43*ae8c6e27Sflorian /* Number of days per month (except for February in leap years). */
44*ae8c6e27Sflorian static const int mdays[] = {
45*ae8c6e27Sflorian 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
46*ae8c6e27Sflorian };
47*ae8c6e27Sflorian 
48*ae8c6e27Sflorian #define LDNS_MOD(x,y) (((x) % (y) < 0) ? ((x) % (y) + (y)) : ((x) % (y)))
49*ae8c6e27Sflorian #define LDNS_DIV(x,y) (((x) % (y) < 0) ? ((x) / (y) -  1 ) : ((x) / (y)))
50*ae8c6e27Sflorian 
51*ae8c6e27Sflorian static int
52*ae8c6e27Sflorian is_leap_year(int year)
53*ae8c6e27Sflorian {
54*ae8c6e27Sflorian 	return LDNS_MOD(year,   4) == 0 && (LDNS_MOD(year, 100) != 0
55*ae8c6e27Sflorian 	    || LDNS_MOD(year, 400) == 0);
56*ae8c6e27Sflorian }
57*ae8c6e27Sflorian 
58*ae8c6e27Sflorian static int
59*ae8c6e27Sflorian leap_days(int y1, int y2)
60*ae8c6e27Sflorian {
61*ae8c6e27Sflorian 	--y1;
62*ae8c6e27Sflorian 	--y2;
63*ae8c6e27Sflorian 	return (LDNS_DIV(y2,   4) - LDNS_DIV(y1,   4)) -
64*ae8c6e27Sflorian 	       (LDNS_DIV(y2, 100) - LDNS_DIV(y1, 100)) +
65*ae8c6e27Sflorian 	       (LDNS_DIV(y2, 400) - LDNS_DIV(y1, 400));
66*ae8c6e27Sflorian }
67*ae8c6e27Sflorian 
68*ae8c6e27Sflorian /*
69*ae8c6e27Sflorian  * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
70*ae8c6e27Sflorian  */
71*ae8c6e27Sflorian time_t
72*ae8c6e27Sflorian sldns_mktime_from_utc(const struct tm *tm)
73*ae8c6e27Sflorian {
74*ae8c6e27Sflorian 	int year = 1900 + tm->tm_year;
75*ae8c6e27Sflorian 	time_t days = 365 * ((time_t) year - 1970) + leap_days(1970, year);
76*ae8c6e27Sflorian 	time_t hours;
77*ae8c6e27Sflorian 	time_t minutes;
78*ae8c6e27Sflorian 	time_t seconds;
79*ae8c6e27Sflorian 	int i;
80*ae8c6e27Sflorian 
81*ae8c6e27Sflorian 	for (i = 0; i < tm->tm_mon; ++i) {
82*ae8c6e27Sflorian 		days += mdays[i];
83*ae8c6e27Sflorian 	}
84*ae8c6e27Sflorian 	if (tm->tm_mon > 1 && is_leap_year(year)) {
85*ae8c6e27Sflorian 		++days;
86*ae8c6e27Sflorian 	}
87*ae8c6e27Sflorian 	days += tm->tm_mday - 1;
88*ae8c6e27Sflorian 
89*ae8c6e27Sflorian 	hours = days * 24 + tm->tm_hour;
90*ae8c6e27Sflorian 	minutes = hours * 60 + tm->tm_min;
91*ae8c6e27Sflorian 	seconds = minutes * 60 + tm->tm_sec;
92*ae8c6e27Sflorian 
93*ae8c6e27Sflorian 	return seconds;
94*ae8c6e27Sflorian }
95*ae8c6e27Sflorian 
96*ae8c6e27Sflorian #if SIZEOF_TIME_T <= 4
97*ae8c6e27Sflorian 
98*ae8c6e27Sflorian static void
99*ae8c6e27Sflorian sldns_year_and_yday_from_days_since_epoch(int64_t days, struct tm *result)
100*ae8c6e27Sflorian {
101*ae8c6e27Sflorian 	int year = 1970;
102*ae8c6e27Sflorian 	int new_year;
103*ae8c6e27Sflorian 
104*ae8c6e27Sflorian 	while (days < 0 || days >= (int64_t) (is_leap_year(year) ? 366 : 365)) {
105*ae8c6e27Sflorian 		new_year = year + (int) LDNS_DIV(days, 365);
106*ae8c6e27Sflorian 		days -= (new_year - year) * 365;
107*ae8c6e27Sflorian 		days -= leap_days(year, new_year);
108*ae8c6e27Sflorian 		year  = new_year;
109*ae8c6e27Sflorian 	}
110*ae8c6e27Sflorian 	result->tm_year = year;
111*ae8c6e27Sflorian 	result->tm_yday = (int) days;
112*ae8c6e27Sflorian }
113*ae8c6e27Sflorian 
114*ae8c6e27Sflorian /* Number of days per month in a leap year. */
115*ae8c6e27Sflorian static const int leap_year_mdays[] = {
116*ae8c6e27Sflorian 	31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
117*ae8c6e27Sflorian };
118*ae8c6e27Sflorian 
119*ae8c6e27Sflorian static void
120*ae8c6e27Sflorian sldns_mon_and_mday_from_year_and_yday(struct tm *result)
121*ae8c6e27Sflorian {
122*ae8c6e27Sflorian 	int idays = result->tm_yday;
123*ae8c6e27Sflorian 	const int *mon_lengths = is_leap_year(result->tm_year) ?
124*ae8c6e27Sflorian 					leap_year_mdays : mdays;
125*ae8c6e27Sflorian 
126*ae8c6e27Sflorian 	result->tm_mon = 0;
127*ae8c6e27Sflorian 	while  (idays >= mon_lengths[result->tm_mon]) {
128*ae8c6e27Sflorian 		idays -= mon_lengths[result->tm_mon++];
129*ae8c6e27Sflorian 	}
130*ae8c6e27Sflorian 	result->tm_mday = idays + 1;
131*ae8c6e27Sflorian }
132*ae8c6e27Sflorian 
133*ae8c6e27Sflorian static void
134*ae8c6e27Sflorian sldns_wday_from_year_and_yday(struct tm *result)
135*ae8c6e27Sflorian {
136*ae8c6e27Sflorian 	result->tm_wday = 4 /* 1-1-1970 was a thursday */
137*ae8c6e27Sflorian 			+ LDNS_MOD((result->tm_year - 1970), 7) * LDNS_MOD(365, 7)
138*ae8c6e27Sflorian 			+ leap_days(1970, result->tm_year)
139*ae8c6e27Sflorian 			+ result->tm_yday;
140*ae8c6e27Sflorian 	result->tm_wday = LDNS_MOD(result->tm_wday, 7);
141*ae8c6e27Sflorian 	if (result->tm_wday < 0) {
142*ae8c6e27Sflorian 		result->tm_wday += 7;
143*ae8c6e27Sflorian 	}
144*ae8c6e27Sflorian }
145*ae8c6e27Sflorian 
146*ae8c6e27Sflorian static struct tm *
147*ae8c6e27Sflorian sldns_gmtime64_r(int64_t clock, struct tm *result)
148*ae8c6e27Sflorian {
149*ae8c6e27Sflorian 	result->tm_isdst = 0;
150*ae8c6e27Sflorian 	result->tm_sec   = (int) LDNS_MOD(clock, 60);
151*ae8c6e27Sflorian 	clock            =       LDNS_DIV(clock, 60);
152*ae8c6e27Sflorian 	result->tm_min   = (int) LDNS_MOD(clock, 60);
153*ae8c6e27Sflorian 	clock            =       LDNS_DIV(clock, 60);
154*ae8c6e27Sflorian 	result->tm_hour  = (int) LDNS_MOD(clock, 24);
155*ae8c6e27Sflorian 	clock            =       LDNS_DIV(clock, 24);
156*ae8c6e27Sflorian 
157*ae8c6e27Sflorian 	sldns_year_and_yday_from_days_since_epoch(clock, result);
158*ae8c6e27Sflorian 	sldns_mon_and_mday_from_year_and_yday(result);
159*ae8c6e27Sflorian 	sldns_wday_from_year_and_yday(result);
160*ae8c6e27Sflorian 	result->tm_year -= 1900;
161*ae8c6e27Sflorian 
162*ae8c6e27Sflorian 	return result;
163*ae8c6e27Sflorian }
164*ae8c6e27Sflorian 
165*ae8c6e27Sflorian #endif /* SIZEOF_TIME_T <= 4 */
166*ae8c6e27Sflorian 
167*ae8c6e27Sflorian static int64_t
168*ae8c6e27Sflorian sldns_serial_arithmetics_time(int32_t time, time_t now)
169*ae8c6e27Sflorian {
170*ae8c6e27Sflorian 	int32_t offset = time - (int32_t) now;
171*ae8c6e27Sflorian 	return (int64_t) now + offset;
172*ae8c6e27Sflorian }
173*ae8c6e27Sflorian 
174*ae8c6e27Sflorian struct tm *
175*ae8c6e27Sflorian sldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct tm *result)
176*ae8c6e27Sflorian {
177*ae8c6e27Sflorian #if SIZEOF_TIME_T <= 4
178*ae8c6e27Sflorian 	int64_t secs_since_epoch = sldns_serial_arithmetics_time(time, now);
179*ae8c6e27Sflorian 	return  sldns_gmtime64_r(secs_since_epoch, result);
180*ae8c6e27Sflorian #else
181*ae8c6e27Sflorian 	time_t  secs_since_epoch = sldns_serial_arithmetics_time(time, now);
182*ae8c6e27Sflorian 	return  gmtime_r(&secs_since_epoch, result);
183*ae8c6e27Sflorian #endif
184*ae8c6e27Sflorian }
185*ae8c6e27Sflorian 
186*ae8c6e27Sflorian int
187*ae8c6e27Sflorian sldns_hexdigit_to_int(char ch)
188*ae8c6e27Sflorian {
189*ae8c6e27Sflorian 	switch (ch) {
190*ae8c6e27Sflorian 	case '0': return 0;
191*ae8c6e27Sflorian 	case '1': return 1;
192*ae8c6e27Sflorian 	case '2': return 2;
193*ae8c6e27Sflorian 	case '3': return 3;
194*ae8c6e27Sflorian 	case '4': return 4;
195*ae8c6e27Sflorian 	case '5': return 5;
196*ae8c6e27Sflorian 	case '6': return 6;
197*ae8c6e27Sflorian 	case '7': return 7;
198*ae8c6e27Sflorian 	case '8': return 8;
199*ae8c6e27Sflorian 	case '9': return 9;
200*ae8c6e27Sflorian 	case 'a': case 'A': return 10;
201*ae8c6e27Sflorian 	case 'b': case 'B': return 11;
202*ae8c6e27Sflorian 	case 'c': case 'C': return 12;
203*ae8c6e27Sflorian 	case 'd': case 'D': return 13;
204*ae8c6e27Sflorian 	case 'e': case 'E': return 14;
205*ae8c6e27Sflorian 	case 'f': case 'F': return 15;
206*ae8c6e27Sflorian 	default:
207*ae8c6e27Sflorian 		return -1;
208*ae8c6e27Sflorian 	}
209*ae8c6e27Sflorian }
210*ae8c6e27Sflorian 
211*ae8c6e27Sflorian uint32_t
212*ae8c6e27Sflorian sldns_str2period(const char *nptr, const char **endptr)
213*ae8c6e27Sflorian {
214*ae8c6e27Sflorian 	int sign = 0;
215*ae8c6e27Sflorian 	uint32_t i = 0;
216*ae8c6e27Sflorian 	uint32_t seconds = 0;
217*ae8c6e27Sflorian 
218*ae8c6e27Sflorian 	for(*endptr = nptr; **endptr; (*endptr)++) {
219*ae8c6e27Sflorian 		switch (**endptr) {
220*ae8c6e27Sflorian 			case ' ':
221*ae8c6e27Sflorian 			case '\t':
222*ae8c6e27Sflorian 				break;
223*ae8c6e27Sflorian 			case '-':
224*ae8c6e27Sflorian 				if(sign == 0) {
225*ae8c6e27Sflorian 					sign = -1;
226*ae8c6e27Sflorian 				} else {
227*ae8c6e27Sflorian 					return seconds;
228*ae8c6e27Sflorian 				}
229*ae8c6e27Sflorian 				break;
230*ae8c6e27Sflorian 			case '+':
231*ae8c6e27Sflorian 				if(sign == 0) {
232*ae8c6e27Sflorian 					sign = 1;
233*ae8c6e27Sflorian 				} else {
234*ae8c6e27Sflorian 					return seconds;
235*ae8c6e27Sflorian 				}
236*ae8c6e27Sflorian 				break;
237*ae8c6e27Sflorian 			case 's':
238*ae8c6e27Sflorian 			case 'S':
239*ae8c6e27Sflorian 				seconds += i;
240*ae8c6e27Sflorian 				i = 0;
241*ae8c6e27Sflorian 				break;
242*ae8c6e27Sflorian 			case 'm':
243*ae8c6e27Sflorian 			case 'M':
244*ae8c6e27Sflorian 				seconds += i * 60;
245*ae8c6e27Sflorian 				i = 0;
246*ae8c6e27Sflorian 				break;
247*ae8c6e27Sflorian 			case 'h':
248*ae8c6e27Sflorian 			case 'H':
249*ae8c6e27Sflorian 				seconds += i * 60 * 60;
250*ae8c6e27Sflorian 				i = 0;
251*ae8c6e27Sflorian 				break;
252*ae8c6e27Sflorian 			case 'd':
253*ae8c6e27Sflorian 			case 'D':
254*ae8c6e27Sflorian 				seconds += i * 60 * 60 * 24;
255*ae8c6e27Sflorian 				i = 0;
256*ae8c6e27Sflorian 				break;
257*ae8c6e27Sflorian 			case 'w':
258*ae8c6e27Sflorian 			case 'W':
259*ae8c6e27Sflorian 				seconds += i * 60 * 60 * 24 * 7;
260*ae8c6e27Sflorian 				i = 0;
261*ae8c6e27Sflorian 				break;
262*ae8c6e27Sflorian 			case '0':
263*ae8c6e27Sflorian 			case '1':
264*ae8c6e27Sflorian 			case '2':
265*ae8c6e27Sflorian 			case '3':
266*ae8c6e27Sflorian 			case '4':
267*ae8c6e27Sflorian 			case '5':
268*ae8c6e27Sflorian 			case '6':
269*ae8c6e27Sflorian 			case '7':
270*ae8c6e27Sflorian 			case '8':
271*ae8c6e27Sflorian 			case '9':
272*ae8c6e27Sflorian 				i *= 10;
273*ae8c6e27Sflorian 				i += (**endptr - '0');
274*ae8c6e27Sflorian 				break;
275*ae8c6e27Sflorian 			default:
276*ae8c6e27Sflorian 				seconds += i;
277*ae8c6e27Sflorian 				/* disregard signedness */
278*ae8c6e27Sflorian 				return seconds;
279*ae8c6e27Sflorian 		}
280*ae8c6e27Sflorian 	}
281*ae8c6e27Sflorian 	seconds += i;
282*ae8c6e27Sflorian 	/* disregard signedness */
283*ae8c6e27Sflorian 	return seconds;
284*ae8c6e27Sflorian }
285*ae8c6e27Sflorian 
286*ae8c6e27Sflorian int
287*ae8c6e27Sflorian sldns_parse_escape(uint8_t *ch_p, const char** str_p)
288*ae8c6e27Sflorian {
289*ae8c6e27Sflorian 	uint16_t val;
290*ae8c6e27Sflorian 
291*ae8c6e27Sflorian 	if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) &&
292*ae8c6e27Sflorian 	    (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) &&
293*ae8c6e27Sflorian 	    (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) {
294*ae8c6e27Sflorian 
295*ae8c6e27Sflorian 		val = (uint16_t)(((*str_p)[0] - '0') * 100 +
296*ae8c6e27Sflorian 				 ((*str_p)[1] - '0') *  10 +
297*ae8c6e27Sflorian 				 ((*str_p)[2] - '0'));
298*ae8c6e27Sflorian 
299*ae8c6e27Sflorian 		if (val > 255) {
300*ae8c6e27Sflorian 			goto error;
301*ae8c6e27Sflorian 		}
302*ae8c6e27Sflorian 		*ch_p = (uint8_t)val;
303*ae8c6e27Sflorian 		*str_p += 3;
304*ae8c6e27Sflorian 		return 1;
305*ae8c6e27Sflorian 
306*ae8c6e27Sflorian 	} else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) {
307*ae8c6e27Sflorian 
308*ae8c6e27Sflorian 		*ch_p = (uint8_t)*(*str_p)++;
309*ae8c6e27Sflorian 		return 1;
310*ae8c6e27Sflorian 	}
311*ae8c6e27Sflorian error:
312*ae8c6e27Sflorian 	*str_p = NULL;
313*ae8c6e27Sflorian 	return 0; /* LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE */
314*ae8c6e27Sflorian }
315*ae8c6e27Sflorian 
316*ae8c6e27Sflorian /** parse one character, with escape codes */
317*ae8c6e27Sflorian int
318*ae8c6e27Sflorian sldns_parse_char(uint8_t *ch_p, const char** str_p)
319*ae8c6e27Sflorian {
320*ae8c6e27Sflorian 	switch (**str_p) {
321*ae8c6e27Sflorian 
322*ae8c6e27Sflorian 	case '\0':	return 0;
323*ae8c6e27Sflorian 
324*ae8c6e27Sflorian 	case '\\':	*str_p += 1;
325*ae8c6e27Sflorian 			return sldns_parse_escape(ch_p, str_p);
326*ae8c6e27Sflorian 
327*ae8c6e27Sflorian 	default:	*ch_p = (uint8_t)*(*str_p)++;
328*ae8c6e27Sflorian 			return 1;
329*ae8c6e27Sflorian 	}
330*ae8c6e27Sflorian }
331*ae8c6e27Sflorian 
332*ae8c6e27Sflorian size_t sldns_b32_ntop_calculate_size(size_t src_data_length)
333*ae8c6e27Sflorian {
334*ae8c6e27Sflorian 	return src_data_length == 0 ? 0 : ((src_data_length - 1) / 5 + 1) * 8;
335*ae8c6e27Sflorian }
336*ae8c6e27Sflorian 
337*ae8c6e27Sflorian size_t sldns_b32_ntop_calculate_size_no_padding(size_t src_data_length)
338*ae8c6e27Sflorian {
339*ae8c6e27Sflorian 	return ((src_data_length + 3) * 8 / 5) - 4;
340*ae8c6e27Sflorian }
341*ae8c6e27Sflorian 
342*ae8c6e27Sflorian static int
343*ae8c6e27Sflorian sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
344*ae8c6e27Sflorian 	int extended_hex, int add_padding)
345*ae8c6e27Sflorian {
346*ae8c6e27Sflorian 	size_t ret_sz;
347*ae8c6e27Sflorian 	const char* b32 = extended_hex ?  "0123456789abcdefghijklmnopqrstuv"
348*ae8c6e27Sflorian 					: "abcdefghijklmnopqrstuvwxyz234567";
349*ae8c6e27Sflorian 
350*ae8c6e27Sflorian 	size_t c = 0; /* c is used to carry partial base32 character over
351*ae8c6e27Sflorian 		       * byte boundaries for sizes with a remainder.
352*ae8c6e27Sflorian 		       * (i.e. src_sz % 5 != 0)
353*ae8c6e27Sflorian 		       */
354*ae8c6e27Sflorian 
355*ae8c6e27Sflorian 	ret_sz = add_padding ? sldns_b32_ntop_calculate_size(src_sz)
356*ae8c6e27Sflorian 			     : sldns_b32_ntop_calculate_size_no_padding(src_sz);
357*ae8c6e27Sflorian 
358*ae8c6e27Sflorian 	/* Do we have enough space? */
359*ae8c6e27Sflorian 	if (dst_sz < ret_sz + 1)
360*ae8c6e27Sflorian 		return -1;
361*ae8c6e27Sflorian 
362*ae8c6e27Sflorian 	/* We know the size; terminate the string */
363*ae8c6e27Sflorian 	dst[ret_sz] = '\0';
364*ae8c6e27Sflorian 
365*ae8c6e27Sflorian 	/* First process all chunks of five */
366*ae8c6e27Sflorian 	while (src_sz >= 5) {
367*ae8c6e27Sflorian 		/* 00000... ........ ........ ........ ........ */
368*ae8c6e27Sflorian 		dst[0] = b32[(src[0]       ) >> 3];
369*ae8c6e27Sflorian 
370*ae8c6e27Sflorian 		/* .....111 11...... ........ ........ ........ */
371*ae8c6e27Sflorian 		dst[1] = b32[(src[0] & 0x07) << 2 | src[1] >> 6];
372*ae8c6e27Sflorian 
373*ae8c6e27Sflorian 		/* ........ ..22222. ........ ........ ........ */
374*ae8c6e27Sflorian 		dst[2] = b32[(src[1] & 0x3e) >> 1];
375*ae8c6e27Sflorian 
376*ae8c6e27Sflorian 		/* ........ .......3 3333.... ........ ........ */
377*ae8c6e27Sflorian 		dst[3] = b32[(src[1] & 0x01) << 4 | src[2] >> 4];
378*ae8c6e27Sflorian 
379*ae8c6e27Sflorian 		/* ........ ........ ....4444 4....... ........ */
380*ae8c6e27Sflorian 		dst[4] = b32[(src[2] & 0x0f) << 1 | src[3] >> 7];
381*ae8c6e27Sflorian 
382*ae8c6e27Sflorian 		/* ........ ........ ........ .55555.. ........ */
383*ae8c6e27Sflorian 		dst[5] = b32[(src[3] & 0x7c) >> 2];
384*ae8c6e27Sflorian 
385*ae8c6e27Sflorian 		/* ........ ........ ........ ......66 666..... */
386*ae8c6e27Sflorian 		dst[6] = b32[(src[3] & 0x03) << 3 | src[4] >> 5];
387*ae8c6e27Sflorian 
388*ae8c6e27Sflorian 		/* ........ ........ ........ ........ ...77777 */
389*ae8c6e27Sflorian 		dst[7] = b32[(src[4] & 0x1f)     ];
390*ae8c6e27Sflorian 
391*ae8c6e27Sflorian 		src_sz -= 5;
392*ae8c6e27Sflorian 		src    += 5;
393*ae8c6e27Sflorian 		dst    += 8;
394*ae8c6e27Sflorian 	}
395*ae8c6e27Sflorian 	/* Process what remains */
396*ae8c6e27Sflorian 	switch (src_sz) {
397*ae8c6e27Sflorian 	case 4: /* ........ ........ ........ ......66 666..... */
398*ae8c6e27Sflorian 		dst[6] = b32[(src[3] & 0x03) << 3];
399*ae8c6e27Sflorian 
400*ae8c6e27Sflorian 		/* ........ ........ ........ .55555.. ........ */
401*ae8c6e27Sflorian 		dst[5] = b32[(src[3] & 0x7c) >> 2];
402*ae8c6e27Sflorian 
403*ae8c6e27Sflorian 		/* ........ ........ ....4444 4....... ........ */
404*ae8c6e27Sflorian 			 c =  src[3]         >> 7 ;
405*ae8c6e27Sflorian 		/* fallthrough */
406*ae8c6e27Sflorian 	case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
407*ae8c6e27Sflorian 
408*ae8c6e27Sflorian 		/* ........ .......3 3333.... ........ ........ */
409*ae8c6e27Sflorian 			 c =  src[2]         >> 4 ;
410*ae8c6e27Sflorian 		/* fallthrough */
411*ae8c6e27Sflorian 	case 2:	dst[3] = b32[(src[1] & 0x01) << 4 | c];
412*ae8c6e27Sflorian 
413*ae8c6e27Sflorian 		/* ........ ..22222. ........ ........ ........ */
414*ae8c6e27Sflorian 		dst[2] = b32[(src[1] & 0x3e) >> 1];
415*ae8c6e27Sflorian 
416*ae8c6e27Sflorian 		/* .....111 11...... ........ ........ ........ */
417*ae8c6e27Sflorian 			 c =  src[1]         >> 6 ;
418*ae8c6e27Sflorian 		/* fallthrough */
419*ae8c6e27Sflorian 	case 1:	dst[1] = b32[(src[0] & 0x07) << 2 | c];
420*ae8c6e27Sflorian 
421*ae8c6e27Sflorian 		/* 00000... ........ ........ ........ ........ */
422*ae8c6e27Sflorian 		dst[0] = b32[ src[0]         >> 3];
423*ae8c6e27Sflorian 	}
424*ae8c6e27Sflorian 	/* Add padding */
425*ae8c6e27Sflorian 	if (add_padding) {
426*ae8c6e27Sflorian 		switch (src_sz) {
427*ae8c6e27Sflorian 			case 1: dst[2] = '=';
428*ae8c6e27Sflorian 				dst[3] = '=';
429*ae8c6e27Sflorian 				/* fallthrough */
430*ae8c6e27Sflorian 			case 2: dst[4] = '=';
431*ae8c6e27Sflorian 				/* fallthrough */
432*ae8c6e27Sflorian 			case 3: dst[5] = '=';
433*ae8c6e27Sflorian 				dst[6] = '=';
434*ae8c6e27Sflorian 				/* fallthrough */
435*ae8c6e27Sflorian 			case 4: dst[7] = '=';
436*ae8c6e27Sflorian 		}
437*ae8c6e27Sflorian 	}
438*ae8c6e27Sflorian 	return (int)ret_sz;
439*ae8c6e27Sflorian }
440*ae8c6e27Sflorian 
441*ae8c6e27Sflorian int
442*ae8c6e27Sflorian sldns_b32_ntop(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz)
443*ae8c6e27Sflorian {
444*ae8c6e27Sflorian 	return sldns_b32_ntop_base(src, src_sz, dst, dst_sz, 0, 1);
445*ae8c6e27Sflorian }
446*ae8c6e27Sflorian 
447*ae8c6e27Sflorian int
448*ae8c6e27Sflorian sldns_b32_ntop_extended_hex(const uint8_t* src, size_t src_sz,
449*ae8c6e27Sflorian 		char* dst, size_t dst_sz)
450*ae8c6e27Sflorian {
451*ae8c6e27Sflorian 	return sldns_b32_ntop_base(src, src_sz, dst, dst_sz, 1, 1);
452*ae8c6e27Sflorian }
453*ae8c6e27Sflorian 
454*ae8c6e27Sflorian size_t sldns_b32_pton_calculate_size(size_t src_text_length)
455*ae8c6e27Sflorian {
456*ae8c6e27Sflorian 	return src_text_length * 5 / 8;
457*ae8c6e27Sflorian }
458*ae8c6e27Sflorian 
459*ae8c6e27Sflorian static int
460*ae8c6e27Sflorian sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz,
461*ae8c6e27Sflorian 	int extended_hex, int check_padding)
462*ae8c6e27Sflorian {
463*ae8c6e27Sflorian 	size_t i = 0;
464*ae8c6e27Sflorian 	char ch = '\0';
465*ae8c6e27Sflorian 	uint8_t buf[8];
466*ae8c6e27Sflorian 	uint8_t* start = dst;
467*ae8c6e27Sflorian 
468*ae8c6e27Sflorian 	while (src_sz) {
469*ae8c6e27Sflorian 		/* Collect 8 characters in buf (if possible) */
470*ae8c6e27Sflorian 		for (i = 0; i < 8; i++) {
471*ae8c6e27Sflorian 
472*ae8c6e27Sflorian 			do {
473*ae8c6e27Sflorian 				ch = *src++;
474*ae8c6e27Sflorian 				--src_sz;
475*ae8c6e27Sflorian 
476*ae8c6e27Sflorian 			} while (isspace((unsigned char)ch) && src_sz > 0);
477*ae8c6e27Sflorian 
478*ae8c6e27Sflorian 			if (ch == '=' || ch == '\0')
479*ae8c6e27Sflorian 				break;
480*ae8c6e27Sflorian 
481*ae8c6e27Sflorian 			else if (extended_hex)
482*ae8c6e27Sflorian 
483*ae8c6e27Sflorian 				if (ch >= '0' && ch <= '9')
484*ae8c6e27Sflorian 					buf[i] = (uint8_t)ch - '0';
485*ae8c6e27Sflorian 				else if (ch >= 'a' && ch <= 'v')
486*ae8c6e27Sflorian 					buf[i] = (uint8_t)ch - 'a' + 10;
487*ae8c6e27Sflorian 				else if (ch >= 'A' && ch <= 'V')
488*ae8c6e27Sflorian 					buf[i] = (uint8_t)ch - 'A' + 10;
489*ae8c6e27Sflorian 				else
490*ae8c6e27Sflorian 					return -1;
491*ae8c6e27Sflorian 
492*ae8c6e27Sflorian 			else if (ch >= 'a' && ch <= 'z')
493*ae8c6e27Sflorian 				buf[i] = (uint8_t)ch - 'a';
494*ae8c6e27Sflorian 			else if (ch >= 'A' && ch <= 'Z')
495*ae8c6e27Sflorian 				buf[i] = (uint8_t)ch - 'A';
496*ae8c6e27Sflorian 			else if (ch >= '2' && ch <= '7')
497*ae8c6e27Sflorian 				buf[i] = (uint8_t)ch - '2' + 26;
498*ae8c6e27Sflorian 			else
499*ae8c6e27Sflorian 				return -1;
500*ae8c6e27Sflorian 		}
501*ae8c6e27Sflorian 		/* Less that 8 characters. We're done. */
502*ae8c6e27Sflorian 		if (i < 8)
503*ae8c6e27Sflorian 			break;
504*ae8c6e27Sflorian 
505*ae8c6e27Sflorian 		/* Enough space available at the destination? */
506*ae8c6e27Sflorian 		if (dst_sz < 5)
507*ae8c6e27Sflorian 			return -1;
508*ae8c6e27Sflorian 
509*ae8c6e27Sflorian 		/* 00000... ........ ........ ........ ........ */
510*ae8c6e27Sflorian 		/* .....111 11...... ........ ........ ........ */
511*ae8c6e27Sflorian 		dst[0] = buf[0] << 3 | buf[1] >> 2;
512*ae8c6e27Sflorian 
513*ae8c6e27Sflorian 		/* .....111 11...... ........ ........ ........ */
514*ae8c6e27Sflorian 		/* ........ ..22222. ........ ........ ........ */
515*ae8c6e27Sflorian 		/* ........ .......3 3333.... ........ ........ */
516*ae8c6e27Sflorian 		dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
517*ae8c6e27Sflorian 
518*ae8c6e27Sflorian 		/* ........ .......3 3333.... ........ ........ */
519*ae8c6e27Sflorian 		/* ........ ........ ....4444 4....... ........ */
520*ae8c6e27Sflorian 		dst[2] = buf[3] << 4 | buf[4] >> 1;
521*ae8c6e27Sflorian 
522*ae8c6e27Sflorian 		/* ........ ........ ....4444 4....... ........ */
523*ae8c6e27Sflorian 		/* ........ ........ ........ .55555.. ........ */
524*ae8c6e27Sflorian 		/* ........ ........ ........ ......66 666..... */
525*ae8c6e27Sflorian 		dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
526*ae8c6e27Sflorian 
527*ae8c6e27Sflorian 		/* ........ ........ ........ ......66 666..... */
528*ae8c6e27Sflorian 		/* ........ ........ ........ ........ ...77777 */
529*ae8c6e27Sflorian 		dst[4] = buf[6] << 5 | buf[7];
530*ae8c6e27Sflorian 
531*ae8c6e27Sflorian 		dst += 5;
532*ae8c6e27Sflorian 		dst_sz -= 5;
533*ae8c6e27Sflorian 	}
534*ae8c6e27Sflorian 	/* Not ending on a eight byte boundary? */
535*ae8c6e27Sflorian 	if (i > 0 && i < 8) {
536*ae8c6e27Sflorian 
537*ae8c6e27Sflorian 		/* Enough space available at the destination? */
538*ae8c6e27Sflorian 		if (dst_sz < (i + 1) / 2)
539*ae8c6e27Sflorian 			return -1;
540*ae8c6e27Sflorian 
541*ae8c6e27Sflorian 		switch (i) {
542*ae8c6e27Sflorian 		case 7: /* ........ ........ ........ ......66 666..... */
543*ae8c6e27Sflorian 			/* ........ ........ ........ .55555.. ........ */
544*ae8c6e27Sflorian 			/* ........ ........ ....4444 4....... ........ */
545*ae8c6e27Sflorian 			dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
546*ae8c6e27Sflorian 			/* fallthrough */
547*ae8c6e27Sflorian 
548*ae8c6e27Sflorian 		case 5: /* ........ ........ ....4444 4....... ........ */
549*ae8c6e27Sflorian 			/* ........ .......3 3333.... ........ ........ */
550*ae8c6e27Sflorian 			dst[2] = buf[3] << 4 | buf[4] >> 1;
551*ae8c6e27Sflorian 			/* fallthrough */
552*ae8c6e27Sflorian 
553*ae8c6e27Sflorian 		case 4: /* ........ .......3 3333.... ........ ........ */
554*ae8c6e27Sflorian 			/* ........ ..22222. ........ ........ ........ */
555*ae8c6e27Sflorian 			/* .....111 11...... ........ ........ ........ */
556*ae8c6e27Sflorian 			dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
557*ae8c6e27Sflorian 			/* fallthrough */
558*ae8c6e27Sflorian 
559*ae8c6e27Sflorian 		case 2: /* .....111 11...... ........ ........ ........ */
560*ae8c6e27Sflorian 			/* 00000... ........ ........ ........ ........ */
561*ae8c6e27Sflorian 			dst[0] = buf[0] << 3 | buf[1] >> 2;
562*ae8c6e27Sflorian 
563*ae8c6e27Sflorian 			break;
564*ae8c6e27Sflorian 
565*ae8c6e27Sflorian 		default:
566*ae8c6e27Sflorian 			return -1;
567*ae8c6e27Sflorian 		}
568*ae8c6e27Sflorian 		dst += (i + 1) / 2;
569*ae8c6e27Sflorian 
570*ae8c6e27Sflorian 		if (check_padding) {
571*ae8c6e27Sflorian 			/* Check remaining padding characters */
572*ae8c6e27Sflorian 			if (ch != '=')
573*ae8c6e27Sflorian 				return -1;
574*ae8c6e27Sflorian 
575*ae8c6e27Sflorian 			/* One down, 8 - i - 1 more to come... */
576*ae8c6e27Sflorian 			for (i = 8 - i - 1; i > 0; i--) {
577*ae8c6e27Sflorian 
578*ae8c6e27Sflorian 				do {
579*ae8c6e27Sflorian 					if (src_sz == 0)
580*ae8c6e27Sflorian 						return -1;
581*ae8c6e27Sflorian 					ch = *src++;
582*ae8c6e27Sflorian 					src_sz--;
583*ae8c6e27Sflorian 
584*ae8c6e27Sflorian 				} while (isspace((unsigned char)ch));
585*ae8c6e27Sflorian 
586*ae8c6e27Sflorian 				if (ch != '=')
587*ae8c6e27Sflorian 					return -1;
588*ae8c6e27Sflorian 			}
589*ae8c6e27Sflorian 		}
590*ae8c6e27Sflorian 	}
591*ae8c6e27Sflorian 	return dst - start;
592*ae8c6e27Sflorian }
593*ae8c6e27Sflorian 
594*ae8c6e27Sflorian int
595*ae8c6e27Sflorian sldns_b32_pton(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz)
596*ae8c6e27Sflorian {
597*ae8c6e27Sflorian 	return sldns_b32_pton_base(src, src_sz, dst, dst_sz, 0, 1);
598*ae8c6e27Sflorian }
599*ae8c6e27Sflorian 
600*ae8c6e27Sflorian int
601*ae8c6e27Sflorian sldns_b32_pton_extended_hex(const char* src, size_t src_sz,
602*ae8c6e27Sflorian 		uint8_t* dst, size_t dst_sz)
603*ae8c6e27Sflorian {
604*ae8c6e27Sflorian 	return sldns_b32_pton_base(src, src_sz, dst, dst_sz, 1, 1);
605*ae8c6e27Sflorian }
606*ae8c6e27Sflorian 
607*ae8c6e27Sflorian size_t sldns_b64_ntop_calculate_size(size_t srcsize)
608*ae8c6e27Sflorian {
609*ae8c6e27Sflorian 	return ((((srcsize + 2) / 3) * 4) + 1);
610*ae8c6e27Sflorian }
611*ae8c6e27Sflorian 
612*ae8c6e27Sflorian /* RFC 1521, section 5.2.
613*ae8c6e27Sflorian  *
614*ae8c6e27Sflorian  * The encoding process represents 24-bit groups of input bits as output
615*ae8c6e27Sflorian  * strings of 4 encoded characters. Proceeding from left to right, a
616*ae8c6e27Sflorian  * 24-bit input group is formed by concatenating 3 8-bit input groups.
617*ae8c6e27Sflorian  * These 24 bits are then treated as 4 concatenated 6-bit groups, each
618*ae8c6e27Sflorian  * of which is translated into a single digit in the base64 alphabet.
619*ae8c6e27Sflorian  *
620*ae8c6e27Sflorian  * This routine does not insert spaces or linebreaks after 76 characters.
621*ae8c6e27Sflorian  */
622*ae8c6e27Sflorian int sldns_b64_ntop(uint8_t const *src, size_t srclength,
623*ae8c6e27Sflorian 	char *target, size_t targsize)
624*ae8c6e27Sflorian {
625*ae8c6e27Sflorian 	const char* b64 =
626*ae8c6e27Sflorian 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
627*ae8c6e27Sflorian 	const char pad64 = '=';
628*ae8c6e27Sflorian 	size_t i = 0, o = 0;
629*ae8c6e27Sflorian 	if(targsize < sldns_b64_ntop_calculate_size(srclength))
630*ae8c6e27Sflorian 		return -1;
631*ae8c6e27Sflorian 	/* whole chunks: xxxxxxyy yyyyzzzz zzwwwwww */
632*ae8c6e27Sflorian 	while(i+3 <= srclength) {
633*ae8c6e27Sflorian 		if(o+4 > targsize) return -1;
634*ae8c6e27Sflorian 		target[o] = b64[src[i] >> 2];
635*ae8c6e27Sflorian 		target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ];
636*ae8c6e27Sflorian 		target[o+2] = b64[ ((src[i+1]&0x0f)<<2) | (src[i+2]>>6) ];
637*ae8c6e27Sflorian 		target[o+3] = b64[ (src[i+2]&0x3f) ];
638*ae8c6e27Sflorian 		i += 3;
639*ae8c6e27Sflorian 		o += 4;
640*ae8c6e27Sflorian 	}
641*ae8c6e27Sflorian 	/* remainder */
642*ae8c6e27Sflorian 	switch(srclength - i) {
643*ae8c6e27Sflorian 	case 2:
644*ae8c6e27Sflorian 		/* two at end, converted into A B C = */
645*ae8c6e27Sflorian 		target[o] = b64[src[i] >> 2];
646*ae8c6e27Sflorian 		target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ];
647*ae8c6e27Sflorian 		target[o+2] = b64[ ((src[i+1]&0x0f)<<2) ];
648*ae8c6e27Sflorian 		target[o+3] = pad64;
649*ae8c6e27Sflorian 		/* i += 2; */
650*ae8c6e27Sflorian 		o += 4;
651*ae8c6e27Sflorian 		break;
652*ae8c6e27Sflorian 	case 1:
653*ae8c6e27Sflorian 		/* one at end, converted into A B = = */
654*ae8c6e27Sflorian 		target[o] = b64[src[i] >> 2];
655*ae8c6e27Sflorian 		target[o+1] = b64[ ((src[i]&0x03)<<4) ];
656*ae8c6e27Sflorian 		target[o+2] = pad64;
657*ae8c6e27Sflorian 		target[o+3] = pad64;
658*ae8c6e27Sflorian 		/* i += 1; */
659*ae8c6e27Sflorian 		o += 4;
660*ae8c6e27Sflorian 		break;
661*ae8c6e27Sflorian 	case 0:
662*ae8c6e27Sflorian 	default:
663*ae8c6e27Sflorian 		/* nothing */
664*ae8c6e27Sflorian 		break;
665*ae8c6e27Sflorian 	}
666*ae8c6e27Sflorian 	/* assert: i == srclength */
667*ae8c6e27Sflorian 	if(o+1 > targsize) return -1;
668*ae8c6e27Sflorian 	target[o] = 0;
669*ae8c6e27Sflorian 	return (int)o;
670*ae8c6e27Sflorian }
671*ae8c6e27Sflorian 
672*ae8c6e27Sflorian size_t sldns_b64_pton_calculate_size(size_t srcsize)
673*ae8c6e27Sflorian {
674*ae8c6e27Sflorian 	return (((((srcsize + 3) / 4) * 3)) + 1);
675*ae8c6e27Sflorian }
676*ae8c6e27Sflorian 
677*ae8c6e27Sflorian int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
678*ae8c6e27Sflorian {
679*ae8c6e27Sflorian 	const uint8_t pad64 = 64; /* is 64th in the b64 array */
680*ae8c6e27Sflorian 	const char* s = src;
681*ae8c6e27Sflorian 	uint8_t in[4];
682*ae8c6e27Sflorian 	size_t o = 0, incount = 0;
683*ae8c6e27Sflorian 
684*ae8c6e27Sflorian 	while(*s) {
685*ae8c6e27Sflorian 		/* skip any character that is not base64 */
686*ae8c6e27Sflorian 		/* conceptually we do:
687*ae8c6e27Sflorian 		const char* b64 =      pad'=' is appended to array
688*ae8c6e27Sflorian 		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
689*ae8c6e27Sflorian 		const char* d = strchr(b64, *s++);
690*ae8c6e27Sflorian 		and use d-b64;
691*ae8c6e27Sflorian 		*/
692*ae8c6e27Sflorian 		char d = *s++;
693*ae8c6e27Sflorian 		if(d <= 'Z' && d >= 'A')
694*ae8c6e27Sflorian 			d -= 'A';
695*ae8c6e27Sflorian 		else if(d <= 'z' && d >= 'a')
696*ae8c6e27Sflorian 			d = d - 'a' + 26;
697*ae8c6e27Sflorian 		else if(d <= '9' && d >= '0')
698*ae8c6e27Sflorian 			d = d - '0' + 52;
699*ae8c6e27Sflorian 		else if(d == '+')
700*ae8c6e27Sflorian 			d = 62;
701*ae8c6e27Sflorian 		else if(d == '/')
702*ae8c6e27Sflorian 			d = 63;
703*ae8c6e27Sflorian 		else if(d == '=')
704*ae8c6e27Sflorian 			d = 64;
705*ae8c6e27Sflorian 		else	continue;
706*ae8c6e27Sflorian 		in[incount++] = (uint8_t)d;
707*ae8c6e27Sflorian 		if(incount != 4)
708*ae8c6e27Sflorian 			continue;
709*ae8c6e27Sflorian 		/* process whole block of 4 characters into 3 output bytes */
710*ae8c6e27Sflorian 		if(in[3] == pad64 && in[2] == pad64) { /* A B = = */
711*ae8c6e27Sflorian 			if(o+1 > targsize)
712*ae8c6e27Sflorian 				return -1;
713*ae8c6e27Sflorian 			target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
714*ae8c6e27Sflorian 			o += 1;
715*ae8c6e27Sflorian 			break; /* we are done */
716*ae8c6e27Sflorian 		} else if(in[3] == pad64) { /* A B C = */
717*ae8c6e27Sflorian 			if(o+2 > targsize)
718*ae8c6e27Sflorian 				return -1;
719*ae8c6e27Sflorian 			target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
720*ae8c6e27Sflorian 			target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
721*ae8c6e27Sflorian 			o += 2;
722*ae8c6e27Sflorian 			break; /* we are done */
723*ae8c6e27Sflorian 		} else {
724*ae8c6e27Sflorian 			if(o+3 > targsize)
725*ae8c6e27Sflorian 				return -1;
726*ae8c6e27Sflorian 			/* write xxxxxxyy yyyyzzzz zzwwwwww */
727*ae8c6e27Sflorian 			target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
728*ae8c6e27Sflorian 			target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
729*ae8c6e27Sflorian 			target[o+2]= ((in[2]&0x03)<<6) | in[3];
730*ae8c6e27Sflorian 			o += 3;
731*ae8c6e27Sflorian 		}
732*ae8c6e27Sflorian 		incount = 0;
733*ae8c6e27Sflorian 	}
734*ae8c6e27Sflorian 	return (int)o;
735*ae8c6e27Sflorian }
736