Coverage Report

Created: 2019-09-11 14:12

/src/botan/build/include/botan/internal/codec_base.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Base Encoding and Decoding
3
* (C) 2018 Erwan Chaussy
4
* (C) 2018 Jack Lloyd
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#ifndef BOTAN_BASE_CODEC_H_
10
#define BOTAN_BASE_CODEC_H_
11
12
#include <botan/secmem.h>
13
#include <botan/exceptn.h>
14
#include <vector>
15
#include <string>
16
17
namespace Botan {
18
19
/**
20
* Perform encoding using the base provided
21
* @param base object giving access to the encodings specifications
22
* @param output an array of at least base.encode_max_output bytes
23
* @param input is some binary data
24
* @param input_length length of input in bytes
25
* @param input_consumed is an output parameter which says how many
26
*        bytes of input were actually consumed. If less than
27
*        input_length, then the range input[consumed:length]
28
*        should be passed in later along with more input.
29
* @param final_inputs true iff this is the last input, in which case
30
         padding chars will be applied if needed
31
* @return number of bytes written to output
32
*/
33
template <class Base>
34
size_t base_encode(Base&& base,
35
                   char output[],
36
                   const uint8_t input[],
37
                   size_t input_length,
38
                   size_t& input_consumed,
39
                   bool final_inputs)
40
0
   {
41
0
   input_consumed = 0;
42
0
43
0
   const size_t encoding_bytes_in = base.encoding_bytes_in();
44
0
   const size_t encoding_bytes_out = base.encoding_bytes_out();
45
0
46
0
   size_t input_remaining = input_length;
47
0
   size_t output_produced = 0;
48
0
49
0
   while(input_remaining >= encoding_bytes_in)
50
0
      {
51
0
      base.encode(output + output_produced, input + input_consumed);
52
0
53
0
      input_consumed += encoding_bytes_in;
54
0
      output_produced += encoding_bytes_out;
55
0
      input_remaining -= encoding_bytes_in;
56
0
      }
57
0
58
0
   if(final_inputs && input_remaining)
59
0
      {
60
0
      std::vector<uint8_t> remainder(encoding_bytes_in, 0);
61
0
      for(size_t i = 0; i != input_remaining; ++i)
62
0
         { remainder[i] = input[input_consumed + i]; }
63
0
64
0
      base.encode(output + output_produced, remainder.data());
65
0
66
0
      const size_t bits_consumed = base.bits_consumed();
67
0
      const size_t remaining_bits_before_padding = base.remaining_bits_before_padding();
68
0
69
0
      size_t empty_bits = 8 * (encoding_bytes_in - input_remaining);
70
0
      size_t index = output_produced + encoding_bytes_out - 1;
71
0
      while(empty_bits >= remaining_bits_before_padding)
72
0
         {
73
0
         output[index--] = '=';
74
0
         empty_bits -= bits_consumed;
75
0
         }
76
0
77
0
      input_consumed += input_remaining;
78
0
      output_produced += encoding_bytes_out;
79
0
      }
80
0
81
0
   return output_produced;
82
0
   }
Unexecuted instantiation: base64.cpp:unsigned long Botan::base_encode<Botan::(anonymous namespace)::Base64>(Botan::(anonymous namespace)::Base64&&, char*, unsigned char const*, unsigned long, unsigned long&, bool)
Unexecuted instantiation: base64.cpp:unsigned long Botan::base_encode<Botan::(anonymous namespace)::Base64&>(Botan::(anonymous namespace)::Base64&, char*, unsigned char const*, unsigned long, unsigned long&, bool)
83
84
85
template <typename Base>
86
std::string base_encode_to_string(Base&& base, const uint8_t input[], size_t input_length)
87
0
   {
88
0
   const size_t output_length = base.encode_max_output(input_length);
89
0
   std::string output(output_length, 0);
90
0
91
0
   size_t consumed = 0;
92
0
   size_t produced = 0;
93
0
94
0
   if(output_length > 0)
95
0
      {
96
0
      produced = base_encode(base, &output.front(),
97
0
                                   input, input_length,
98
0
                                   consumed, true);
99
0
      }
100
0
101
0
   BOTAN_ASSERT_EQUAL(consumed, input_length, "Consumed the entire input");
102
0
   BOTAN_ASSERT_EQUAL(produced, output.size(), "Produced expected size");
103
0
104
0
   return output;
105
0
   }
106
107
/**
108
* Perform decoding using the base provided
109
* @param base object giving access to the encodings specifications
110
* @param output an array of at least Base::decode_max_output bytes
111
* @param input some base input
112
* @param input_length length of input in bytes
113
* @param input_consumed is an output parameter which says how many
114
*        bytes of input were actually consumed. If less than
115
*        input_length, then the range input[consumed:length]
116
*        should be passed in later along with more input.
117
* @param final_inputs true iff this is the last input, in which case
118
         padding is allowed
119
* @param ignore_ws ignore whitespace on input; if false, throw an
120
                   exception if whitespace is encountered
121
* @return number of bytes written to output
122
*/
123
template <typename Base>
124
size_t base_decode(Base&& base,
125
                   uint8_t output[],
126
                   const char input[],
127
                   size_t input_length,
128
                   size_t& input_consumed,
129
                   bool final_inputs,
130
                   bool ignore_ws = true)
131
5.52k
   {
132
5.52k
   const size_t decoding_bytes_in = base.decoding_bytes_in();
133
5.52k
   const size_t decoding_bytes_out = base.decoding_bytes_out();
134
5.52k
135
5.52k
   uint8_t* out_ptr = output;
136
5.52k
   std::vector<uint8_t> decode_buf(decoding_bytes_in, 0);
137
5.52k
   size_t decode_buf_pos = 0;
138
5.52k
   size_t final_truncate = 0;
139
5.52k
140
5.52k
   clear_mem(output, base.decode_max_output(input_length));
141
5.52k
142
6.00M
   for(size_t i = 0; i != input_length; ++i)
143
5.99M
      {
144
5.99M
      const uint8_t bin = base.lookup_binary_value(input[i]);
145
5.99M
146
5.99M
      if(base.check_bad_char(bin, input[i], ignore_ws)) // May throw Invalid_Argument
147
5.87M
         {
148
5.87M
         decode_buf[decode_buf_pos] = bin;
149
5.87M
         ++decode_buf_pos;
150
5.87M
         }
151
5.99M
152
5.99M
      /*
153
5.99M
      * If we're at the end of the input, pad with 0s and truncate
154
5.99M
      */
155
5.99M
      if(final_inputs && (i == input_length - 1))
156
5.37k
         {
157
5.37k
         if(decode_buf_pos)
158
154
            {
159
470
            for(size_t j = decode_buf_pos; j < decoding_bytes_in; ++j)
160
316
               { decode_buf[j] = 0; }
161
154
162
154
            final_truncate = decoding_bytes_in - decode_buf_pos;
163
154
            decode_buf_pos = decoding_bytes_in;
164
154
            }
165
5.37k
         }
166
5.99M
167
5.99M
      if(decode_buf_pos == decoding_bytes_in)
168
1.46M
         {
169
1.46M
         base.decode(out_ptr, decode_buf.data());
170
1.46M
171
1.46M
         out_ptr += decoding_bytes_out;
172
1.46M
         decode_buf_pos = 0;
173
1.46M
         input_consumed = i+1;
174
1.46M
         }
175
5.99M
      }
176
5.52k
177
12.9k
   while(input_consumed < input_length &&
178
12.9k
         base.lookup_binary_value(input[input_consumed]) == 0x80)
179
7.38k
      {
180
7.38k
      ++input_consumed;
181
7.38k
      }
182
5.52k
183
5.52k
   size_t written = (out_ptr - output) - base.bytes_to_remove(final_truncate);
184
5.52k
185
5.52k
   return written;
186
5.52k
   }
Unexecuted instantiation: base64.cpp:unsigned long Botan::base_decode<Botan::(anonymous namespace)::Base64>(Botan::(anonymous namespace)::Base64&&, unsigned char*, char const*, unsigned long, unsigned long&, bool, bool)
base64.cpp:unsigned long Botan::base_decode<Botan::(anonymous namespace)::Base64&>(Botan::(anonymous namespace)::Base64&, unsigned char*, char const*, unsigned long, unsigned long&, bool, bool)
Line
Count
Source
131
5.52k
   {
132
5.52k
   const size_t decoding_bytes_in = base.decoding_bytes_in();
133
5.52k
   const size_t decoding_bytes_out = base.decoding_bytes_out();
134
5.52k
135
5.52k
   uint8_t* out_ptr = output;
136
5.52k
   std::vector<uint8_t> decode_buf(decoding_bytes_in, 0);
137
5.52k
   size_t decode_buf_pos = 0;
138
5.52k
   size_t final_truncate = 0;
139
5.52k
140
5.52k
   clear_mem(output, base.decode_max_output(input_length));
141
5.52k
142
6.00M
   for(size_t i = 0; i != input_length; ++i)
143
5.99M
      {
144
5.99M
      const uint8_t bin = base.lookup_binary_value(input[i]);
145
5.99M
146
5.99M
      if(base.check_bad_char(bin, input[i], ignore_ws)) // May throw Invalid_Argument
147
5.87M
         {
148
5.87M
         decode_buf[decode_buf_pos] = bin;
149
5.87M
         ++decode_buf_pos;
150
5.87M
         }
151
5.99M
152
5.99M
      /*
153
5.99M
      * If we're at the end of the input, pad with 0s and truncate
154
5.99M
      */
155
5.99M
      if(final_inputs && (i == input_length - 1))
156
5.37k
         {
157
5.37k
         if(decode_buf_pos)
158
154
            {
159
470
            for(size_t j = decode_buf_pos; j < decoding_bytes_in; ++j)
160
316
               { decode_buf[j] = 0; }
161
154
162
154
            final_truncate = decoding_bytes_in - decode_buf_pos;
163
154
            decode_buf_pos = decoding_bytes_in;
164
154
            }
165
5.37k
         }
166
5.99M
167
5.99M
      if(decode_buf_pos == decoding_bytes_in)
168
1.46M
         {
169
1.46M
         base.decode(out_ptr, decode_buf.data());
170
1.46M
171
1.46M
         out_ptr += decoding_bytes_out;
172
1.46M
         decode_buf_pos = 0;
173
1.46M
         input_consumed = i+1;
174
1.46M
         }
175
5.99M
      }
176
5.52k
177
12.9k
   while(input_consumed < input_length &&
178
12.9k
         base.lookup_binary_value(input[input_consumed]) == 0x80)
179
7.38k
      {
180
7.38k
      ++input_consumed;
181
7.38k
      }
182
5.52k
183
5.52k
   size_t written = (out_ptr - output) - base.bytes_to_remove(final_truncate);
184
5.52k
185
5.52k
   return written;
186
5.52k
   }
187
188
template<typename Base>
189
size_t base_decode_full(Base&& base, uint8_t output[], const char input[], size_t input_length, bool ignore_ws)
190
5.52k
   {
191
5.52k
   size_t consumed = 0;
192
5.52k
   const size_t written = base_decode(base, output, input, input_length, consumed, true, ignore_ws);
193
5.52k
194
5.52k
   if(consumed != input_length)
195
82
      {
196
82
      throw Invalid_Argument(base.name() + " decoding failed, input did not have full bytes");
197
82
      }
198
5.44k
199
5.44k
   return written;
200
5.44k
   }
Unexecuted instantiation: base64.cpp:unsigned long Botan::base_decode_full<Botan::(anonymous namespace)::Base64>(Botan::(anonymous namespace)::Base64&&, unsigned char*, char const*, unsigned long, bool)
base64.cpp:unsigned long Botan::base_decode_full<Botan::(anonymous namespace)::Base64&>(Botan::(anonymous namespace)::Base64&, unsigned char*, char const*, unsigned long, bool)
Line
Count
Source
190
5.52k
   {
191
5.52k
   size_t consumed = 0;
192
5.52k
   const size_t written = base_decode(base, output, input, input_length, consumed, true, ignore_ws);
193
5.52k
194
5.52k
   if(consumed != input_length)
195
82
      {
196
82
      throw Invalid_Argument(base.name() + " decoding failed, input did not have full bytes");
197
82
      }
198
5.44k
199
5.44k
   return written;
200
5.44k
   }
201
202
template<typename Vector, typename Base>
203
Vector base_decode_to_vec(Base&& base,
204
                          const char input[],
205
                          size_t input_length,
206
                          bool ignore_ws)
207
5.52k
   {
208
5.52k
   const size_t output_length = base.decode_max_output(input_length);
209
5.52k
   Vector bin(output_length);
210
5.52k
211
5.52k
   const size_t written =
212
5.52k
      base_decode_full(base, bin.data(), input, input_length, ignore_ws);
213
5.52k
214
5.52k
   bin.resize(written);
215
5.52k
   return bin;
216
5.52k
   }
217
218
}
219
220
#endif