summaryrefslogtreecommitdiff
path: root/contrib/unbound/sldns/parseutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/sldns/parseutil.c')
-rw-r--r--contrib/unbound/sldns/parseutil.c99
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);
+}