security: Add base64 and hex encoding/decoding support in transformation
Change-Id: I11d5c8921abcf04411aac38382dc285269f553ef
Refs: #3009
diff --git a/src/security/transform/hex-decode.cpp b/src/security/transform/hex-decode.cpp
new file mode 100644
index 0000000..aa82461
--- /dev/null
+++ b/src/security/transform/hex-decode.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "hex-decode.hpp"
+
+namespace ndn {
+namespace security {
+namespace transform {
+
+static const int8_t C2H[256] = { // hex decoding pad.
+// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0-15
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16-31
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 32-47
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 48-63
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 64-79
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80-95
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 96-111
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 112-127
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 128-143
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 144-159
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 160-175
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 176-191
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 192-207
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 208-223
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 224-239
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 240-255
+};
+
+HexDecode::HexDecode()
+ : m_hasOddByte(false)
+ , m_oddByte(0)
+{
+}
+
+size_t
+HexDecode::convert(const uint8_t* hex, size_t hexLen)
+{
+ if (hexLen == 0)
+ return 0;
+
+ setOutputBuffer(toBytes(hex, hexLen));
+
+ size_t totalDecodedLen = hexLen + (m_hasOddByte ? 1 : 0);
+ if (totalDecodedLen % 2 == 1) {
+ m_oddByte = hex[hexLen - 1];
+ m_hasOddByte = true;
+ }
+ else
+ m_hasOddByte = false;
+
+ return hexLen;
+}
+
+void
+HexDecode::finalize()
+{
+ if (m_hasOddByte)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Incomplete input"));
+}
+
+unique_ptr<Transform::OBuffer>
+HexDecode::toBytes(const uint8_t* hex, size_t hexLen)
+{
+ size_t bufferSize = (hexLen + (m_hasOddByte ? 1 : 0)) >> 1;
+ auto buffer = make_unique<OBuffer>(bufferSize);
+ uint8_t* buf = &buffer->front();
+
+ if (m_hasOddByte) {
+ if (C2H[hex[0]] < 0 || C2H[m_oddByte] < 0)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Wrong input byte"));
+
+ buf[0] = (C2H[m_oddByte] << 4) + (C2H[hex[0]]);
+ buf += 1;
+ hex += 1;
+ hexLen -= 1;
+ }
+
+ while (hexLen > 1) {
+ if (C2H[hex[0]] < 0 || C2H[hex[1]] < 0)
+ BOOST_THROW_EXCEPTION(Error(getIndex(), "Wrong input byte"));
+
+ buf[0] = (C2H[hex[0]] << 4) + (C2H[hex[1]]);
+ buf += 1;
+ hex += 2;
+ hexLen -= 2;
+ }
+
+ return buffer;
+}
+
+unique_ptr<Transform>
+hexDecode()
+{
+ return make_unique<HexDecode>();
+}
+
+} // namespace transform
+} // namespace security
+} // namespace ndn