Botan  2.7.0
Crypto and TLS for C++11
codec_base.h
Go to the documentation of this file.
1 /*
2 * Base Encoding and Decoding
3 * (C) 2018 Erwan Chaussy
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #ifndef BOTAN_BASE_CODEC_H_
9 #define BOTAN_BASE_CODEC_H_
10 
11 #include <botan/secmem.h>
12 #include <vector>
13 #include <string>
14 
15 namespace Botan {
16 
17 /**
18 * Perform encoding using the base provided
19 * @param base object giving access to the encodings specifications
20 * @param output an array of at least base.encode_max_output bytes
21 * @param input is some binary data
22 * @param input_length length of input in bytes
23 * @param input_consumed is an output parameter which says how many
24 * bytes of input were actually consumed. If less than
25 * input_length, then the range input[consumed:length]
26 * should be passed in later along with more input.
27 * @param final_inputs true iff this is the last input, in which case
28  padding chars will be applied if needed
29 * @return number of bytes written to output
30 */
31 template <class Base>
32 size_t base_encode(Base&& base,
33  char output[],
34  const uint8_t input[],
35  size_t input_length,
36  size_t& input_consumed,
37  bool final_inputs)
38  {
39  input_consumed = 0;
40 
41  const size_t encoding_bytes_in = base.encoding_bytes_in();
42  const size_t encoding_bytes_out = base.encoding_bytes_out();
43 
44  size_t input_remaining = input_length;
45  size_t output_produced = 0;
46 
47  while(input_remaining >= encoding_bytes_in)
48  {
49  base.encode(output + output_produced, input + input_consumed);
50 
51  input_consumed += encoding_bytes_in;
52  output_produced += encoding_bytes_out;
53  input_remaining -= encoding_bytes_in;
54  }
55 
56  if(final_inputs && input_remaining)
57  {
58  std::vector<uint8_t> remainder(encoding_bytes_in, 0);
59  for(size_t i = 0; i != input_remaining; ++i)
60  { remainder[i] = input[input_consumed + i]; }
61 
62  base.encode(output + output_produced, remainder.data());
63 
64  const size_t bits_consumed = base.bits_consumed();
65  const size_t remaining_bits_before_padding = base.remaining_bits_before_padding();
66 
67  size_t empty_bits = 8 * (encoding_bytes_in - input_remaining);
68  size_t index = output_produced + encoding_bytes_out - 1;
69  while(empty_bits >= remaining_bits_before_padding)
70  {
71  output[index--] = '=';
72  empty_bits -= bits_consumed;
73  }
74 
75  input_consumed += input_remaining;
76  output_produced += encoding_bytes_out;
77  }
78 
79  return output_produced;
80  }
81 
82 /**
83 * Perform decoding using the base provided
84 * @param base object giving access to the encodings specifications
85 * @param output an array of at least base.decode_max_output bytes
86 * @param input some base input
87 * @param input_length length of input in bytes
88 * @param input_consumed is an output parameter which says how many
89 * bytes of input were actually consumed. If less than
90 * input_length, then the range input[consumed:length]
91 * should be passed in later along with more input.
92 * @param final_inputs true iff this is the last input, in which case
93  padding is allowed
94 * @param ignore_ws ignore whitespace on input; if false, throw an
95  exception if whitespace is encountered
96 * @return number of bytes written to output
97 */
98 template <typename Base>
99 size_t base_decode(Base&& base,
100  uint8_t output[],
101  const char input[],
102  size_t input_length,
103  size_t& input_consumed,
104  bool final_inputs,
105  bool ignore_ws = true)
106  {
107  const size_t decoding_bytes_in = base.decoding_bytes_in();
108  const size_t decoding_bytes_out = base.decoding_bytes_out();
109 
110  uint8_t* out_ptr = output;
111  std::vector<uint8_t> decode_buf(decoding_bytes_in, 0);
112  size_t decode_buf_pos = 0;
113  size_t final_truncate = 0;
114 
115  clear_mem(output, base.decode_max_output(input_length));
116 
117  for(size_t i = 0; i != input_length; ++i)
118  {
119  const uint8_t bin = base.lookup_binary_value(input[i]);
120 
121  if(base.check_bad_char(bin, input[i], ignore_ws)) // May throw Invalid_Argument
122  {
123  decode_buf[decode_buf_pos] = bin;
124  ++decode_buf_pos;
125  }
126 
127  /*
128  * If we're at the end of the input, pad with 0s and truncate
129  */
130  if(final_inputs && (i == input_length - 1))
131  {
132  if(decode_buf_pos)
133  {
134  for(size_t j = decode_buf_pos; j < decoding_bytes_in; ++j)
135  { decode_buf[j] = 0; }
136 
137  final_truncate = decoding_bytes_in - decode_buf_pos;
138  decode_buf_pos = decoding_bytes_in;
139  }
140  }
141 
142  if(decode_buf_pos == decoding_bytes_in)
143  {
144  base.decode(out_ptr, decode_buf.data());
145 
146  out_ptr += decoding_bytes_out;
147  decode_buf_pos = 0;
148  input_consumed = i+1;
149  }
150  }
151 
152  while(input_consumed < input_length &&
153  base.lookup_binary_value(input[input_consumed]) == 0x80)
154  {
155  ++input_consumed;
156  }
157 
158  size_t written = (out_ptr - output) - base.bytes_to_remove(final_truncate);
159 
160  return written;
161  }
162 
163 }
164 
165 #endif
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)
Definition: codec_base.h:99
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:97
Definition: alg_id.cpp:13
size_t base_encode(Base &&base, char output[], const uint8_t input[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: codec_base.h:32