Coverage Report

Created: 2020-11-21 08:34

/src/botan/src/lib/codec/hex/hex.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Hex Encoding and Decoding
3
* (C) 2010 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/hex.h>
9
#include <botan/mem_ops.h>
10
#include <botan/exceptn.h>
11
12
namespace Botan {
13
14
void hex_encode(char output[],
15
                const uint8_t input[],
16
                size_t input_length,
17
                bool uppercase)
18
26.4k
   {
19
26.4k
   static const uint8_t BIN_TO_HEX_UPPER[16] = {
20
26.4k
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
21
26.4k
      'A', 'B', 'C', 'D', 'E', 'F' };
22
23
26.4k
   static const uint8_t BIN_TO_HEX_LOWER[16] = {
24
26.4k
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
25
26.4k
      'a', 'b', 'c', 'd', 'e', 'f' };
26
27
26.4k
   const uint8_t* tbl = uppercase ? BIN_TO_HEX_UPPER : BIN_TO_HEX_LOWER;
28
29
740k
   for(size_t i = 0; i != input_length; ++i)
30
713k
      {
31
713k
      uint8_t x = input[i];
32
713k
      output[2*i  ] = tbl[(x >> 4) & 0x0F];
33
713k
      output[2*i+1] = tbl[(x     ) & 0x0F];
34
713k
      }
35
26.4k
   }
36
37
std::string hex_encode(const uint8_t input[],
38
                       size_t input_length,
39
                       bool uppercase)
40
26.4k
   {
41
26.4k
   std::string output(2 * input_length, 0);
42
43
26.4k
   if(input_length)
44
26.4k
      hex_encode(&output.front(), input, input_length, uppercase);
45
46
26.4k
   return output;
47
26.4k
   }
48
49
size_t hex_decode(uint8_t output[],
50
                  const char input[],
51
                  size_t input_length,
52
                  size_t& input_consumed,
53
                  bool ignore_ws)
54
78.1k
   {
55
   /*
56
   * Mapping of hex characters to either their binary equivalent
57
   * or to an error code.
58
   *  If valid hex (0-9 A-F a-f), the value.
59
   *  If whitespace, then 0x80
60
   *  Otherwise 0xFF
61
   * Warning: this table assumes ASCII character encodings
62
   */
63
64
78.1k
   static const uint8_t HEX_TO_BIN[256] = {
65
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
66
78.1k
      0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
67
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
68
78.1k
      0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
69
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
70
78.1k
      0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
71
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
72
78.1k
      0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
73
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
74
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,
75
78.1k
      0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
76
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
77
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
78
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
79
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
80
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
81
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
82
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
83
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
84
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
85
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
86
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
87
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
88
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
90
78.1k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
91
92
78.1k
   uint8_t* out_ptr = output;
93
78.1k
   bool top_nibble = true;
94
95
78.1k
   clear_mem(output, input_length / 2);
96
97
7.02M
   for(size_t i = 0; i != input_length; ++i)
98
6.94M
      {
99
6.94M
      const uint8_t bin = HEX_TO_BIN[static_cast<uint8_t>(input[i])];
100
101
6.94M
      if(bin >= 0x10)
102
0
         {
103
0
         if(bin == 0x80 && ignore_ws)
104
0
            continue;
105
106
0
         std::string bad_char(1, input[i]);
107
0
         if(bad_char == "\t")
108
0
           bad_char = "\\t";
109
0
         else if(bad_char == "\n")
110
0
           bad_char = "\\n";
111
112
0
         throw Invalid_Argument(
113
0
           std::string("hex_decode: invalid hex character '") +
114
0
           bad_char + "'");
115
0
         }
116
117
6.94M
      if(top_nibble)
118
3.47M
         *out_ptr |= bin << 4;
119
3.47M
      else
120
3.47M
         *out_ptr |= bin;
121
122
6.94M
      top_nibble = !top_nibble;
123
6.94M
      if(top_nibble)
124
3.47M
         ++out_ptr;
125
6.94M
      }
126
127
78.1k
   input_consumed = input_length;
128
78.1k
   size_t written = (out_ptr - output);
129
130
   /*
131
   * We only got half of a uint8_t at the end; zap the half-written
132
   * output and mark it as unread
133
   */
134
78.1k
   if(!top_nibble)
135
0
      {
136
0
      *out_ptr = 0;
137
0
      input_consumed -= 1;
138
0
      }
139
140
78.1k
   return written;
141
78.1k
   }
142
143
size_t hex_decode(uint8_t output[],
144
                  const char input[],
145
                  size_t input_length,
146
                  bool ignore_ws)
147
78.1k
   {
148
78.1k
   size_t consumed = 0;
149
78.1k
   size_t written = hex_decode(output, input, input_length,
150
78.1k
                               consumed, ignore_ws);
151
152
78.1k
   if(consumed != input_length)
153
0
      throw Invalid_Argument("hex_decode: input did not have full bytes");
154
155
78.1k
   return written;
156
78.1k
   }
157
158
size_t hex_decode(uint8_t output[],
159
                  const std::string& input,
160
                  bool ignore_ws)
161
49.6k
   {
162
49.6k
   return hex_decode(output, input.data(), input.length(), ignore_ws);
163
49.6k
   }
164
165
secure_vector<uint8_t> hex_decode_locked(const char input[],
166
                                      size_t input_length,
167
                                      bool ignore_ws)
168
28.5k
   {
169
28.5k
   secure_vector<uint8_t> bin(1 + input_length / 2);
170
171
28.5k
   size_t written = hex_decode(bin.data(),
172
28.5k
                               input,
173
28.5k
                               input_length,
174
28.5k
                               ignore_ws);
175
176
28.5k
   bin.resize(written);
177
28.5k
   return bin;
178
28.5k
   }
179
180
secure_vector<uint8_t> hex_decode_locked(const std::string& input,
181
                                      bool ignore_ws)
182
0
   {
183
0
   return hex_decode_locked(input.data(), input.size(), ignore_ws);
184
0
   }
185
186
std::vector<uint8_t> hex_decode(const char input[],
187
                             size_t input_length,
188
                             bool ignore_ws)
189
0
   {
190
0
   std::vector<uint8_t> bin(1 + input_length / 2);
191
192
0
   size_t written = hex_decode(bin.data(),
193
0
                               input,
194
0
                               input_length,
195
0
                               ignore_ws);
196
197
0
   bin.resize(written);
198
0
   return bin;
199
0
   }
200
201
std::vector<uint8_t> hex_decode(const std::string& input,
202
                             bool ignore_ws)
203
0
   {
204
0
   return hex_decode(input.data(), input.size(), ignore_ws);
205
0
   }
206
207
}