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/fmt.h>
14#include <botan/internal/int_utils.h>
15#include <botan/internal/loadstor.h>
16#include <botan/internal/rounding.h>
24 static std::string name() {
return "base64"; }
26 static constexpr size_t encoding_bytes_in() noexcept {
return m_encoding_bytes_in; }
28 static constexpr size_t encoding_bytes_out() noexcept {
return m_encoding_bytes_out; }
30 static constexpr size_t decoding_bytes_in() noexcept {
return m_encoding_bytes_out; }
32 static constexpr size_t decoding_bytes_out() noexcept {
return m_encoding_bytes_in; }
34 static constexpr size_t bits_consumed() noexcept {
return m_encoding_bits; }
36 static constexpr size_t remaining_bits_before_padding() noexcept {
return m_remaining_bits_before_padding; }
38 static constexpr size_t encode_max_output(
size_t input_length) {
39 const size_t encoding_blocks =
round_up(input_length, m_encoding_bytes_in) / m_encoding_bytes_in;
40 return mul_or_throw(encoding_blocks, m_encoding_bytes_out,
"Input too large to base64 encode");
43 static constexpr size_t decode_max_output(
size_t input_length) {
45 return (
round_up(input_length, m_encoding_bytes_out) / m_encoding_bytes_out) * m_encoding_bytes_in;
48 static void encode(
char out[4],
const uint8_t in[3])
noexcept;
50 static uint8_t lookup_binary_value(
char input)
noexcept;
52 static bool check_bad_char(uint8_t bin,
char input,
bool ignore_ws);
54 static void decode(uint8_t*
out_ptr,
const uint8_t decode_buf[4]) {
55 out_ptr[0] = (decode_buf[0] << 2) | (decode_buf[1] >> 4);
56 out_ptr[1] = (decode_buf[1] << 4) | (decode_buf[2] >> 2);
57 out_ptr[2] = (decode_buf[2] << 6) | decode_buf[3];
60 static size_t bytes_to_remove(
size_t final_truncate) {
return final_truncate; }
63 static constexpr size_t m_encoding_bits = 6;
64 static constexpr size_t m_remaining_bits_before_padding = 8;
66 static constexpr size_t m_encoding_bytes_in = 3;
67 static constexpr size_t m_encoding_bytes_out = 4;
70uint32_t lookup_base64_chars(uint32_t x32) {
84 uint32_t r = x32 + 0x41414141;
95void Base64::encode(
char out[4],
const uint8_t in[3])
noexcept {
96 const uint32_t b0 = (in[0] & 0xFC) >> 2;
97 const uint32_t b1 = ((in[0] & 0x03) << 4) | (in[1] >> 4);
98 const uint32_t b2 = ((in[1] & 0x0F) << 2) | (in[2] >> 6);
99 const uint32_t b3 = in[2] & 0x3F;
101 const uint32_t z = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
103 const uint32_t b64 = lookup_base64_chars(z);
112uint8_t Base64::lookup_binary_value(
char input)
noexcept {
113 auto has_zero_byte = [](uint64_t v) {
return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080); };
117 return ((((v - 1) & 0x0101010101010101) * 0x0101010101010101) >> 56) - 1;
120 constexpr uint64_t lo = 0x0101010101010101;
122 const uint8_t x =
static_cast<uint8_t
>(input);
124 const uint64_t x8 = x * lo;
127 constexpr uint64_t val_l =
make_uint64(0, 0, 0, 0, 0,
'A',
'a',
'0');
128 constexpr uint64_t val_u =
make_uint64(0, 0, 0, 0, 0, 26, 26, 10);
135 const uint64_t val_v = 0xbfb904 ^ (0xFF000000 - (x << 24));
140 constexpr uint64_t specials_i =
make_uint64(0,
'+',
'/',
'=',
' ',
'\n',
'\t',
'\r');
142 const uint64_t specials_v = 0x3e3f8180808080 ^ (
static_cast<uint64_t
>(z) << 56);
144 const uint64_t smask = has_zero_byte(x8 ^ specials_i) ^ 0x8000000000000000;
150bool Base64::check_bad_char(uint8_t bin,
char input,
bool ignore_ws) {
153 }
else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws))) {
161size_t base64_encode(
char out[],
const uint8_t in[],
size_t input_length,
size_t& input_consumed,
bool final_inputs) {
162 return base_encode(Base64(), out, in, input_length, input_consumed, final_inputs);
170 uint8_t out[],
const char in[],
size_t input_length,
size_t& input_consumed,
bool final_inputs,
bool ignore_ws) {
171 return base_decode(Base64(), out, in, input_length, input_consumed, final_inputs, ignore_ws);
174size_t base64_decode(uint8_t output[],
const char input[],
size_t input_length,
bool ignore_ws) {
178size_t base64_decode(uint8_t output[], std::string_view input,
bool ignore_ws) {
179 return base64_decode(output, input.data(), input.length(), ignore_ws);
182size_t base64_decode(std::span<uint8_t> output, std::string_view input,
bool ignore_ws) {
186 return base64_decode(output.data(), input.data(), input.length(), ignore_ws);
198 return Base64::encode_max_output(input_length);
202 return Base64::decode_max_output(input_length);
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 T mul_or_throw(T a, T b, std::string_view msg)
constexpr T swar_lt(T a, T b)
std::string base_encode_to_string(const Base &base, const uint8_t input[], size_t input_length)
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)
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
size_t base_encode(const Base &base, char output[], const uint8_t input[], 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_decode(const Base &base, uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws=true)
size_t base64_encode_max_output(size_t input_length)
size_t base64_decode_max_output(size_t input_length)
std::vector< T, secure_allocator< T > > secure_vector
Vector base_decode_to_vec(const Base &base, const char input[], size_t input_length, bool ignore_ws)
size_t base_decode_full(const Base &base, uint8_t output[], const char input[], size_t input_length, bool ignore_ws)