All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sec-tpm.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
8 #include "sec-tpm.hpp"
9 
10 #include "cryptopp.hpp"
11 
12 using namespace std;
13 
14 namespace ndn {
15 
17 SecTpm::exportPrivateKeyPkcs5FromTpm(const Name& keyName, const string& passwordStr)
18 {
19  using namespace CryptoPP;
20 
21  uint8_t salt[8] = {0};
22  uint8_t iv[8] = {0};
23 
24  // derive key
25  if (!generateRandomBlock(salt, 8) || !generateRandomBlock(iv, 8))
26  throw Error("Cannot generate salt or iv");
27 
28  uint32_t iterationCount = 2048;
29 
30  PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
31  size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
32  byte derived[24] = {0};
33  byte purpose = 0;
34 
35  try
36  {
37  keyGenerator.DeriveKey(derived, derivedLen, purpose,
38  reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
39  salt, 8, iterationCount);
40  }
41  catch (CryptoPP::Exception& e)
42  {
43  throw Error("Cannot derived the encryption key");
44  }
45 
46  //encrypt
47  CBC_Mode< DES_EDE3 >::Encryption e;
48  e.SetKeyWithIV(derived, derivedLen, iv);
49 
50  ConstBufferPtr pkcs8PrivateKey = exportPrivateKeyPkcs8FromTpm(keyName);
51  if (!static_cast<bool>(pkcs8PrivateKey))
52  throw Error("Cannot export the private key, #1");
53 
54  OBufferStream encryptedOs;
55  try
56  {
57  StringSource stringSource(pkcs8PrivateKey->buf(), pkcs8PrivateKey->size(), true,
58  new StreamTransformationFilter(e, new FileSink(encryptedOs)));
59  }
60  catch (CryptoPP::Exception& e)
61  {
62  throw Error("Cannot export the private key, #2");
63  }
64 
65  //encode
66  OID pbes2Id("1.2.840.113549.1.5.13");
67  OID pbkdf2Id("1.2.840.113549.1.5.12");
68  OID pbes2encsId("1.2.840.113549.3.7");
69 
70  OBufferStream pkcs8Os;
71  try
72  {
73  FileSink sink(pkcs8Os);
74 
75  // EncryptedPrivateKeyInfo ::= SEQUENCE {
76  // encryptionAlgorithm EncryptionAlgorithmIdentifier,
77  // encryptedData OCTET STRING }
78  DERSequenceEncoder encryptedPrivateKeyInfo(sink);
79  {
80  // EncryptionAlgorithmIdentifier ::= SEQUENCE {
81  // algorithm OBJECT IDENTIFIER {{PBES2-id}},
82  // parameters SEQUENCE {{PBES2-params}} }
83  DERSequenceEncoder encryptionAlgorithm(encryptedPrivateKeyInfo);
84  {
85  pbes2Id.encode(encryptionAlgorithm);
86  // PBES2-params ::= SEQUENCE {
87  // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
88  // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
89  DERSequenceEncoder pbes2Params(encryptionAlgorithm);
90  {
91  // AlgorithmIdentifier ::= SEQUENCE {
92  // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
93  // parameters SEQUENCE {{PBKDF2-params}} }
94  DERSequenceEncoder pbes2KDFs(pbes2Params);
95  {
96  pbkdf2Id.encode(pbes2KDFs);
97  // AlgorithmIdentifier ::= SEQUENCE {
98  // salt OCTET STRING,
99  // iterationCount INTEGER (1..MAX),
100  // keyLength INTEGER (1..MAX) OPTIONAL,
101  // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
102  DERSequenceEncoder pbkdf2Params(pbes2KDFs);
103  {
104  DEREncodeOctetString(pbkdf2Params, salt, 8);
105  DEREncodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
106  }
107  pbkdf2Params.MessageEnd();
108  }
109  pbes2KDFs.MessageEnd();
110 
111  // AlgorithmIdentifier ::= SEQUENCE {
112  // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
113  // parameters OCTET STRING} {{iv}} }
114  DERSequenceEncoder pbes2Encs(pbes2Params);
115  {
116  pbes2encsId.encode(pbes2Encs);
117  DEREncodeOctetString(pbes2Encs, iv, 8);
118  }
119  pbes2Encs.MessageEnd();
120  }
121  pbes2Params.MessageEnd();
122  }
123  encryptionAlgorithm.MessageEnd();
124 
125  DEREncodeOctetString(encryptedPrivateKeyInfo,
126  encryptedOs.buf()->buf(), encryptedOs.buf()->size());
127  }
128  encryptedPrivateKeyInfo.MessageEnd();
129 
130  return pkcs8Os.buf();
131  }
132  catch (CryptoPP::Exception& e)
133  {
134  throw Error("Cannot export the private key, #3");
135  }
136 }
137 
138 bool
139 SecTpm::importPrivateKeyPkcs5IntoTpm(const Name& keyName,
140  const uint8_t* buf, size_t size,
141  const string& passwordStr)
142 {
143  using namespace CryptoPP;
144 
145  OID pbes2Id;
146  OID pbkdf2Id;
147  SecByteBlock saltBlock;
148  uint32_t iterationCount;
149  OID pbes2encsId;
150  SecByteBlock ivBlock;
151  SecByteBlock encryptedDataBlock;
152 
153  try
154  {
155  // decode some decoding processes are not necessary for now,
156  // because we assume only one encryption scheme.
157  StringSource source(buf, size, true);
158 
159  // EncryptedPrivateKeyInfo ::= SEQUENCE {
160  // encryptionAlgorithm EncryptionAlgorithmIdentifier,
161  // encryptedData OCTET STRING }
162  BERSequenceDecoder encryptedPrivateKeyInfo(source);
163  {
164  // EncryptionAlgorithmIdentifier ::= SEQUENCE {
165  // algorithm OBJECT IDENTIFIER {{PBES2-id}},
166  // parameters SEQUENCE {{PBES2-params}} }
167  BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo);
168  {
169  pbes2Id.decode(encryptionAlgorithm);
170  // PBES2-params ::= SEQUENCE {
171  // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
172  // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
173  BERSequenceDecoder pbes2Params(encryptionAlgorithm);
174  {
175  // AlgorithmIdentifier ::= SEQUENCE {
176  // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
177  // parameters SEQUENCE {{PBKDF2-params}} }
178  BERSequenceDecoder pbes2KDFs(pbes2Params);
179  {
180  pbkdf2Id.decode(pbes2KDFs);
181  // AlgorithmIdentifier ::= SEQUENCE {
182  // salt OCTET STRING,
183  // iterationCount INTEGER (1..MAX),
184  // keyLength INTEGER (1..MAX) OPTIONAL,
185  // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
186  BERSequenceDecoder pbkdf2Params(pbes2KDFs);
187  {
188  BERDecodeOctetString(pbkdf2Params, saltBlock);
189  BERDecodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
190  }
191  pbkdf2Params.MessageEnd();
192  }
193  pbes2KDFs.MessageEnd();
194 
195  // AlgorithmIdentifier ::= SEQUENCE {
196  // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
197  // parameters OCTET STRING} {{iv}} }
198  BERSequenceDecoder pbes2Encs(pbes2Params);
199  {
200  pbes2encsId.decode(pbes2Encs);
201  BERDecodeOctetString(pbes2Encs, ivBlock);
202  }
203  pbes2Encs.MessageEnd();
204  }
205  pbes2Params.MessageEnd();
206  }
207  encryptionAlgorithm.MessageEnd();
208 
209  BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock);
210  }
211  encryptedPrivateKeyInfo.MessageEnd();
212  }
213  catch (CryptoPP::Exception& e)
214  {
215  return false;
216  }
217 
218 
219  PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
220  size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
221  byte derived[24] = {0};
222  byte purpose = 0;
223 
224  try
225  {
226  keyGenerator.DeriveKey(derived, derivedLen,
227  purpose,
228  reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
229  saltBlock.BytePtr(), saltBlock.size(),
230  iterationCount);
231  }
232  catch (CryptoPP::Exception& e)
233  {
234  return false;
235  }
236 
237  //decrypt
238  CBC_Mode< DES_EDE3 >::Decryption d;
239  d.SetKeyWithIV(derived, derivedLen, ivBlock.BytePtr());
240 
241  OBufferStream privateKeyOs;
242  try
243  {
244  StringSource encryptedSource(encryptedDataBlock.BytePtr(), encryptedDataBlock.size(), true,
245  new StreamTransformationFilter(d, new FileSink(privateKeyOs)));
246  }
247  catch (CryptoPP::Exception& e)
248  {
249  return false;
250  }
251 
252  if (!importPrivateKeyPkcs8IntoTpm(keyName,
253  privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()))
254  return false;
255 
256  //derive public key
257  OBufferStream publicKeyOs;
258 
259  try
260  {
261  RSA::PrivateKey privateKey;
262  privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref());
263  RSAFunction publicKey(privateKey);
264 
265  FileSink publicKeySink(publicKeyOs);
266  publicKey.DEREncode(publicKeySink);
267  publicKeySink.MessageEnd();
268  }
269  catch (CryptoPP::Exception& e)
270  {
271  return false;
272  }
273 
274  if (!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size()))
275  return false;
276 
277  return true;
278 }
279 
280 
281 } // namespace ndn
Class implementing interface similar to ostringstream, but to construct ndn::Buffer.
Definition: buffer.hpp:176
ptr_lib::shared_ptr< const Buffer > ConstBufferPtr
Definition: buffer.hpp:17
size_t size() const
Get the number of components.
Definition: name.hpp:329
A Name holds an array of Name::Component and represents an NDN name.
Definition: name.hpp:26
Definition: oid.hpp:20
void encode(CryptoPP::BufferedTransformation &out) const
Definition: oid.cpp:109