non-standard base64 functions in tinc 1.1

Todd C. Miller Todd.Miller at courtesan.com
Wed Aug 30 22:35:44 CEST 2017


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;
 }
 


More information about the tinc-devel mailing list