Coverage Report

Created: 2020-05-23 13:54

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