Coverage Report

Created: 2019-09-11 14:12

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