blob: c887626245b8de3ecaf832a50f2ef9b653698ce0 [file] [log] [blame]
Yingdi Yu38317e52015-07-22 13:58:02 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento9ced9e62017-10-31 20:34:49 -04002/*
3 * Copyright (c) 2013-2017 Regents of the University of California.
Yingdi Yu38317e52015-07-22 13:58:02 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "hex-decode.hpp"
23
24namespace ndn {
25namespace security {
26namespace transform {
27
Davide Pesavento9ced9e62017-10-31 20:34:49 -040028// hex decoding pad
29static const int8_t C2H[] = {
Yingdi Yu38317e52015-07-22 13:58:02 -070030// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
31 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
32 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
33 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32-47
34 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48-63
35 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64-79
36 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80-95
37 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96-111
38 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112-127
39 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
40 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
41 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
42 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
43 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
44 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
45 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 240-255
47};
Davide Pesavento9ced9e62017-10-31 20:34:49 -040048static_assert(std::extent<decltype(C2H)>::value == 256, "");
49
Yingdi Yu38317e52015-07-22 13:58:02 -070050
51HexDecode::HexDecode()
52 : m_hasOddByte(false)
53 , m_oddByte(0)
54{
55}
56
57size_t
58HexDecode::convert(const uint8_t* hex, size_t hexLen)
59{
60 if (hexLen == 0)
61 return 0;
62
63 setOutputBuffer(toBytes(hex, hexLen));
64
65 size_t totalDecodedLen = hexLen + (m_hasOddByte ? 1 : 0);
66 if (totalDecodedLen % 2 == 1) {
67 m_oddByte = hex[hexLen - 1];
68 m_hasOddByte = true;
69 }
70 else
71 m_hasOddByte = false;
72
73 return hexLen;
74}
75
76void
77HexDecode::finalize()
78{
79 if (m_hasOddByte)
80 BOOST_THROW_EXCEPTION(Error(getIndex(), "Incomplete input"));
81}
82
83unique_ptr<Transform::OBuffer>
84HexDecode::toBytes(const uint8_t* hex, size_t hexLen)
85{
86 size_t bufferSize = (hexLen + (m_hasOddByte ? 1 : 0)) >> 1;
87 auto buffer = make_unique<OBuffer>(bufferSize);
Davide Pesavento9ced9e62017-10-31 20:34:49 -040088 auto it = buffer->begin();
Yingdi Yu38317e52015-07-22 13:58:02 -070089
90 if (m_hasOddByte) {
91 if (C2H[hex[0]] < 0 || C2H[m_oddByte] < 0)
92 BOOST_THROW_EXCEPTION(Error(getIndex(), "Wrong input byte"));
93
Davide Pesavento9ced9e62017-10-31 20:34:49 -040094 *it = (C2H[m_oddByte] << 4) + C2H[hex[0]];
95 ++it;
Yingdi Yu38317e52015-07-22 13:58:02 -070096 hex += 1;
97 hexLen -= 1;
98 }
99
Davide Pesavento9ced9e62017-10-31 20:34:49 -0400100 while (hexLen >= 2) {
Yingdi Yu38317e52015-07-22 13:58:02 -0700101 if (C2H[hex[0]] < 0 || C2H[hex[1]] < 0)
102 BOOST_THROW_EXCEPTION(Error(getIndex(), "Wrong input byte"));
103
Davide Pesavento9ced9e62017-10-31 20:34:49 -0400104 *it = (C2H[hex[0]] << 4) + C2H[hex[1]];
105 ++it;
Yingdi Yu38317e52015-07-22 13:58:02 -0700106 hex += 2;
107 hexLen -= 2;
108 }
109
110 return buffer;
111}
112
113unique_ptr<Transform>
114hexDecode()
115{
116 return make_unique<HexDecode>();
117}
118
119} // namespace transform
120} // namespace security
121} // namespace ndn