1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) 2020, Linaro Limited
* 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 = 0;
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 = 0;
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)
{
bool ret = false;
size_t n = 0;
uint8_t idx = 0;
uint8_t *b = buf;
size_t m = 0;
size_t s = 0;
uint8_t byte = 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;
switch (s) {
case 0:
byte = idx << 2;
s++;
break;
case 1:
if (b && m < *blen)
b[m] = byte | (idx >> 4);
m++;
byte = (idx & 0xf) << 4;
s++;
break;
case 2:
if (b && m < *blen)
b[m] = byte | (idx >> 2);
m++;
byte = (idx & 0x3) << 6;
s++;
break;
case 3:
if (b && m < *blen)
b[m] = byte | 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.
* We expect that each fully extracted byte is stored in output buffer.
*/
ret = (!m && !*blen) || (b && (m <= *blen));
*blen = m;
return ret;
}
|