20 #include <freerdp/config.h>
22 #include <winpr/crt.h>
24 #include <freerdp/crypto/crypto.h>
26 static const BYTE enc_base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27 static const BYTE enc_base64url[] =
28 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
30 static const signed char dec_base64url[] = {
167 static const signed char dec_base64[] = {
305 static INLINE
char* base64_encode_ex(
const BYTE* WINPR_RESTRICT alphabet,
306 const BYTE* WINPR_RESTRICT data,
size_t length, BOOL pad,
307 BOOL crLf,
size_t lineSize)
311 size_t outLen = (length + 3) * 4 / 3;
315 size_t nCrLf = (outLen + lineSize - 1) / lineSize;
318 size_t outCounter = 0;
320 const BYTE* q = data;
321 BYTE* p = malloc(outLen + extra + 1ull);
325 char* ret = (
char*)p;
340 blocks = length - (length % 3);
341 for (
size_t i = 0; i < blocks; i += 3, q += 3)
343 c = (q[0] << 16) + (q[1] << 8) + q[2];
345 *p++ = alphabet[(c & 0x00FC0000) >> 18];
346 *p++ = alphabet[(c & 0x0003F000) >> 12];
347 *p++ = alphabet[(c & 0x00000FC0) >> 6];
348 *p++ = alphabet[c & 0x0000003F];
351 if (crLf && (outCounter % lineSize == 0))
365 *p++ = alphabet[(c & 0x00FC0000) >> 18];
366 *p++ = alphabet[(c & 0x0003F000) >> 12];
374 c = (q[0] << 16) + (q[1] << 8);
375 *p++ = alphabet[(c & 0x00FC0000) >> 18];
376 *p++ = alphabet[(c & 0x0003F000) >> 12];
377 *p++ = alphabet[(c & 0x00000FC0) >> 6];
385 if (crLf && length % 3)
395 static INLINE
char* base64_encode(
const BYTE* WINPR_RESTRICT alphabet,
396 const BYTE* WINPR_RESTRICT data,
size_t length, BOOL pad)
398 return base64_encode_ex(alphabet, data, length, pad, FALSE, 64);
401 static INLINE
int base64_decode_char(
const signed char* WINPR_RESTRICT alphabet,
char c)
406 return alphabet[(size_t)c];
409 static INLINE
void* base64_decode(
const signed char* WINPR_RESTRICT alphabet,
410 const char* WINPR_RESTRICT s,
size_t length,
411 size_t* WINPR_RESTRICT data_len, BOOL pad)
415 const size_t remainder = length % 4;
417 if ((pad && remainder > 0) || (remainder == 1))
420 if (!pad && remainder)
421 length += 4 - remainder;
423 BYTE* q = data = (BYTE*)malloc(length / 4 * 3 + 1);
428 const size_t nBlocks = (length / 4);
429 size_t outputLen = 0;
437 for (
size_t i = 0; i < nBlocks - 1; i++, q += 3)
439 n[0] = base64_decode_char(alphabet, *s++);
440 n[1] = base64_decode_char(alphabet, *s++);
441 n[2] = base64_decode_char(alphabet, *s++);
442 n[3] = base64_decode_char(alphabet, *s++);
444 if ((n[0] == -1) || (n[1] == -1) || (n[2] == -1) || (n[3] == -1))
447 q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
448 q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
449 q[2] = (BYTE)(((n[2] & 3) << 6) + n[3]);
454 n[0] = base64_decode_char(alphabet, *s++);
455 n[1] = base64_decode_char(alphabet, *s++);
456 if ((n[0] == -1) || (n[1] == -1))
459 n[2] = remainder == 2 ? -1 : base64_decode_char(alphabet, *s++);
460 n[3] = remainder >= 2 ? -1 : base64_decode_char(alphabet, *s++);
462 q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
470 q[1] = (BYTE)((n[1] & 15) << 4);
476 q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
477 q[2] = (BYTE)((n[2] & 3) << 6);
483 q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
484 q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
485 q[2] = (BYTE)(((n[2] & 3) << 6) + n[3]);
489 *data_len = outputLen;
490 data[outputLen] =
'\0';
498 char* crypto_base64_encode_ex(
const BYTE* WINPR_RESTRICT data,
size_t length, BOOL withCrLf)
500 return base64_encode_ex(enc_base64, data, length, TRUE, withCrLf, 64);
503 char* crypto_base64_encode(
const BYTE* WINPR_RESTRICT data,
size_t length)
505 return base64_encode(enc_base64, data, length, TRUE);
508 void crypto_base64_decode(
const char* WINPR_RESTRICT enc_data,
size_t length,
509 BYTE** WINPR_RESTRICT dec_data,
size_t* WINPR_RESTRICT res_length)
511 *dec_data = base64_decode(dec_base64, enc_data, length, res_length, TRUE);
514 char* crypto_base64url_encode(
const BYTE* WINPR_RESTRICT data,
size_t length)
516 return base64_encode(enc_base64url, data, length, FALSE);
519 void crypto_base64url_decode(
const char* WINPR_RESTRICT enc_data,
size_t length,
520 BYTE** WINPR_RESTRICT dec_data,
size_t* WINPR_RESTRICT res_length)
522 *dec_data = base64_decode(dec_base64url, enc_data, length, res_length, FALSE);