1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2020, Linaro Limited 4 * Copyright (c) 2014, STMicroelectronics International N.V. 5 */ 6 #include "base64.h" 7 8 static const char base64_table[] = 9 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 10 11 size_t base64_enc_len(size_t size) 12 { 13 return 4 * ((size + 2) / 3) + 1; 14 } 15 16 bool base64_enc(const void *data, size_t dlen, char *buf, size_t *blen) 17 { 18 size_t n = 0; 19 size_t boffs = 0; 20 const unsigned char *d = data; 21 22 n = base64_enc_len(dlen); 23 if (*blen < n) { 24 *blen = n; 25 return false; 26 } 27 28 for (n = 0; n < dlen; n += 3) { 29 uint32_t igrp; 30 31 igrp = d[n]; 32 igrp <<= 8; 33 34 if ((n + 1) < dlen) 35 igrp |= d[n + 1]; 36 igrp <<= 8; 37 38 if ((n + 2) < dlen) 39 igrp |= d[n + 2]; 40 41 buf[boffs] = base64_table[(igrp >> 18) & 0x3f]; 42 buf[boffs + 1] = base64_table[(igrp >> 12) & 0x3f]; 43 if ((n + 1) < dlen) 44 buf[boffs + 2] = base64_table[(igrp >> 6) & 0x3f]; 45 else 46 buf[boffs + 2] = '='; 47 if ((n + 2) < dlen) 48 buf[boffs + 3] = base64_table[igrp & 0x3f]; 49 else 50 buf[boffs + 3] = '='; 51 52 boffs += 4; 53 } 54 buf[boffs++] = '\0'; 55 56 *blen = boffs; 57 return true; 58 } 59 60 static bool get_idx(char ch, uint8_t *idx) 61 { 62 size_t n = 0; 63 64 for (n = 0; base64_table[n] != '\0'; n++) { 65 if (ch == base64_table[n]) { 66 *idx = n; 67 return true; 68 } 69 } 70 return false; 71 } 72 73 bool base64_dec(const char *data, size_t size, void *buf, size_t *blen) 74 { 75 bool ret = false; 76 size_t n = 0; 77 uint8_t idx = 0; 78 uint8_t *b = buf; 79 size_t m = 0; 80 size_t s = 0; 81 uint8_t byte = 0; 82 83 for (n = 0; n < size && data[n] != '\0'; n++) { 84 if (data[n] == '=') 85 break; /* Reached pad characters, we're done */ 86 87 if (!get_idx(data[n], &idx)) 88 continue; 89 90 switch (s) { 91 case 0: 92 byte = idx << 2; 93 s++; 94 break; 95 case 1: 96 if (b && m < *blen) 97 b[m] = byte | (idx >> 4); 98 m++; 99 byte = (idx & 0xf) << 4; 100 s++; 101 break; 102 case 2: 103 if (b && m < *blen) 104 b[m] = byte | (idx >> 2); 105 m++; 106 byte = (idx & 0x3) << 6; 107 s++; 108 break; 109 case 3: 110 if (b && m < *blen) 111 b[m] = byte | idx; 112 m++; 113 s = 0; 114 break; 115 default: 116 return false; /* "Can't happen" */ 117 } 118 } 119 120 /* 121 * We don't detect if input was bad, but that's OK with the spec. 122 * We expect that each fully extracted byte is stored in output buffer. 123 */ 124 ret = (!m && !*blen) || (b && (m <= *blen)); 125 *blen = m; 126 127 return ret; 128 } 129