8#include <botan/base64.h>
10#include <botan/exceptn.h>
11#include <botan/internal/charset.h>
12#include <botan/internal/codec_base.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/int_utils.h>
16#include <botan/internal/loadstor.h>
17#include <botan/internal/rounding.h>
25 static std::string
name() noexcept {
return "base64"; }
27 static size_t encoding_bytes_in() noexcept {
return m_encoding_bytes_in; }
29 static size_t encoding_bytes_out() noexcept {
return m_encoding_bytes_out; }
31 static size_t decoding_bytes_in() noexcept {
return m_encoding_bytes_out; }
33 static size_t decoding_bytes_out() noexcept {
return m_encoding_bytes_in; }
35 static size_t bits_consumed() noexcept {
return m_encoding_bits; }
37 static size_t remaining_bits_before_padding() noexcept {
return m_remaining_bits_before_padding; }
39 static size_t encode_max_output(
size_t input_length) {
40 return (
round_up(input_length, m_encoding_bytes_in) / m_encoding_bytes_in) * m_encoding_bytes_out;
43 static size_t decode_max_output(
size_t input_length) {
44 return (
round_up(input_length, m_encoding_bytes_out) * m_encoding_bytes_in) / m_encoding_bytes_out;
47 static void encode(
char out[4],
const uint8_t in[3])
noexcept;
49 static uint8_t lookup_binary_value(
char input)
noexcept;
51 static bool check_bad_char(uint8_t bin,
char input,
bool ignore_ws);
53 static void decode(uint8_t*
out_ptr,
const uint8_t decode_buf[4]) {
54 out_ptr[0] = (decode_buf[0] << 2) | (decode_buf[1] >> 4);
55 out_ptr[1] = (decode_buf[1] << 4) | (decode_buf[2] >> 2);
56 out_ptr[2] = (decode_buf[2] << 6) | decode_buf[3];
59 static size_t bytes_to_remove(
size_t final_truncate) {
return final_truncate; }
62 static const size_t m_encoding_bits = 6;
63 static const size_t m_remaining_bits_before_padding = 8;
65 static const size_t m_encoding_bytes_in = 3;
66 static const size_t m_encoding_bytes_out = 4;
69uint32_t lookup_base64_chars(uint32_t x32) {
83 uint32_t r = x32 + 0x41414141;
85 r += (~swar_lt<uint32_t>(x32, 0x1A1A1A1A)) & 0x06060606;
86 r -= (~swar_lt<uint32_t>(x32, 0x34343434)) & 0x4B4B4B4B;
87 r -= (~swar_lt<uint32_t>(x32, 0x3E3E3E3E)) & 0x0F0F0F0F;
88 r += (~swar_lt<uint32_t>(x32, 0x3F3F3F3F)) & 0x03030303;
94void Base64::encode(
char out[4],
const uint8_t in[3])
noexcept {
95 const uint32_t b0 = (in[0] & 0xFC) >> 2;
96 const uint32_t b1 = ((in[0] & 0x03) << 4) | (in[1] >> 4);
97 const uint32_t b2 = ((in[1] & 0x0F) << 2) | (in[2] >> 6);
98 const uint32_t b3 = in[2] & 0x3F;
100 const uint32_t z = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
102 const uint32_t b64 = lookup_base64_chars(z);
111uint8_t Base64::lookup_binary_value(
char input)
noexcept {
112 auto has_zero_byte = [](uint64_t v) {
return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080); };
116 return ((((v - 1) & 0x0101010101010101) * 0x0101010101010101) >> 56) - 1;
119 constexpr uint64_t lo = 0x0101010101010101;
121 const uint8_t x =
static_cast<uint8_t
>(input);
123 const uint64_t x8 = x * lo;
126 constexpr uint64_t val_l =
make_uint64(0, 0, 0, 0, 0,
'A',
'a',
'0');
127 constexpr uint64_t val_u =
make_uint64(0, 0, 0, 0, 0, 26, 26, 10);
134 const uint64_t val_v = 0xbfb904 ^ (0xFF000000 - (x << 24));
139 constexpr uint64_t specials_i =
make_uint64(0,
'+',
'/',
'=',
' ',
'\n',
'\t',
'\r');
141 const uint64_t specials_v = 0x3e3f8180808080 ^ (
static_cast<uint64_t
>(z) << 56);
143 const uint64_t smask = has_zero_byte(x8 ^ specials_i) ^ 0x8000000000000000;
149bool Base64::check_bad_char(uint8_t bin,
char input,
bool ignore_ws) {
152 }
else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws))) {
160size_t base64_encode(
char out[],
const uint8_t in[],
size_t input_length,
size_t& input_consumed,
bool final_inputs) {
161 return base_encode(Base64(), out, in, input_length, input_consumed, final_inputs);
169 uint8_t out[],
const char in[],
size_t input_length,
size_t& input_consumed,
bool final_inputs,
bool ignore_ws) {
170 return base_decode(Base64(), out, in, input_length, input_consumed, final_inputs, ignore_ws);
173size_t base64_decode(uint8_t output[],
const char input[],
size_t input_length,
bool ignore_ws) {
177size_t base64_decode(uint8_t output[], std::string_view input,
bool ignore_ws) {
178 return base64_decode(output, input.data(), input.length(), ignore_ws);
181size_t base64_decode(std::span<uint8_t> output, std::string_view input,
bool ignore_ws) {
185 return base64_decode(output.data(), input.data(), input.length(), ignore_ws);
197 return Base64::encode_max_output(input_length);
201 return Base64::decode_max_output(input_length);
int(* final)(unsigned char *, CTX *)
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
constexpr uint8_t get_byte(T input)
std::string format_char_for_display(char c)
constexpr auto out_ptr(T &outptr) noexcept
constexpr uint64_t make_uint64(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3, uint8_t i4, uint8_t i5, uint8_t i6, uint8_t i7)
std::string fmt(std::string_view format, const T &... args)
constexpr T swar_in_range(T v, T lower, T upper)
constexpr size_t round_up(size_t n, size_t align_to)
constexpr size_t index_of_first_set_byte(T v)
Vector base_decode_to_vec(Base &&base, const char input[], size_t input_length, bool ignore_ws)
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
size_t base64_decode(uint8_t out[], const char in[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws)
size_t base_encode(Base &&base, char output[], const uint8_t input[], size_t input_length, size_t &input_consumed, bool final_inputs)
size_t base64_encode_max_output(size_t input_length)
size_t base64_decode_max_output(size_t input_length)
size_t base_decode(Base &&base, uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws=true)
std::string base_encode_to_string(Base &&base, const uint8_t input[], size_t input_length)
std::vector< T, secure_allocator< T > > secure_vector
size_t base_decode_full(Base &&base, uint8_t output[], const char input[], size_t input_length, bool ignore_ws)