NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
back-end-file.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2018 Regents of the University of California.
4  *
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 "back-end-file.hpp"
23 #include "key-handle-mem.hpp"
24 #include "../transform.hpp"
25 #include "../transform/private-key.hpp"
26 #include "../../encoding/buffer-stream.hpp"
27 
28 #include <cstdlib>
29 #include <fstream>
30 #include <sys/stat.h>
31 
32 #include <boost/filesystem.hpp>
33 
34 namespace ndn {
35 namespace security {
36 namespace tpm {
37 
39 
41 {
42 public:
43  explicit
44  Impl(const std::string& dir)
45  {
46  if (!dir.empty()) {
47  keystorePath = boost::filesystem::path(dir);
48  }
49 #ifdef NDN_CXX_HAVE_TESTS
50  else if (std::getenv("TEST_HOME") != nullptr) {
51  keystorePath = boost::filesystem::path(std::getenv("TEST_HOME")) / ".ndn";
52  }
53 #endif // NDN_CXX_HAVE_TESTS
54  else if (std::getenv("HOME") != nullptr) {
55  keystorePath = boost::filesystem::path(std::getenv("HOME")) / ".ndn";
56  }
57  else {
58  keystorePath = boost::filesystem::current_path() / ".ndn";
59  }
60 
61  keystorePath /= "ndnsec-key-file";
62  boost::filesystem::create_directories(keystorePath);
63  }
64 
65  boost::filesystem::path
66  toFileName(const Name& keyName)
67  {
68  std::stringstream os;
69  {
70  using namespace transform;
71  bufferSource(keyName.wireEncode().wire(), keyName.wireEncode().size()) >>
73  }
74  return keystorePath / (os.str() + ".privkey");
75  }
76 
77 public:
78  boost::filesystem::path keystorePath;
79 };
80 
81 BackEndFile::BackEndFile(const std::string& location)
82  : m_impl(new Impl(location))
83 {
84 }
85 
86 BackEndFile::~BackEndFile() = default;
87 
88 const std::string&
90 {
91  static std::string scheme = "tpm-file";
92  return scheme;
93 }
94 
95 bool
96 BackEndFile::doHasKey(const Name& keyName) const
97 {
98  if (!boost::filesystem::exists(m_impl->toFileName(keyName)))
99  return false;
100 
101  try {
102  loadKey(keyName);
103  return true;
104  }
105  catch (const std::runtime_error&) {
106  return false;
107  }
108 }
109 
110 unique_ptr<KeyHandle>
111 BackEndFile::doGetKeyHandle(const Name& keyName) const
112 {
113  if (!doHasKey(keyName))
114  return nullptr;
115 
116  return make_unique<KeyHandleMem>(loadKey(keyName));
117 }
118 
119 unique_ptr<KeyHandle>
120 BackEndFile::doCreateKey(const Name& identityName, const KeyParams& params)
121 {
122  shared_ptr<PrivateKey> key(transform::generatePrivateKey(params).release());
123  unique_ptr<KeyHandle> keyHandle = make_unique<KeyHandleMem>(key);
124 
125  setKeyName(*keyHandle, identityName, params);
126 
127  try {
128  saveKey(keyHandle->getKeyName(), key);
129  return keyHandle;
130  }
131  catch (const std::runtime_error& e) {
132  BOOST_THROW_EXCEPTION(Error(std::string("Cannot write key to disk: ") + e.what()));
133  }
134 }
135 
136 void
137 BackEndFile::doDeleteKey(const Name& keyName)
138 {
139  boost::filesystem::path keyPath(m_impl->toFileName(keyName));
140 
141  if (boost::filesystem::exists(keyPath)) {
142  try {
143  boost::filesystem::remove(keyPath);
144  }
145  catch (const boost::filesystem::filesystem_error&) {
146  BOOST_THROW_EXCEPTION(Error("Cannot delete key"));
147  }
148  }
149 }
150 
152 BackEndFile::doExportKey(const Name& keyName, const char* pw, size_t pwLen)
153 {
154  shared_ptr<PrivateKey> key;
155  try {
156  key = loadKey(keyName);
157  }
158  catch (const PrivateKey::Error&) {
159  BOOST_THROW_EXCEPTION(Error("Cannot export private key"));
160  }
161  OBufferStream os;
162  key->savePkcs8(os, pw, pwLen);
163  return os.buf();
164 }
165 
166 void
167 BackEndFile::doImportKey(const Name& keyName, const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
168 {
169  try {
170  auto key = make_shared<PrivateKey>();
171  key->loadPkcs8(buf, size, pw, pwLen);
172  saveKey(keyName, key);
173  }
174  catch (const PrivateKey::Error&) {
175  BOOST_THROW_EXCEPTION(Error("Cannot import private key"));
176  }
177 }
178 
179 shared_ptr<PrivateKey>
180 BackEndFile::loadKey(const Name& keyName) const
181 {
182  auto key = make_shared<PrivateKey>();
183  std::fstream is(m_impl->toFileName(keyName).string(), std::ios_base::in);
184  key->loadPkcs1Base64(is);
185  return key;
186 }
187 
188 void
189 BackEndFile::saveKey(const Name& keyName, shared_ptr<PrivateKey> key)
190 {
191  std::string fileName = m_impl->toFileName(keyName).string();
192  std::fstream os(fileName, std::ios_base::out);
193  key->savePkcs1Base64(os);
194 
195  // set file permission
196  ::chmod(fileName.c_str(), 0000400);
197 }
198 
199 } // namespace tpm
200 } // namespace security
201 } // namespace ndn
Copyright (c) 2011-2015 Regents of the University of California.
unique_ptr< Transform > hexEncode(bool useUpperCase)
Definition: hex-encode.cpp:70
boost::filesystem::path keystorePath
unique_ptr< PrivateKey > generatePrivateKey(const KeyParams &keyParams)
Generate a private key according to keyParams.
static const std::string & getScheme()
unique_ptr< Sink > streamSink(std::ostream &os)
Definition: stream-sink.cpp:53
BackEndFile(const std::string &location="")
Create file-based TPM backend.
unique_ptr< Transform > digestFilter(DigestAlgorithm algo)
Use the SHA256 hash of the public key as the key id.
Represents an absolute name.
Definition: name.hpp:42
static void setKeyName(KeyHandle &keyHandle, const Name &identity, const KeyParams &params)
Set the key name in keyHandle according to identity and params.
Definition: back-end.cpp:110
boost::filesystem::path toFileName(const Name &keyName)
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:126
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:89