diff options
Diffstat (limited to 'contrib/unbound/sldns/parseutil.c')
-rw-r--r-- | contrib/unbound/sldns/parseutil.c | 99 |
1 files changed, 78 insertions, 21 deletions
diff --git a/contrib/unbound/sldns/parseutil.c b/contrib/unbound/sldns/parseutil.c index 3515d64c5d10..9f289d3596c3 100644 --- a/contrib/unbound/sldns/parseutil.c +++ b/contrib/unbound/sldns/parseutil.c @@ -619,13 +619,18 @@ size_t sldns_b64_ntop_calculate_size(size_t srcsize) * * This routine does not insert spaces or linebreaks after 76 characters. */ -int sldns_b64_ntop(uint8_t const *src, size_t srclength, - char *target, size_t targsize) +static int sldns_b64_ntop_base(uint8_t const *src, size_t srclength, + char *target, size_t targsize, int base64url, int padding) { - const char* b64 = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + char* b64; const char pad64 = '='; size_t i = 0, o = 0; + if(base64url) + b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123" + "456789-_"; + else + b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123" + "456789+/"; if(targsize < sldns_b64_ntop_calculate_size(srclength)) return -1; /* whole chunks: xxxxxxyy yyyyzzzz zzwwwwww */ @@ -645,18 +650,26 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength, target[o] = b64[src[i] >> 2]; target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ]; target[o+2] = b64[ ((src[i+1]&0x0f)<<2) ]; - target[o+3] = pad64; - /* i += 2; */ - o += 4; + if(padding) { + target[o+3] = pad64; + /* i += 2; */ + o += 4; + } else { + o += 3; + } break; case 1: /* one at end, converted into A B = = */ target[o] = b64[src[i] >> 2]; target[o+1] = b64[ ((src[i]&0x03)<<4) ]; - target[o+2] = pad64; - target[o+3] = pad64; - /* i += 1; */ - o += 4; + if(padding) { + target[o+2] = pad64; + target[o+3] = pad64; + /* i += 1; */ + o += 4; + } else { + o += 2; + } break; case 0: default: @@ -669,19 +682,36 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength, return (int)o; } +int sldns_b64_ntop(uint8_t const *src, size_t srclength, char *target, + size_t targsize) +{ + return sldns_b64_ntop_base(src, srclength, target, targsize, + 0 /* no base64url */, 1 /* padding */); +} + +int sldns_b64url_ntop(uint8_t const *src, size_t srclength, char *target, + size_t targsize) +{ + return sldns_b64_ntop_base(src, srclength, target, targsize, + 1 /* base64url */, 0 /* no padding */); +} + size_t sldns_b64_pton_calculate_size(size_t srcsize) { return (((((srcsize + 3) / 4) * 3)) + 1); } -int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize) +/* padding not required if srcsize is set */ +static int sldns_b64_pton_base(char const *src, size_t srcsize, uint8_t *target, + size_t targsize, int base64url) { const uint8_t pad64 = 64; /* is 64th in the b64 array */ const char* s = src; uint8_t in[4]; size_t o = 0, incount = 0; + int check_padding = (srcsize) ? 0 : 1; - while(*s) { + while(*s && (check_padding || srcsize)) { /* skip any character that is not base64 */ /* conceptually we do: const char* b64 = pad'=' is appended to array @@ -690,30 +720,43 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize) and use d-b64; */ char d = *s++; + srcsize--; if(d <= 'Z' && d >= 'A') d -= 'A'; else if(d <= 'z' && d >= 'a') d = d - 'a' + 26; else if(d <= '9' && d >= '0') d = d - '0' + 52; - else if(d == '+') + else if(!base64url && d == '+') d = 62; - else if(d == '/') + else if(base64url && d == '-') + d = 62; + else if(!base64url && d == '/') + d = 63; + else if(base64url && d == '_') d = 63; - else if(d == '=') + else if(d == '=') { + if(!check_padding) + continue; d = 64; - else continue; + } else continue; + in[incount++] = (uint8_t)d; - if(incount != 4) + /* work on block of 4, unless padding is not used and there are + * less than 4 chars left */ + if(incount != 4 && (check_padding || srcsize)) continue; + assert(!check_padding || incount==4); /* process whole block of 4 characters into 3 output bytes */ - if(in[3] == pad64 && in[2] == pad64) { /* A B = = */ + if((incount == 2 || + (incount == 4 && in[3] == pad64 && in[2] == pad64))) { /* A B = = */ if(o+1 > targsize) return -1; target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); o += 1; break; /* we are done */ - } else if(in[3] == pad64) { /* A B C = */ + } else if(incount == 3 || + (incount == 4 && in[3] == pad64)) { /* A B C = */ if(o+2 > targsize) return -1; target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); @@ -721,7 +764,7 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize) o += 2; break; /* we are done */ } else { - if(o+3 > targsize) + if(incount != 4 || o+3 > targsize) return -1; /* write xxxxxxyy yyyyzzzz zzwwwwww */ target[o] = (in[0]<<2) | ((in[1]&0x30)>>4); @@ -733,3 +776,17 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize) } return (int)o; } + +int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize) +{ + return sldns_b64_pton_base(src, 0, target, targsize, 0); +} + +int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target, + size_t targsize) +{ + if(!srcsize) { + return 0; + } + return sldns_b64_pton_base(src, srcsize, target, targsize, 1); +} |