From 17d40a464e7d37a7aa64a731e24c7db5805a9bd8 Mon Sep 17 00:00:00 2001 From: alashkova Date: Fri, 11 Oct 2024 16:15:50 +0300 Subject: [PATCH] =?UTF-8?q?SUPPORT-8592.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20base64=5Fdecoded=5Flength()=20=D0=B8?= =?UTF-8?q?=20decode=5Fbase64=5Furl()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/base64.c | 89 +++++++++++++++++++++++++++++++++++++++++++++- src/utils/base64.h | 2 ++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/utils/base64.c b/src/utils/base64.c index cd4de4f..4c9381e 100644 --- a/src/utils/base64.c +++ b/src/utils/base64.c @@ -1,5 +1,7 @@ #include "base64.h" +#include "logger.h" + #include #include @@ -79,4 +81,89 @@ encode_base64_url(str_t *dst, const str_t *src) dst->data[n * 4 + 3] = basis64_url[d]; } } -} \ No newline at end of file +} + +static void +init_decode_base64_url(unsigned char **table) +{ + static unsigned char basis64_url[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, + 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + + assert(table != NULL); + + *table = basis64_url; +} + +int +decode_base64_url(str_t *dst, const str_t *src) +{ + uint32_t value = 0; + unsigned int c; + size_t i; + size_t n = 0; + uint8_t *p = NULL; + + assert(dst != NULL && !str_t_is_null(*dst)); + assert(src != NULL && !str_t_is_null(*src)); + + if ((src->len % 4) == 1) { + LOG_ERROR("decode_base64_url failed. Desc: invalid src length (%zd)", src->len); + goto error; + } + + unsigned char *basis64_url; + init_decode_base64_url(&basis64_url); + + p = (uint8_t *) dst->data; + + for (i = 0; i < src->len; i++) { + c = (unsigned int) src->data[i]; + + if (c < 128 && basis64_url[c] < 64) { + value = (value << 6) | basis64_url[c]; + + if ((i % 4) == 3) { + if (p != NULL) { + p[n] = (value >> 16) & 0xFF; + p[n + 1] = (value >> 8) & 0xFF; + p[n + 2] = value & 0xFF; + } + + n += 3; + value = 0; + } + } else { + LOG_ERROR("decode_base64_url failed. Desc: invalid character: %c", src->data[i]); + goto error; + } + } + + if ((src->len % 4) == 2) { + if (p != NULL) { + p[n] = (value >> 4) & 0xFF; + } + n++; + } else if ((src->len % 4) == 3) { + if (p != NULL) { + p[n] = (value >> 10) & 0xFF; + p[n + 1] = (value >> 2) & 0xFF; + } + n += 2; + } + + dst->len = n; + + return 0; + +error: + LOG_ERROR("decode_base64_url exit with error"); + return -1; +} diff --git a/src/utils/base64.h b/src/utils/base64.h index 55b199d..6ec70e4 100644 --- a/src/utils/base64.h +++ b/src/utils/base64.h @@ -4,7 +4,9 @@ #include "str_t.h" #define base64_encoded_length(len) (((len + 2) / 3) * 4) +#define base64_decoded_length(len) (((len + 3) / 4) * 3) void encode_base64_url(str_t *dst, const str_t *src); +int decode_base64_url(str_t *dst, const str_t *src); #endif // BASE64_H \ No newline at end of file