blob: d46c301036a0da7c16b2b6e9600a51f03de724c8 [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/*
Davide Pesavento765abc92021-12-27 00:44:04 -05003 * Copyright (c) 2013-2021 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
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/security/transform/hex-decode.hpp"
Yingdi Yu38317e52015-07-22 13:58:02 -070023
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
Davide Pesavento765abc92021-12-27 00:44:04 -050058HexDecode::convert(span<const uint8_t> hex)
Yingdi Yu38317e52015-07-22 13:58:02 -070059{
Davide Pesavento765abc92021-12-27 00:44:04 -050060 if (hex.empty())
Yingdi Yu38317e52015-07-22 13:58:02 -070061 return 0;
62
Davide Pesavento765abc92021-12-27 00:44:04 -050063 setOutputBuffer(toBytes(hex.data(), hex.size()));
Yingdi Yu38317e52015-07-22 13:58:02 -070064
Davide Pesavento765abc92021-12-27 00:44:04 -050065 size_t totalDecodedLen = hex.size() + (m_hasOddByte ? 1 : 0);
Yingdi Yu38317e52015-07-22 13:58:02 -070066 if (totalDecodedLen % 2 == 1) {
Davide Pesavento765abc92021-12-27 00:44:04 -050067 m_oddByte = hex.back();
Yingdi Yu38317e52015-07-22 13:58:02 -070068 m_hasOddByte = true;
69 }
Davide Pesavento765abc92021-12-27 00:44:04 -050070 else {
Yingdi Yu38317e52015-07-22 13:58:02 -070071 m_hasOddByte = false;
Davide Pesavento765abc92021-12-27 00:44:04 -050072 }
Yingdi Yu38317e52015-07-22 13:58:02 -070073
Davide Pesavento765abc92021-12-27 00:44:04 -050074 return hex.size();
Yingdi Yu38317e52015-07-22 13:58:02 -070075}
76
77void
78HexDecode::finalize()
79{
80 if (m_hasOddByte)
Davide Pesavento923ba442019-02-12 22:00:38 -050081 NDN_THROW(Error(getIndex(), "Incomplete input"));
Yingdi Yu38317e52015-07-22 13:58:02 -070082}
83
84unique_ptr<Transform::OBuffer>
85HexDecode::toBytes(const uint8_t* hex, size_t hexLen)
86{
87 size_t bufferSize = (hexLen + (m_hasOddByte ? 1 : 0)) >> 1;
88 auto buffer = make_unique<OBuffer>(bufferSize);
Davide Pesavento9ced9e62017-10-31 20:34:49 -040089 auto it = buffer->begin();
Yingdi Yu38317e52015-07-22 13:58:02 -070090
91 if (m_hasOddByte) {
92 if (C2H[hex[0]] < 0 || C2H[m_oddByte] < 0)
Davide Pesavento923ba442019-02-12 22:00:38 -050093 NDN_THROW(Error(getIndex(), "Wrong input byte"));
Yingdi Yu38317e52015-07-22 13:58:02 -070094
Davide Pesavento9ced9e62017-10-31 20:34:49 -040095 *it = (C2H[m_oddByte] << 4) + C2H[hex[0]];
96 ++it;
Yingdi Yu38317e52015-07-22 13:58:02 -070097 hex += 1;
98 hexLen -= 1;
99 }
100
Davide Pesavento9ced9e62017-10-31 20:34:49 -0400101 while (hexLen >= 2) {
Yingdi Yu38317e52015-07-22 13:58:02 -0700102 if (C2H[hex[0]] < 0 || C2H[hex[1]] < 0)
Davide Pesavento923ba442019-02-12 22:00:38 -0500103 NDN_THROW(Error(getIndex(), "Wrong input byte"));
Yingdi Yu38317e52015-07-22 13:58:02 -0700104
Davide Pesavento9ced9e62017-10-31 20:34:49 -0400105 *it = (C2H[hex[0]] << 4) + C2H[hex[1]];
106 ++it;
Yingdi Yu38317e52015-07-22 13:58:02 -0700107 hex += 2;
108 hexLen -= 2;
109 }
110
111 return buffer;
112}
113
114unique_ptr<Transform>
115hexDecode()
116{
117 return make_unique<HexDecode>();
118}
119
120} // namespace transform
121} // namespace security
122} // namespace ndn