Common code

Change-Id: I038344df88bf4bd7d894aee005deceb575662a1f
diff --git a/src/common.cpp b/src/common.cpp
new file mode 100644
index 0000000..da4c5fd
--- /dev/null
+++ b/src/common.cpp
@@ -0,0 +1,56 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC 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.
+ *
+ * NAC 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 NAC library authors and contributors.
+ */
+
+#include "common.hpp"
+
+namespace ndn {
+namespace nac {
+
+Name
+convertKekNameToKdkPrefix(const Name& kekName, const ErrorCallback& onFailure)
+{
+  // * <access-namespace>/KEK/<key-id>  =>>   <access-namespace>/KDK/<key-id>
+  if (kekName.size() < 2 || kekName.get(-2) != KEK) {
+    onFailure(ErrorCode::KekInvalidName, "Invalid KEK name [" + kekName.toUri() + "]");
+    return {};
+  }
+
+  return kekName.getPrefix(-2).append(KDK).append(kekName.get(-1));
+}
+
+std::tuple<Name, Name, Name>
+extractKdkInfoFromCkName(const Name& ckDataName, const Name& ckName, const ErrorCallback& onFailure)
+{
+  // <full-ck-name-with-id> | /ENCRYPTED-BY/<kek-prefix>/NAC/KEK/<key-id>
+
+  if (ckDataName.size() < ckName.size() + 1 ||
+      ckDataName.getPrefix(ckName.size()) != ckName ||
+      ckDataName.get(ckName.size()) != ENCRYPTED_BY) {
+    onFailure(ErrorCode::CkInvalidName, "Invalid CK name [" + ckDataName.toUri() + "]");
+    return {};
+  }
+
+  auto kekName = ckDataName.getSubName(ckName.size() + 1);
+  return std::make_tuple(convertKekNameToKdkPrefix(kekName, onFailure),
+                         kekName.getPrefix(-2),
+                         kekName.getPrefix(-2).append("KEY").append(kekName.get(-1)));
+}
+
+} // namespace nac
+} // namespace ndn
diff --git a/src/common.hpp b/src/common.hpp
new file mode 100644
index 0000000..b37f50c
--- /dev/null
+++ b/src/common.hpp
@@ -0,0 +1,155 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * NAC 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.
+ *
+ * NAC 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 NAC library authors and contributors.
+ */
+
+#ifndef NDN_NAC_COMMON_HPP
+#define NDN_NAC_COMMON_HPP
+
+#include "config.hpp"
+
+#ifdef NDN_NAC_HAVE_TESTS
+#define VIRTUAL_WITH_TESTS virtual
+#define PUBLIC_WITH_TESTS_ELSE_PROTECTED public
+#define PUBLIC_WITH_TESTS_ELSE_PRIVATE public
+#define PROTECTED_WITH_TESTS_ELSE_PRIVATE protected
+#else
+#define VIRTUAL_WITH_TESTS
+#define PUBLIC_WITH_TESTS_ELSE_PROTECTED protected
+#define PUBLIC_WITH_TESTS_ELSE_PRIVATE private
+#define PROTECTED_WITH_TESTS_ELSE_PRIVATE private
+#endif
+
+#include <cstddef>
+#include <list>
+#include <map>
+#include <queue>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <ndn-cxx/data.hpp>
+#include <ndn-cxx/encoding/buffer-stream.hpp>
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/ims/in-memory-storage-persistent.hpp>
+#include <ndn-cxx/interest.hpp>
+#include <ndn-cxx/link.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
+#include <ndn-cxx/security/transform/block-cipher.hpp>
+#include <ndn-cxx/security/transform/buffer-source.hpp>
+#include <ndn-cxx/security/transform/public-key.hpp>
+#include <ndn-cxx/security/transform/stream-sink.hpp>
+#include <ndn-cxx/security/v2/key-chain.hpp>
+#include <ndn-cxx/security/v2/validation-callback.hpp>
+#include <ndn-cxx/security/v2/validation-error.hpp>
+#include <ndn-cxx/security/v2/validator.hpp>
+#include <ndn-cxx/security/validator-null.hpp>
+#include <ndn-cxx/util/random.hpp>
+#include <ndn-cxx/util/signal.hpp>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/asio.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/noncopyable.hpp>
+
+namespace ndn {
+namespace nac {
+
+using security::Identity;
+using security::Key;
+using security::SigningInfo;
+using security::SafeBag;
+using security::ValidatorNull;
+using security::transform::PublicKey;
+using security::v2::Certificate;
+using security::v2::DataValidationFailureCallback;
+using security::v2::DataValidationSuccessCallback;
+using security::v2::ValidationError;
+using security::v2::Validator;
+using security::v2::extractKeyNameFromCertName;
+
+namespace tlv {
+using namespace ndn::tlv;
+
+enum {
+  EncryptedContent = 130,
+  EncryptedPayload = 132,
+  InitialVector = 133,
+  EncryptedPayloadKey = 134,
+};
+
+} // namespace tlv
+
+const name::Component ENCRYPTED_BY("ENCRYPTED-BY");
+const name::Component NAC("NAC");
+const name::Component KEK("KEK");
+const name::Component KDK("KDK");
+const name::Component CK("CK");
+
+const size_t AES_KEY_SIZE = 32;
+const size_t AES_IV_SIZE = 16;
+
+enum class ErrorCode {
+  KekRetrievalFailure = 1,
+  KekRetrievalTimeout = 2,
+  KekInvalidName = 3,
+
+  KdkRetrievalFailure = 11,
+  KdkRetrievalTimeout = 12,
+  KdkInvalidName = 13,
+  KdkDecryptionFailure = 14,
+
+  CkRetrievalFailure = 21,
+  CkRetrievalTimeout = 22,
+  CkInvalidName = 23,
+
+  MissingRequiredKeyLocator = 101,
+  TpmKeyNotFound = 102
+};
+
+using ErrorCallback = std::function<void (const ErrorCode&, const std::string&)>;
+
+
+class Error : public std::runtime_error
+{
+public:
+  using std::runtime_error::runtime_error;
+};
+
+/**
+ * @brief Convert KEK name to KDK prefix:
+ *
+ * `<identity>/NAC/KEK/<key-id>`  =>>  `<identity>/NAC/KDK/<key-id>`
+ */
+Name
+convertKekNameToKdkPrefix(const Name& kekName, const ErrorCallback& onFailure);
+
+/**
+ * @brief Extract KDK information from name of CK data packet name
+ *
+ * @return tuple of (KDK prefix, KDK identity, and KDK key id).  The last two identify
+ *         KDK private/key pair in KeyChain
+ */
+std::tuple<Name, Name, Name>
+extractKdkInfoFromCkName(const Name& ckDataName, const Name& ckName, const ErrorCallback& onFailure);
+
+} // namespace nac
+} // namespace ndn
+
+#endif // NDN_NAC_COMMON_HPP
diff --git a/tests/tests/common.t.cpp b/tests/tests/common.t.cpp
new file mode 100644
index 0000000..7b84d2a
--- /dev/null
+++ b/tests/tests/common.t.cpp
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018, Regents of the University of California
+ *
+ * This file is part of NAC (Name-Based Access Control for NDN).
+ * See AUTHORS.md for complete list of NAC authors and contributors.
+ *
+ * NAC is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NAC 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NAC, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common.hpp"
+
+#include "boost-test.hpp"
+
+namespace ndn {
+namespace nac {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(TestCommon)
+
+BOOST_AUTO_TEST_CASE(Helpers)
+{
+  bool hasFailed = false;
+  auto onFailed = [&] (auto...) { hasFailed = true; };
+
+  auto kdkPrefix = convertKekNameToKdkPrefix(Name("/access/prefix/NAC/dataset/KEK/id"), onFailed);
+
+  BOOST_CHECK(!hasFailed);
+  BOOST_CHECK(kdkPrefix == Name("/access/prefix/NAC/dataset/KDK/id"));
+
+  hasFailed = false;
+  kdkPrefix = convertKekNameToKdkPrefix(Name("/invalid/name"), onFailed);
+  BOOST_CHECK(hasFailed);
+  BOOST_CHECK(kdkPrefix.empty());
+
+  hasFailed = false;
+  Name kdkIdentity, kdkKeyName;
+  std::tie(kdkPrefix, kdkIdentity, kdkKeyName) =
+    extractKdkInfoFromCkName(Name("/ck/prefix/stuff/ENCRYPTED-BY/access/prefix/NAC/dataset/KEK/id"),
+                             Name("/ck/prefix/stuff"), onFailed);
+  BOOST_CHECK(!hasFailed);
+  BOOST_CHECK_EQUAL(kdkPrefix, Name("/access/prefix/NAC/dataset/KDK/id"));
+  BOOST_CHECK_EQUAL(kdkIdentity, Name("/access/prefix/NAC/dataset"));
+  BOOST_CHECK_EQUAL(kdkKeyName, Name("/access/prefix/NAC/dataset/KEY/id"));
+
+  hasFailed = false;
+  std::tie(kdkPrefix, kdkIdentity, kdkKeyName) =
+    extractKdkInfoFromCkName(Name("/ck/prefix/ENCRYPTED-BY/access/prefix/NAC/dataset/KEK/id"),
+                             Name("/ck/prefix/stuff"), onFailed);
+  BOOST_CHECK(hasFailed);
+  BOOST_CHECK(kdkPrefix.empty());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nac
+} // namespace ndn