All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sec-tpm-file.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
10 #include "common.hpp"
11 
12 #include "sec-tpm-file.hpp"
13 
14 #include <boost/filesystem.hpp>
15 #include <boost/algorithm/string.hpp>
16 
17 #include "cryptopp.hpp"
18 
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 
22 #include <algorithm>
23 
24 using namespace std;
25 
26 namespace ndn {
27 
29 {
30 public:
31  Impl(const string& dir)
32  {
33  if (dir.empty())
34  m_keystorePath = boost::filesystem::path(getenv("HOME")) / ".ndn" / "ndnsec-tpm-file";
35  else
36  m_keystorePath = dir;
37 
38  boost::filesystem::create_directories (m_keystorePath);
39  }
40 
41  boost::filesystem::path
42  nameTransform(const string& keyName, const string& extension)
43  {
44  using namespace CryptoPP;
45  string digest;
46  SHA256 hash;
47  StringSource src(keyName,
48  true,
49  new HashFilter(hash,
50  new Base64Encoder(new CryptoPP::StringSink(digest))));
51 
52  boost::algorithm::trim(digest);
53  std::replace(digest.begin(), digest.end(), '/', '%');
54 
55  return m_keystorePath / (digest + extension);
56  }
57 
58  string
59  maintainMapping(const string& keyName)
60  {
61  string keyFileName = nameTransform(keyName, "").string();
62 
63  ofstream outfile;
64  string dirFile = (m_keystorePath / "mapping.txt").string();
65 
66  outfile.open(dirFile.c_str(), std::ios_base::app);
67  outfile << keyName << ' ' << keyFileName << '\n';
68  outfile.close();
69 
70  return keyFileName;
71  }
72 
73 public:
74  boost::filesystem::path m_keystorePath;
75 };
76 
77 
78 SecTpmFile::SecTpmFile(const string& dir)
79  : m_impl(new Impl(dir))
80  , m_inTerminal(false)
81 {}
82 
83 void
84 SecTpmFile::generateKeyPairInTpm(const Name& keyName, KeyType keyType, int keySize)
85 {
86  string keyURI = keyName.toUri();
87 
88  if (doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
89  throw Error("public key exists");
91  throw Error("private key exists");
92 
93  string keyFileName = m_impl->maintainMapping(keyURI);
94 
95  try
96  {
97  switch (keyType)
98  {
99  case KEY_TYPE_RSA:
100  {
101  using namespace CryptoPP;
102  AutoSeededRandomPool rng;
103 
104  InvertibleRSAFunction privateKey;
105  privateKey.Initialize(rng, keySize);
106 
107  string privateKeyFileName = keyFileName + ".pri";
108  Base64Encoder privateKeySink(new FileSink(privateKeyFileName.c_str()));
109  privateKey.DEREncode(privateKeySink);
110  privateKeySink.MessageEnd();
111 
112  RSAFunction publicKey(privateKey);
113  string publicKeyFileName = keyFileName + ".pub";
114  Base64Encoder publicKeySink(new FileSink(publicKeyFileName.c_str()));
115  publicKey.DEREncode(publicKeySink);
116  publicKeySink.MessageEnd();
117 
118  /*set file permission*/
119  chmod(privateKeyFileName.c_str(), 0000400);
120  chmod(publicKeyFileName.c_str(), 0000444);
121  return;
122  }
123  default:
124  throw Error("Unsupported key type!");
125  }
126  }
127  catch (CryptoPP::Exception& e)
128  {
129  throw Error(e.what());
130  }
131 }
132 
133 void
135 {
136  boost::filesystem::path publicKeyPath(m_impl->nameTransform(keyName.toUri(), ".pub"));
137  boost::filesystem::path privateKeyPath(m_impl->nameTransform(keyName.toUri(), ".pri"));
138 
139  if (boost::filesystem::exists(publicKeyPath))
140  boost::filesystem::remove(publicKeyPath);
141 
142  if (boost::filesystem::exists(privateKeyPath))
143  boost::filesystem::remove(privateKeyPath);
144 }
145 
146 shared_ptr<PublicKey>
148 {
149  string keyURI = keyName.toUri();
150 
151  if (!doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
152  throw Error("Public Key does not exist");
153 
154  ostringstream os;
155  try
156  {
157  using namespace CryptoPP;
158  FileSource(m_impl->nameTransform(keyURI, ".pub").string().c_str(),
159  true,
160  new Base64Decoder(new FileSink(os)));
161  }
162  catch (CryptoPP::Exception& e)
163  {
164  throw Error(e.what());
165  }
166 
167  return make_shared<PublicKey>(reinterpret_cast<const uint8_t*>(os.str().c_str()),
168  os.str().size());
169 }
170 
173 {
174  OBufferStream privateKeyOs;
175  CryptoPP::FileSource(m_impl->nameTransform(keyName.toUri(), ".pri").string().c_str(), true,
176  new CryptoPP::Base64Decoder(new CryptoPP::FileSink(privateKeyOs)));
177 
178  return privateKeyOs.buf();
179 }
180 
181 bool
182 SecTpmFile::importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
183 {
184  try
185  {
186  using namespace CryptoPP;
187 
188  string keyFileName = m_impl->maintainMapping(keyName.toUri());
189  keyFileName.append(".pri");
190  StringSource(buf, size,
191  true,
192  new Base64Encoder(new FileSink(keyFileName.c_str())));
193  return true;
194  }
195  catch (CryptoPP::Exception& e)
196  {
197  return false;
198  }
199 }
200 
201 bool
202 SecTpmFile::importPublicKeyPkcs1IntoTpm(const Name& keyName, const uint8_t* buf, size_t size)
203 {
204  try
205  {
206  using namespace CryptoPP;
207 
208  string keyFileName = m_impl->maintainMapping(keyName.toUri());
209  keyFileName.append(".pub");
210  StringSource(buf, size,
211  true,
212  new Base64Encoder(new FileSink(keyFileName.c_str())));
213  return true;
214  }
215  catch (CryptoPP::Exception& e)
216  {
217  return false;
218  }
219 }
220 
221 Block
222 SecTpmFile::signInTpm(const uint8_t* data, size_t dataLength,
223  const Name& keyName, DigestAlgorithm digestAlgorithm)
224 {
225  string keyURI = keyName.toUri();
226 
227  if (!doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
228  throw Error("private key doesn't exists");
229 
230  try
231  {
232  using namespace CryptoPP;
233  AutoSeededRandomPool rng;
234 
235  //Read private key
236  ByteQueue bytes;
237  FileSource file(m_impl->nameTransform(keyURI, ".pri").string().c_str(),
238  true, new Base64Decoder);
239  file.TransferTo(bytes);
240  bytes.MessageEnd();
241  RSA::PrivateKey privateKey;
242  privateKey.Load(bytes);
243 
244  //Sign message
245  switch (digestAlgorithm)
246  {
248  {
249  RSASS<PKCS1v15, SHA256>::Signer signer(privateKey);
250 
251  OBufferStream os;
252  StringSource(data, dataLength,
253  true,
254  new SignerFilter(rng, signer, new FileSink(os)));
255 
256  return Block(Tlv::SignatureValue, os.buf());
257  }
258  default:
259  throw Error("Unsupported digest algorithm!");
260  }
261  }
262  catch (CryptoPP::Exception& e)
263  {
264  throw Error(e.what());
265  }
266 }
267 
268 
270 SecTpmFile::decryptInTpm(const uint8_t* data, size_t dataLength,
271  const Name& keyName, bool isSymmetric)
272 {
273  throw Error("SecTpmFile::decryptInTpm is not supported!");
274  // string keyURI = keyName.toUri();
275  // if (!isSymmetric)
276  // {
277  // if (!doesKeyExistInTpm(keyName, KEY_CLASS_PRIVATE))
278  // throw Error("private key doesn't exist");
279 
280  // try{
281  // using namespace CryptoPP;
282  // AutoSeededRandomPool rng;
283 
284  // //Read private key
285  // ByteQueue bytes;
286  // FileSource file(m_impl->nameTransform(keyURI, ".pri").string().c_str(), true, new Base64Decoder);
287  // file.TransferTo(bytes);
288  // bytes.MessageEnd();
289  // RSA::PrivateKey privateKey;
290  // privateKey.Load(bytes);
291  // RSAES_PKCS1v15_Decryptor decryptor(privateKey);
292 
293  // OBufferStream os;
294  // StringSource(data, dataLength, true, new PK_DecryptorFilter(rng, decryptor, new FileSink(os)));
295 
296  // return os.buf();
297  // }
298  // catch (CryptoPP::Exception& e){
299  // throw Error(e.what());
300  // }
301  // }
302  // else
303  // {
304  // throw Error("Symmetric encryption is not implemented!");
305  // // if (!doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
306  // // throw Error("symmetric key doesn't exist");
307 
308  // // try{
309  // // string keyBits;
310  // // string symKeyFileName = m_impl->nameTransform(keyURI, ".key");
311  // // FileSource(symKeyFileName, true, new HexDecoder(new StringSink(keyBits)));
312 
313  // // using CryptoPP::AES;
314  // // AutoSeededRandomPool rnd;
315  // // byte iv[AES::BLOCKSIZE];
316  // // rnd.GenerateBlock(iv, AES::BLOCKSIZE);
317 
318  // // CFB_Mode<AES>::Decryption decryptor;
319  // // decryptor.SetKeyWithIV(reinterpret_cast<const uint8_t*>(keyBits.c_str()), keyBits.size(), iv);
320 
321  // // OBufferStream os;
322  // // StringSource(data, dataLength, true, new StreamTransformationFilter(decryptor,new FileSink(os)));
323  // // return os.buf();
324 
325  // // }catch (CryptoPP::Exception& e){
326  // // throw Error(e.what());
327  // // }
328  // }
329 }
330 
332 SecTpmFile::encryptInTpm(const uint8_t* data, size_t dataLength,
333  const Name& keyName, bool isSymmetric)
334 {
335  throw Error("SecTpmFile::encryptInTpm is not supported!");
336  // string keyURI = keyName.toUri();
337 
338  // if (!isSymmetric)
339  // {
340  // if (!doesKeyExistInTpm(keyName, KEY_CLASS_PUBLIC))
341  // throw Error("public key doesn't exist");
342  // try
343  // {
344  // using namespace CryptoPP;
345  // AutoSeededRandomPool rng;
346 
347  // //Read private key
348  // ByteQueue bytes;
349  // FileSource file(m_impl->nameTransform(keyURI, ".pub").string().c_str(), true, new Base64Decoder);
350  // file.TransferTo(bytes);
351  // bytes.MessageEnd();
352  // RSA::PublicKey publicKey;
353  // publicKey.Load(bytes);
354 
355  // OBufferStream os;
356  // RSAES_PKCS1v15_Encryptor encryptor(publicKey);
357 
358  // StringSource(data, dataLength, true, new PK_EncryptorFilter(rng, encryptor, new FileSink(os)));
359  // return os.buf();
360  // }
361  // catch (CryptoPP::Exception& e){
362  // throw Error(e.what());
363  // }
364  // }
365  // else
366  // {
367  // throw Error("Symmetric encryption is not implemented!");
368  // // if (!doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
369  // // throw Error("symmetric key doesn't exist");
370 
371  // // try{
372  // // string keyBits;
373  // // string symKeyFileName = m_impl->nameTransform(keyURI, ".key");
374  // // FileSource(symKeyFileName, true, new HexDecoder(new StringSink(keyBits)));
375 
376  // // using CryptoPP::AES;
377  // // AutoSeededRandomPool rnd;
378  // // byte iv[AES::BLOCKSIZE];
379  // // rnd.GenerateBlock(iv, AES::BLOCKSIZE);
380 
381  // // CFB_Mode<AES>::Encryption encryptor;
382  // // encryptor.SetKeyWithIV(reinterpret_cast<const uint8_t*>(keyBits.c_str()), keyBits.size(), iv);
383 
384  // // OBufferStream os;
385  // // StringSource(data, dataLength, true, new StreamTransformationFilter(encryptor, new FileSink(os)));
386  // // return os.buf();
387  // // }catch (CryptoPP::Exception& e){
388  // // throw Error(e.what());
389  // // }
390  // }
391 }
392 
393 
394 void
395 SecTpmFile::generateSymmetricKeyInTpm(const Name& keyName, KeyType keyType, int keySize)
396 {
397  throw Error("SecTpmFile::generateSymmetricKeyInTpm is not supported!");
398  // string keyURI = keyName.toUri();
399 
400  // if (doesKeyExistInTpm(keyName, KEY_CLASS_SYMMETRIC))
401  // throw Error("symmetric key exists");
402 
403  // string keyFileName = m_impl->maintainMapping(keyURI);
404  // string symKeyFileName = keyFileName + ".key";
405 
406  // try{
407  // switch (keyType){
408  // case KEY_TYPE_AES:
409  // {
410  // using namespace CryptoPP;
411  // AutoSeededRandomPool rng;
412 
413  // SecByteBlock key(0x00, keySize);
414  // rng.GenerateBlock(key, keySize);
415 
416  // StringSource(key, key.size(), true, new HexEncoder(new FileSink(symKeyFileName.c_str())));
417 
418  // chmod(symKeyFileName.c_str(), 0000400);
419  // return;
420  // }
421  // default:
422  // throw Error("Unsupported symmetric key type!");
423  // }
424  // }catch (CryptoPP::Exception& e){
425  // throw Error(e.what());
426  // }
427 }
428 
429 bool
430 SecTpmFile::doesKeyExistInTpm(const Name& keyName, KeyClass keyClass)
431 {
432  string keyURI = keyName.toUri();
433  if (keyClass == KEY_CLASS_PUBLIC)
434  {
435  if (boost::filesystem::exists(m_impl->nameTransform(keyURI, ".pub")))
436  return true;
437  else
438  return false;
439  }
440  if (keyClass == KEY_CLASS_PRIVATE)
441  {
442  if (boost::filesystem::exists(m_impl->nameTransform(keyURI, ".pri")))
443  return true;
444  else
445  return false;
446  }
447  if (keyClass == KEY_CLASS_SYMMETRIC)
448  {
449  if (boost::filesystem::exists(m_impl->nameTransform(keyURI, ".key")))
450  return true;
451  else
452  return false;
453  }
454  return false;
455 }
456 
457 bool
458 SecTpmFile::generateRandomBlock(uint8_t* res, size_t size)
459 {
460  try
461  {
462  CryptoPP::AutoSeededRandomPool rng;
463  rng.GenerateBlock(res, size);
464  return true;
465  }
466  catch (CryptoPP::Exception& e)
467  {
468  return false;
469  }
470 }
471 
472 } // namespace ndn
boost::filesystem::path m_keystorePath
Class implementing interface similar to ostringstream, but to construct ndn::Buffer.
Definition: buffer.hpp:176
virtual void generateSymmetricKeyInTpm(const Name &keyName, KeyType keyType, int keySize)
Generate a symmetric key.
virtual bool doesKeyExistInTpm(const Name &keyName, KeyClass keyClass)
Check if a particular key exists.
Class representing wire element of the NDN packet.
Definition: block.hpp:26
std::string toUri() const
Encode this name as a URI.
Definition: name.hpp:536
ptr_lib::shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:17
virtual void deleteKeyPairInTpm(const Name &keyName)
Delete a key pair of asymmetric keys.
virtual shared_ptr< PublicKey > getPublicKeyFromTpm(const Name &keyName)
Get a public key.
boost::filesystem::path nameTransform(const string &keyName, const string &extension)
virtual ConstBufferPtr decryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Decrypt data.
ptr_lib::shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
Definition: buffer.hpp:192
virtual bool generateRandomBlock(uint8_t *res, size_t size)
Generate a random block.
A Name holds an array of Name::Component and represents an NDN name.
Definition: name.hpp:26
virtual ConstBufferPtr exportPrivateKeyPkcs8FromTpm(const Name &keyName)
Export a private key in PKCS#8 format.
string maintainMapping(const string &keyName)
virtual Block signInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, DigestAlgorithm digestAlgorithm)
Sign data.
virtual bool importPublicKeyPkcs1IntoTpm(const Name &keyName, const uint8_t *buf, size_t size)
Import a public key in PKCS#1 format.
virtual ConstBufferPtr encryptInTpm(const uint8_t *data, size_t dataLength, const Name &keyName, bool isSymmetric)
Encrypt data.
void trim(std::string &str)
Modify str in place to erase whitespace on the left and right.
virtual bool importPrivateKeyPkcs8IntoTpm(const Name &keyName, const uint8_t *buf, size_t size)
Import a private key in PKCS#8 format.
Impl(const string &dir)
virtual void generateKeyPairInTpm(const Name &keyName, KeyType keyType, int keySize)
Generate a pair of asymmetric keys.