[crypto] extend base64 to output crLf when encoding

Some windows APIs do put \r\n every 64 characters of the output of a
base64 encoded blob. The extended version of crypto_base64_encode allows
to do the same.
This commit is contained in:
David Fort 2023-08-16 11:06:17 +02:00 committed by akallabeth
parent ce41d514ab
commit 361da15eed
3 changed files with 52 additions and 3 deletions

View File

@ -39,6 +39,8 @@ extern "C"
typedef struct rdp_CertInfo rdpCertInfo;
FREERDP_API char* crypto_base64_encode(const BYTE* data, size_t length);
FREERDP_API char* crypto_base64_encode_ex(const BYTE* data, size_t length, BOOL withCrLf);
FREERDP_API void crypto_base64_decode(const char* enc_data, size_t length, BYTE** dec_data,
size_t* res_length);

View File

@ -26,7 +26,8 @@
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char base64url[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
static char* base64_encode(const char* alphabet, const BYTE* data, size_t length, BOOL pad)
static char* base64_encode_ex(const char* alphabet, const BYTE* data, size_t length, BOOL pad,
BOOL crLf, size_t lineSize)
{
int c;
const BYTE* q;
@ -34,9 +35,17 @@ static char* base64_encode(const char* alphabet, const BYTE* data, size_t length
char* ret;
int i = 0;
int blocks;
size_t outLen = (length + 3) * 4 / 3;
size_t extra = 0;
if (crLf)
{
size_t nCrLf = (outLen + lineSize - 1) / lineSize;
extra = nCrLf * 2;
}
size_t outCounter = 0;
q = data;
p = ret = (char*)malloc((length + 3) * 4 / 3 + 1);
p = ret = (char*)malloc(outLen + extra + 1);
if (!p)
return NULL;
@ -62,6 +71,13 @@ static char* base64_encode(const char* alphabet, const BYTE* data, size_t length
*p++ = alphabet[(c & 0x0003F000) >> 12];
*p++ = alphabet[(c & 0x00000FC0) >> 6];
*p++ = alphabet[c & 0x0000003F];
outCounter += 4;
if (crLf && (outCounter % lineSize == 0))
{
*p++ = '\r';
*p++ = '\n';
}
}
/* then remainder */
@ -89,11 +105,21 @@ static char* base64_encode(const char* alphabet, const BYTE* data, size_t length
break;
}
if (crLf && length % 3)
{
*p++ = '\r';
*p++ = '\n';
}
*p = 0;
return ret;
}
static char* base64_encode(const char* alphabet, const BYTE* data, size_t length, BOOL pad)
{
return base64_encode_ex(alphabet, data, length, pad, FALSE, 64);
}
static int base64_decode_char(const char* alphabet, char c)
{
char* p = NULL;
@ -197,6 +223,11 @@ out_free:
return NULL;
}
char* crypto_base64_encode_ex(const BYTE* data, size_t length, BOOL withCrLf)
{
return base64_encode_ex(base64, data, length, TRUE, withCrLf, 64);
}
char* crypto_base64_encode(const BYTE* data, size_t length)
{
return base64_encode(base64, data, length, TRUE);

View File

@ -156,7 +156,23 @@ int TestBase64(int argc, char* argv[])
fprintf(stderr, "ko, = in a wrong place\n");
return -1;
}
fprintf(stderr, "ok\n");
testNb++;
/* test the encode_ex version that will add \r\n */
fprintf(stderr, "%d:encode base64 with crLf...", testNb);
const char* longStr = "01234567890123456789012345678901234567890123456789";
const char* longStrExpected =
"MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3\r\nODk=\r\n";
char* encoded = crypto_base64_encode_ex((const BYTE*)longStr, strlen(longStr), TRUE);
if (!encoded || strcmp(encoded, longStrExpected) != 0)
{
fprintf(stderr, "problem with encode with CRLF\n");
return -1;
}
free(encoded);
fprintf(stderr, "ok\n");
return 0;
}