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-2022 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 
27 
28 #include <cstdlib>
29 #include <fstream>
30 #include <sys/stat.h>
31 
32 #if BOOST_VERSION >= 107200
33 #include <boost/filesystem/exception.hpp>
34 #endif
35 #include <boost/filesystem/operations.hpp>
36 #include <boost/filesystem/path.hpp>
37 #include <boost/lexical_cast.hpp>
38 
39 namespace ndn {
40 namespace security {
41 namespace tpm {
42 
43 namespace fs = boost::filesystem;
45 
47 {
48 public:
49  explicit
50  Impl(const std::string& dir)
51  {
52  if (!dir.empty()) {
53  m_keystorePath = fs::path(dir);
54  }
55 #ifdef NDN_CXX_HAVE_TESTS
56  else if (std::getenv("TEST_HOME") != nullptr) {
57  m_keystorePath = fs::path(std::getenv("TEST_HOME")) / ".ndn";
58  }
59 #endif // NDN_CXX_HAVE_TESTS
60  else if (std::getenv("HOME") != nullptr) {
61  m_keystorePath = fs::path(std::getenv("HOME")) / ".ndn";
62  }
63  else {
64  m_keystorePath = fs::current_path() / ".ndn";
65  }
66 
67  m_keystorePath /= "ndnsec-key-file";
68  fs::create_directories(m_keystorePath);
69  }
70 
71  fs::path
72  toFileName(const Name& keyName) const
73  {
74  std::ostringstream os;
75  {
76  using namespace transform;
77  bufferSource(keyName.wireEncode())
79  >> hexEncode()
80  >> streamSink(os);
81  }
82  return m_keystorePath / (os.str() + ".privkey");
83  }
84 
85 private:
86  fs::path m_keystorePath;
87 };
88 
89 BackEndFile::BackEndFile(const std::string& location)
90  : m_impl(make_unique<Impl>(location))
91 {
92 }
93 
94 BackEndFile::~BackEndFile() = default;
95 
96 const std::string&
98 {
99  static std::string scheme = "tpm-file";
100  return scheme;
101 }
102 
103 bool
104 BackEndFile::doHasKey(const Name& keyName) const
105 {
106  if (!fs::exists(m_impl->toFileName(keyName)))
107  return false;
108 
109  try {
110  loadKey(keyName);
111  return true;
112  }
113  catch (const std::runtime_error&) {
114  return false;
115  }
116 }
117 
118 unique_ptr<KeyHandle>
119 BackEndFile::doGetKeyHandle(const Name& keyName) const
120 {
121  if (!doHasKey(keyName))
122  return nullptr;
123 
124  return make_unique<KeyHandleMem>(loadKey(keyName));
125 }
126 
127 unique_ptr<KeyHandle>
128 BackEndFile::doCreateKey(const Name& identityName, const KeyParams& params)
129 {
130  switch (params.getKeyType()) {
131  case KeyType::RSA:
132  case KeyType::EC:
133  break;
134  default:
135  NDN_THROW(std::invalid_argument("File-based TPM does not support creating a key of type " +
136  boost::lexical_cast<std::string>(params.getKeyType())));
137  }
138 
139  shared_ptr<PrivateKey> key(transform::generatePrivateKey(params).release());
140  unique_ptr<KeyHandle> keyHandle = make_unique<KeyHandleMem>(key);
141 
142  Name keyName = constructAsymmetricKeyName(*keyHandle, identityName, params);
143  keyHandle->setKeyName(keyName);
144 
145  try {
146  saveKey(keyName, *key);
147  return keyHandle;
148  }
149  catch (const std::runtime_error&) {
150  NDN_THROW_NESTED(Error("Cannot write key to file"));
151  }
152 }
153 
154 void
155 BackEndFile::doDeleteKey(const Name& keyName)
156 {
157  auto keyPath = m_impl->toFileName(keyName);
158  if (!fs::exists(keyPath))
159  return;
160 
161  try {
162  fs::remove(keyPath);
163  }
164  catch (const fs::filesystem_error&) {
165  NDN_THROW_NESTED(Error("Cannot remove key file"));
166  }
167 }
168 
170 BackEndFile::doExportKey(const Name& keyName, const char* pw, size_t pwLen)
171 {
172  unique_ptr<PrivateKey> key;
173  try {
174  key = loadKey(keyName);
175  }
176  catch (const PrivateKey::Error&) {
177  NDN_THROW_NESTED(Error("Cannot export private key"));
178  }
179 
180  OBufferStream os;
181  key->savePkcs8(os, pw, pwLen);
182  return os.buf();
183 }
184 
185 void
186 BackEndFile::doImportKey(const Name& keyName, span<const uint8_t> pkcs8, const char* pw, size_t pwLen)
187 {
188  try {
189  PrivateKey key;
190  key.loadPkcs8(pkcs8, pw, pwLen);
191  saveKey(keyName, key);
192  }
193  catch (const PrivateKey::Error&) {
194  NDN_THROW_NESTED(Error("Cannot import private key"));
195  }
196 }
197 
198 void
199 BackEndFile::doImportKey(const Name& keyName, shared_ptr<transform::PrivateKey> key)
200 {
201  try {
202  saveKey(keyName, *key);
203  }
204  catch (const PrivateKey::Error&) {
205  NDN_THROW_NESTED(Error("Cannot import private key"));
206  }
207 }
208 
209 unique_ptr<PrivateKey>
210 BackEndFile::loadKey(const Name& keyName) const
211 {
212  std::ifstream is(m_impl->toFileName(keyName).string());
213  auto key = make_unique<PrivateKey>();
214  key->loadPkcs1Base64(is);
215  return key;
216 }
217 
218 void
219 BackEndFile::saveKey(const Name& keyName, const PrivateKey& key)
220 {
221  std::string fileName = m_impl->toFileName(keyName).string();
222  std::ofstream os(fileName);
223  key.savePkcs1Base64(os);
224 
225  // set file permission
226  ::chmod(fileName.data(), 0000400);
227 }
228 
229 } // namespace tpm
230 } // namespace security
231 } // namespace ndn
#define NDN_THROW_NESTED(e)
Definition: exception.hpp:71
Copyright (c) 2011-2015 Regents of the University of California.
RSA key, supports sign/verify and encrypt/decrypt operations.
unique_ptr< Transform > hexEncode(bool useUpperCase)
Definition: hex-encode.cpp:70
unique_ptr< PrivateKey > generatePrivateKey(const KeyParams &keyParams)
Generate a private key according to keyParams.
#define NDN_THROW(e)
Definition: exception.hpp:61
Name constructAsymmetricKeyName(const KeyHandle &key, const Name &identity, const KeyParams &params) const
Construct and return the name of a RSA or EC key, based on identity and params.
Definition: back-end.cpp:114
static const std::string & getScheme()
void loadPkcs8(span< const uint8_t > buf, const char *pw, size_t pwLen)
Load the private key in encrypted PKCS#8 format from a buffer buf with passphrase pw...
unique_ptr< Sink > streamSink(std::ostream &os)
Definition: stream-sink.cpp:53
BackEndFile(const std::string &location="")
Create file-based TPM backend.
Elliptic Curve key (e.g. for ECDSA), supports sign/verify operations.
Abstraction of private key in crypto transformation.
Definition: private-key.hpp:38
unique_ptr< Transform > digestFilter(DigestAlgorithm algo)
Use the SHA-256 hash of the public key as key id.
Represents an absolute name.
Definition: name.hpp:41
KeyType getKeyType() const
Definition: key-params.hpp:48
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
Base class for key parameters.
Definition: key-params.hpp:35
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:117
implements an output stream that constructs ndn::Buffer
void savePkcs1Base64(std::ostream &os) const
Save the private key in base64-encoded PKCS#1 format into a stream os.
fs::path toFileName(const Name &keyName) const
shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:139