20#include <freerdp/config.h>
24#include <freerdp/crypto/crypto.h>
26static const BYTE enc_base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27static const BYTE enc_base64url[] =
28 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
30static const signed char dec_base64url[] = {
167static const signed char dec_base64[] = {
305static inline char* base64_encode_ex(
const BYTE* WINPR_RESTRICT alphabet,
306 WINPR_ATTR_UNUSED
size_t alphabetCount,
307 const BYTE* WINPR_RESTRICT data,
size_t length, BOOL pad,
308 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 const unsigned c = ((unsigned)q[0] << 16) + ((unsigned)q[1] << 8) + q[2];
344 const unsigned idx0 = (c & 0x00FC0000) >> 18;
345 const unsigned idx1 = (c & 0x0003F000) >> 12;
346 const unsigned idx2 = (c & 0x00000FC0) >> 6;
347 const unsigned idx3 = c & 0x0000003F;
349 WINPR_ASSERT(idx0 < alphabetCount);
350 WINPR_ASSERT(idx1 < alphabetCount);
351 WINPR_ASSERT(idx2 < alphabetCount);
352 WINPR_ASSERT(idx3 < alphabetCount);
354 *p++ = alphabet[idx0];
355 *p++ = alphabet[idx1];
356 *p++ = alphabet[idx2];
357 *p++ = alphabet[idx3];
360 if (crLf && (outCounter % lineSize == 0))
374 const unsigned c = ((unsigned)q[0] << 16);
375 const unsigned idx0 = (c & 0x00FC0000) >> 18;
376 const unsigned idx1 = (c & 0x0003F000) >> 12;
378 WINPR_ASSERT(idx0 < alphabetCount);
379 WINPR_ASSERT(idx1 < alphabetCount);
381 *p++ = alphabet[idx0];
382 *p++ = alphabet[idx1];
392 const unsigned c = ((unsigned)q[0] << 16) + ((unsigned)q[1] << 8);
393 const unsigned idx0 = (c & 0x00FC0000) >> 18;
394 const unsigned idx1 = (c & 0x0003F000) >> 12;
395 const unsigned idx2 = (c & 0x00000FC0) >> 6;
397 WINPR_ASSERT(idx0 < alphabetCount);
398 WINPR_ASSERT(idx1 < alphabetCount);
399 WINPR_ASSERT(idx2 < alphabetCount);
401 *p++ = alphabet[idx0];
402 *p++ = alphabet[idx1];
403 *p++ = alphabet[idx2];
412 if (crLf && length % 3)
422static inline char* base64_encode(
const BYTE* WINPR_RESTRICT alphabet,
size_t alphabetCount,
423 const BYTE* WINPR_RESTRICT data,
size_t length, BOOL pad)
425 return base64_encode_ex(alphabet, alphabetCount, data, length, pad, FALSE, 64);
428static inline int base64_decode_char(
const signed char* WINPR_RESTRICT alphabet,
429 size_t alphabetCount,
char c)
432 const int ic = (int)c;
433 if ((ic <= 0) || ((size_t)ic >= alphabetCount))
436 return alphabet[(size_t)c];
439static inline void* base64_decode(
const signed char* WINPR_RESTRICT alphabet,
size_t alphabetCount,
440 const char* WINPR_RESTRICT s,
size_t length,
441 size_t* WINPR_RESTRICT data_len, BOOL pad)
445 const size_t remainder = length % 4;
447 if ((pad && remainder > 0) || (remainder == 1))
450 if (!pad && remainder)
451 length += 4 - remainder;
453 BYTE* q = data = (BYTE*)malloc(length / 4 * 3 + 1);
458 const size_t nBlocks = (length / 4);
459 size_t outputLen = 0;
467 for (
size_t i = 0; i < nBlocks - 1; i++, q += 3)
469 n[0] = base64_decode_char(alphabet, alphabetCount, *s++);
470 n[1] = base64_decode_char(alphabet, alphabetCount, *s++);
471 n[2] = base64_decode_char(alphabet, alphabetCount, *s++);
472 n[3] = base64_decode_char(alphabet, alphabetCount, *s++);
474 if ((n[0] == -1) || (n[1] == -1) || (n[2] == -1) || (n[3] == -1))
477 q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
478 q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
479 q[2] = (BYTE)(((n[2] & 3) << 6) + n[3]);
484 n[0] = base64_decode_char(alphabet, alphabetCount, *s++);
485 n[1] = base64_decode_char(alphabet, alphabetCount, *s++);
486 if ((n[0] == -1) || (n[1] == -1))
489 n[2] = remainder == 2 ? -1 : base64_decode_char(alphabet, alphabetCount, *s++);
490 n[3] = remainder >= 2 ? -1 : base64_decode_char(alphabet, alphabetCount, *s++);
492 q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
500 q[1] = (BYTE)((n[1] & 15) << 4);
506 q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
507 q[2] = (BYTE)((n[2] & 3) << 6);
513 q[0] = (BYTE)((n[0] << 2) + (n[1] >> 4));
514 q[1] = (BYTE)(((n[1] & 15) << 4) + (n[2] >> 2));
515 q[2] = (BYTE)(((n[2] & 3) << 6) + n[3]);
519 *data_len = outputLen;
520 data[outputLen] =
'\0';
528char* crypto_base64_encode_ex(
const BYTE* WINPR_RESTRICT data,
size_t length, BOOL withCrLf)
530 return base64_encode_ex(enc_base64, ARRAYSIZE(enc_base64), data, length, TRUE, withCrLf, 64);
533char* crypto_base64_encode(
const BYTE* WINPR_RESTRICT data,
size_t length)
535 return base64_encode(enc_base64, ARRAYSIZE(enc_base64), data, length, TRUE);
538void crypto_base64_decode(
const char* WINPR_RESTRICT enc_data,
size_t length,
539 BYTE** WINPR_RESTRICT dec_data,
size_t* WINPR_RESTRICT res_length)
542 base64_decode(dec_base64, ARRAYSIZE(dec_base64), enc_data, length, res_length, TRUE);
545char* crypto_base64url_encode(
const BYTE* WINPR_RESTRICT data,
size_t length)
547 return base64_encode(enc_base64url, ARRAYSIZE(enc_base64url), data, length, FALSE);
550void crypto_base64url_decode(
const char* WINPR_RESTRICT enc_data,
size_t length,
551 BYTE** WINPR_RESTRICT dec_data,
size_t* WINPR_RESTRICT res_length)
554 base64_decode(dec_base64url, ARRAYSIZE(dec_base64url), enc_data, length, res_length, FALSE);