I noticed that the base64 functions in util.c don't produce the
same results as other versions that implement RFC 1421 (and its
successors). This results in PEM files that can only be decoded
by tinc itself.
Is this intentional?
Below is a diff to make tinc's base64 functions match what everyone
else does. This will break existing key files, though, which is
unfortunate.
- todd
diff --git a/src/utils.c b/src/utils.c
index fadfd05..43d4840 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -75,14 +75,14 @@ int b64decode(const char *src, void *dst, int length) {
uint32_t triplet = 0;
unsigned char *udst = (unsigned char *)dst;
- for(i = 0; i < length && src[i]; i++) {
- triplet |= base64_decode[src[i] & 0xff] << (6 * (i & 3));
+ for(i = 0; i < length && src[i] && src[i] != '=';
i++) {
+ triplet = (triplet << 6) | base64_decode[src[i] & 0xff];
if((i & 3) == 3) {
if(triplet & 0xff000000U)
return 0;
- udst[0] = triplet & 0xff; triplet >>= 8;
+ udst[2] = triplet & 0xff; triplet >>= 8;
udst[1] = triplet & 0xff; triplet >>= 8;
- udst[2] = triplet;
+ udst[0] = triplet;
triplet = 0;
udst += 3;
}
@@ -90,10 +90,12 @@ int b64decode(const char *src, void *dst, int length) {
if(triplet & 0xff000000U)
return 0;
if((i & 3) == 3) {
- udst[0] = triplet & 0xff; triplet >>= 8;
- udst[1] = triplet & 0xff;
+ triplet >>= 2;
+ udst[1] = triplet & 0xff; triplet >>= 8;
+ udst[0] = triplet & 0xff;
return i / 4 * 3 + 2;
} else if((i & 3) == 2) {
+ triplet >>= 4;
udst[0] = triplet & 0xff;
return i / 4 * 3 + 1;
} else {
@@ -109,22 +111,19 @@ static int b64encode_internal(const void *src, char *dst,
int length, const char
switch(length % 3) {
case 2:
- triplet = usrc[si] | usrc[si + 1] << 8;
- dst[di] = alphabet[triplet & 63]; triplet >>= 6;
+ triplet = usrc[si + 1] << 2 | usrc[si] << 10;
+ dst[di + 2] = alphabet[triplet & 63]; triplet >>= 6;
dst[di + 1] = alphabet[triplet & 63]; triplet >>= 6;
- dst[di + 2] = alphabet[triplet];
- dst[di + 3] = 0;
+ dst[di] = alphabet[triplet];
length = di + 3;
break;
case 1:
- triplet = usrc[si];
- dst[di] = alphabet[triplet & 63]; triplet >>= 6;
- dst[di + 1] = alphabet[triplet];
- dst[di + 2] = 0;
+ triplet = usrc[si] << 4;
+ dst[di + 1] = alphabet[triplet & 63]; triplet >>= 6;
+ dst[di] = alphabet[triplet];
length = di + 2;
break;
default:
- dst[di] = 0;
length = di;
break;
}
@@ -139,6 +138,8 @@ static int b64encode_internal(const void *src, char *dst,
int length, const char
dst[di + 3] = alphabet[triplet];
}
+ dst[length] = '\0';
+
return length;
}