blob: 78611c133365611f337ea21006cc9efd90509af1 [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2014, STMicroelectronics International N.V.
*/
#include "base64.h"
static const char base64_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
size_t base64_enc_len(size_t size)
{
return 4 * ((size + 2) / 3) + 1;
}
bool base64_enc(const void *data, size_t dlen, char *buf, size_t *blen)
{
size_t n;
size_t boffs = 0;
const unsigned char *d = data;
n = base64_enc_len(dlen);
if (*blen < n) {
*blen = n;
return false;
}
for (n = 0; n < dlen; n += 3) {
uint32_t igrp;
igrp = d[n];
igrp <<= 8;
if ((n + 1) < dlen)
igrp |= d[n + 1];
igrp <<= 8;
if ((n + 2) < dlen)
igrp |= d[n + 2];
buf[boffs] = base64_table[(igrp >> 18) & 0x3f];
buf[boffs + 1] = base64_table[(igrp >> 12) & 0x3f];
if ((n + 1) < dlen)
buf[boffs + 2] = base64_table[(igrp >> 6) & 0x3f];
else
buf[boffs + 2] = '=';
if ((n + 2) < dlen)
buf[boffs + 3] = base64_table[igrp & 0x3f];
else
buf[boffs + 3] = '=';
boffs += 4;
}
buf[boffs++] = '\0';
*blen = boffs;
return true;
}
static bool get_idx(char ch, uint8_t *idx)
{
size_t n;
for (n = 0; base64_table[n] != '\0'; n++) {
if (ch == base64_table[n]) {
*idx = n;
return true;
}
}
return false;
}
bool base64_dec(const char *data, size_t size, void *buf, size_t *blen)
{
size_t n;
uint8_t idx;
uint8_t *b = buf;
size_t m = 0;
size_t s = 0;
for (n = 0; n < size && data[n] != '\0'; n++) {
if (data[n] == '=')
break; /* Reached pad characters, we're done */
if (!get_idx(data[n], &idx))
continue;
if (m >= *blen)
b = NULL;
switch (s) {
case 0:
if (b)
b[m] = idx << 2;
s++;
break;
case 1:
if (b)
b[m] |= idx >> 4;
m++;
if (m >= *blen)
b = NULL;
if (b)
b[m] = (idx & 0xf) << 4;
s++;
break;
case 2:
if (b)
b[m] |= idx >> 2;
m++;
if (m >= *blen)
b = NULL;
if (b)
b[m] = (idx & 0x3) << 6;
s++;
break;
case 3:
if (b)
b[m] |= idx;
m++;
s = 0;
break;
default:
return false; /* "Can't happen" */
}
}
/* We don't detect if input was bad, but that's OK with the spec. */
*blen = m;
if (b)
return true;
else
return false;
}