Coverage Report

Created: 2020-06-30 13:58

/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
28.4k
   {
19
28.4k
   static const uint8_t BIN_TO_HEX_UPPER[16] = {
20
28.4k
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
21
28.4k
      'A', 'B', 'C', 'D', 'E', 'F' };
22
28.4k
23
28.4k
   static const uint8_t BIN_TO_HEX_LOWER[16] = {
24
28.4k
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
25
28.4k
      'a', 'b', 'c', 'd', 'e', 'f' };
26
28.4k
27
28.4k
   const uint8_t* tbl = uppercase ? BIN_TO_HEX_UPPER : BIN_TO_HEX_LOWER;
28
28.4k
29
782k
   for(size_t i = 0; i != input_length; ++i)
30
753k
      {
31
753k
      uint8_t x = input[i];
32
753k
      output[2*i  ] = tbl[(x >> 4) & 0x0F];
33
753k
      output[2*i+1] = tbl[(x     ) & 0x0F];
34
753k
      }
35
28.4k
   }
36
37
std::string hex_encode(const uint8_t input[],
38
                       size_t input_length,
39
                       bool uppercase)
40
28.4k
   {
41
28.4k
   std::string output(2 * input_length, 0);
42
28.4k
43
28.4k
   if(input_length)
44
28.4k
      hex_encode(&output.front(), input, input_length, uppercase);
45
28.4k
46
28.4k
   return output;
47
28.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
73.3k
   {
55
73.3k
   /*
56
73.3k
   * Mapping of hex characters to either their binary equivalent
57
73.3k
   * or to an error code.
58
73.3k
   *  If valid hex (0-9 A-F a-f), the value.
59
73.3k
   *  If whitespace, then 0x80
60
73.3k
   *  Otherwise 0xFF
61
73.3k
   * Warning: this table assumes ASCII character encodings
62
73.3k
   */
63
73.3k
64
73.3k
   static const uint8_t HEX_TO_BIN[256] = {
65
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
66
73.3k
      0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
67
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
68
73.3k
      0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
69
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
70
73.3k
      0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF,
71
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
72
73.3k
      0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
73
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
74
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x0B, 0x0C,
75
73.3k
      0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
76
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
77
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
78
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
79
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
80
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
81
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
82
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
83
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
84
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
85
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
86
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
87
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
88
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
89
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
90
73.3k
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
91
73.3k
92
73.3k
   uint8_t* out_ptr = output;
93
73.3k
   bool top_nibble = true;
94
73.3k
95
73.3k
   clear_mem(output, input_length / 2);
96
73.3k
97
6.07M
   for(size_t i = 0; i != input_length; ++i)
98
6.00M
      {
99
6.00M
      const uint8_t bin = HEX_TO_BIN[static_cast<uint8_t>(input[i])];
100
6.00M
101
6.00M
      if(bin >= 0x10)
102
0
         {
103
0
         if(bin == 0x80 && ignore_ws)
104
0
            continue;
105
0
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
0
112
0
         throw Invalid_Argument(
113
0
           std::string("hex_decode: invalid hex character '") +
114
0
           bad_char + "'");
115
0
         }
116
6.00M
117
6.00M
      if(top_nibble)
118
3.00M
         *out_ptr |= bin << 4;
119
3.00M
      else
120
3.00M
         *out_ptr |= bin;
121
6.00M
122
6.00M
      top_nibble = !top_nibble;
123
6.00M
      if(top_nibble)
124
3.00M
         ++out_ptr;
125
6.00M
      }
126
73.3k
127
73.3k
   input_consumed = input_length;
128
73.3k
   size_t written = (out_ptr - output);
129
73.3k
130
73.3k
   /*
131
73.3k
   * We only got half of a uint8_t at the end; zap the half-written
132
73.3k
   * output and mark it as unread
133
73.3k
   */
134
73.3k
   if(!top_nibble)
135
0
      {
136
0
      *out_ptr = 0;
137
0
      input_consumed -= 1;
138
0
      }
139
73.3k
140
73.3k
   return written;
141
73.3k
   }
142
143
size_t hex_decode(uint8_t output[],
144
                  const char input[],
145
                  size_t input_length,
146
                  bool ignore_ws)
147
73.3k
   {
148
73.3k
   size_t consumed = 0;
149
73.3k
   size_t written = hex_decode(output, input, input_length,
150
73.3k
                               consumed, ignore_ws);
151
73.3k
152
73.3k
   if(consumed != input_length)
153
0
      throw Invalid_Argument("hex_decode: input did not have full bytes");
154
73.3k
155
73.3k
   return written;
156
73.3k
   }
157
158
size_t hex_decode(uint8_t output[],
159
                  const std::string& input,
160
                  bool ignore_ws)
161
47.7k
   {
162
47.7k
   return hex_decode(output, input.data(), input.length(), ignore_ws);
163
47.7k
   }
164
165
secure_vector<uint8_t> hex_decode_locked(const char input[],
166
                                      size_t input_length,
167
                                      bool ignore_ws)
168
25.5k
   {
169
25.5k
   secure_vector<uint8_t> bin(1 + input_length / 2);
170
25.5k
171
25.5k
   size_t written = hex_decode(bin.data(),
172
25.5k
                               input,
173
25.5k
                               input_length,
174
25.5k
                               ignore_ws);
175
25.5k
176
25.5k
   bin.resize(written);
177
25.5k
   return bin;
178
25.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
0
192
0
   size_t written = hex_decode(bin.data(),
193
0
                               input,
194
0
                               input_length,
195
0
                               ignore_ws);
196
0
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
}