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