blob: b0386884733501c519e367315126a50df79aaba0 [file] [log] [blame]
Yingdi Yu8dceb1d2014-02-18 12:45:10 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080013 */
14
15#include "sec-tpm.hpp"
16
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070017#include "../encoding/oid.hpp"
18#include "../encoding/buffer-stream.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070019#include "cryptopp.hpp"
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080020
21using namespace std;
22
23namespace ndn {
24
25ConstBufferPtr
Yingdi Yu5e96e002014-04-23 18:32:15 -070026SecTpm::exportPrivateKeyPkcs5FromTpm(const Name& keyName, const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080027{
Yingdi Yu2e57a582014-02-20 23:34:43 -080028 using namespace CryptoPP;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070029
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080030 uint8_t salt[8] = {0};
31 uint8_t iv[8] = {0};
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070032
Yingdi Yu2e57a582014-02-20 23:34:43 -080033 // derive key
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070034 if (!generateRandomBlock(salt, 8) || !generateRandomBlock(iv, 8))
Yingdi Yu2e57a582014-02-20 23:34:43 -080035 throw Error("Cannot generate salt or iv");
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080036
Yingdi Yu2e57a582014-02-20 23:34:43 -080037 uint32_t iterationCount = 2048;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070038
Yingdi Yu2e57a582014-02-20 23:34:43 -080039 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
40 size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
41 byte derived[24] = {0};
42 byte purpose = 0;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070043
Yingdi Yu2e57a582014-02-20 23:34:43 -080044 try
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080045 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070046 keyGenerator.DeriveKey(derived, derivedLen, purpose,
47 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -080048 salt, 8, iterationCount);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080049 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070050 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -080051 {
52 throw Error("Cannot derived the encryption key");
53 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080054
Yingdi Yu2e57a582014-02-20 23:34:43 -080055 //encrypt
56 CBC_Mode< DES_EDE3 >::Encryption e;
57 e.SetKeyWithIV(derived, derivedLen, iv);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070058
Yingdi Yu5e96e002014-04-23 18:32:15 -070059 ConstBufferPtr pkcs8PrivateKey = exportPrivateKeyPkcs8FromTpm(keyName);
60 if (!static_cast<bool>(pkcs8PrivateKey))
Yingdi Yu2e57a582014-02-20 23:34:43 -080061 throw Error("Cannot export the private key, #1");
62
63 OBufferStream encryptedOs;
64 try
65 {
Yingdi Yu5e96e002014-04-23 18:32:15 -070066 StringSource stringSource(pkcs8PrivateKey->buf(), pkcs8PrivateKey->size(), true,
Yingdi Yu2e57a582014-02-20 23:34:43 -080067 new StreamTransformationFilter(e, new FileSink(encryptedOs)));
68 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070069 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -080070 {
71 throw Error("Cannot export the private key, #2");
72 }
73
74 //encode
75 OID pbes2Id("1.2.840.113549.1.5.13");
76 OID pbkdf2Id("1.2.840.113549.1.5.12");
77 OID pbes2encsId("1.2.840.113549.3.7");
78
79 OBufferStream pkcs8Os;
80 try
81 {
82 FileSink sink(pkcs8Os);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070083
Yingdi Yu2e57a582014-02-20 23:34:43 -080084 // EncryptedPrivateKeyInfo ::= SEQUENCE {
85 // encryptionAlgorithm EncryptionAlgorithmIdentifier,
86 // encryptedData OCTET STRING }
87 DERSequenceEncoder encryptedPrivateKeyInfo(sink);
88 {
89 // EncryptionAlgorithmIdentifier ::= SEQUENCE {
90 // algorithm OBJECT IDENTIFIER {{PBES2-id}},
91 // parameters SEQUENCE {{PBES2-params}} }
92 DERSequenceEncoder encryptionAlgorithm(encryptedPrivateKeyInfo);
93 {
94 pbes2Id.encode(encryptionAlgorithm);
95 // PBES2-params ::= SEQUENCE {
96 // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
97 // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
98 DERSequenceEncoder pbes2Params(encryptionAlgorithm);
99 {
100 // AlgorithmIdentifier ::= SEQUENCE {
101 // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
102 // parameters SEQUENCE {{PBKDF2-params}} }
103 DERSequenceEncoder pbes2KDFs(pbes2Params);
104 {
105 pbkdf2Id.encode(pbes2KDFs);
106 // AlgorithmIdentifier ::= SEQUENCE {
107 // salt OCTET STRING,
108 // iterationCount INTEGER (1..MAX),
109 // keyLength INTEGER (1..MAX) OPTIONAL,
110 // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
111 DERSequenceEncoder pbkdf2Params(pbes2KDFs);
112 {
113 DEREncodeOctetString(pbkdf2Params, salt, 8);
114 DEREncodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
115 }
116 pbkdf2Params.MessageEnd();
117 }
118 pbes2KDFs.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700119
Yingdi Yu2e57a582014-02-20 23:34:43 -0800120 // AlgorithmIdentifier ::= SEQUENCE {
121 // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
122 // parameters OCTET STRING} {{iv}} }
123 DERSequenceEncoder pbes2Encs(pbes2Params);
124 {
125 pbes2encsId.encode(pbes2Encs);
126 DEREncodeOctetString(pbes2Encs, iv, 8);
127 }
128 pbes2Encs.MessageEnd();
129 }
130 pbes2Params.MessageEnd();
131 }
132 encryptionAlgorithm.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700133
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700134 DEREncodeOctetString(encryptedPrivateKeyInfo,
135 encryptedOs.buf()->buf(), encryptedOs.buf()->size());
Yingdi Yu2e57a582014-02-20 23:34:43 -0800136 }
137 encryptedPrivateKeyInfo.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700138
Yingdi Yu2e57a582014-02-20 23:34:43 -0800139 return pkcs8Os.buf();
140 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700141 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800142 {
143 throw Error("Cannot export the private key, #3");
144 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800145}
146
147bool
Yingdi Yu5e96e002014-04-23 18:32:15 -0700148SecTpm::importPrivateKeyPkcs5IntoTpm(const Name& keyName,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700149 const uint8_t* buf, size_t size,
150 const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800151{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800152 using namespace CryptoPP;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700153
Yingdi Yu2e57a582014-02-20 23:34:43 -0800154 OID pbes2Id;
155 OID pbkdf2Id;
156 SecByteBlock saltBlock;
157 uint32_t iterationCount;
158 OID pbes2encsId;
159 SecByteBlock ivBlock;
160 SecByteBlock encryptedDataBlock;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700161
Yingdi Yu2e57a582014-02-20 23:34:43 -0800162 try
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800163 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700164 // decode some decoding processes are not necessary for now,
165 // because we assume only one encryption scheme.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800166 StringSource source(buf, size, true);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700167
Yingdi Yu2e57a582014-02-20 23:34:43 -0800168 // EncryptedPrivateKeyInfo ::= SEQUENCE {
169 // encryptionAlgorithm EncryptionAlgorithmIdentifier,
170 // encryptedData OCTET STRING }
171 BERSequenceDecoder encryptedPrivateKeyInfo(source);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800172 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800173 // EncryptionAlgorithmIdentifier ::= SEQUENCE {
174 // algorithm OBJECT IDENTIFIER {{PBES2-id}},
175 // parameters SEQUENCE {{PBES2-params}} }
176 BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800177 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800178 pbes2Id.decode(encryptionAlgorithm);
179 // PBES2-params ::= SEQUENCE {
180 // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
181 // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
182 BERSequenceDecoder pbes2Params(encryptionAlgorithm);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800183 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800184 // AlgorithmIdentifier ::= SEQUENCE {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800185 // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
186 // parameters SEQUENCE {{PBKDF2-params}} }
187 BERSequenceDecoder pbes2KDFs(pbes2Params);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800188 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800189 pbkdf2Id.decode(pbes2KDFs);
190 // AlgorithmIdentifier ::= SEQUENCE {
191 // salt OCTET STRING,
192 // iterationCount INTEGER (1..MAX),
193 // keyLength INTEGER (1..MAX) OPTIONAL,
194 // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
195 BERSequenceDecoder pbkdf2Params(pbes2KDFs);
196 {
197 BERDecodeOctetString(pbkdf2Params, saltBlock);
198 BERDecodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
199 }
200 pbkdf2Params.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800201 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800202 pbes2KDFs.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700203
Yingdi Yu2e57a582014-02-20 23:34:43 -0800204 // AlgorithmIdentifier ::= SEQUENCE {
205 // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
206 // parameters OCTET STRING} {{iv}} }
207 BERSequenceDecoder pbes2Encs(pbes2Params);
208 {
209 pbes2encsId.decode(pbes2Encs);
210 BERDecodeOctetString(pbes2Encs, ivBlock);
211 }
212 pbes2Encs.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800213 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800214 pbes2Params.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800215 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800216 encryptionAlgorithm.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800217
Yingdi Yu2e57a582014-02-20 23:34:43 -0800218 BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock);
219 }
220 encryptedPrivateKeyInfo.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800221 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700222 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800223 {
224 return false;
225 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800226
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700227
Yingdi Yu2e57a582014-02-20 23:34:43 -0800228 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
229 size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
230 byte derived[24] = {0};
231 byte purpose = 0;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700232
Yingdi Yu2e57a582014-02-20 23:34:43 -0800233 try
234 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700235 keyGenerator.DeriveKey(derived, derivedLen,
236 purpose,
237 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
238 saltBlock.BytePtr(), saltBlock.size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -0800239 iterationCount);
240 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700241 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800242 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800243 return false;
Yingdi Yu2e57a582014-02-20 23:34:43 -0800244 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800245
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700246 //decrypt
247 CBC_Mode< DES_EDE3 >::Decryption d;
248 d.SetKeyWithIV(derived, derivedLen, ivBlock.BytePtr());
249
250 OBufferStream privateKeyOs;
251 try
252 {
253 StringSource encryptedSource(encryptedDataBlock.BytePtr(), encryptedDataBlock.size(), true,
254 new StreamTransformationFilter(d, new FileSink(privateKeyOs)));
255 }
256 catch (CryptoPP::Exception& e)
257 {
258 return false;
259 }
260
Yingdi Yu5e96e002014-04-23 18:32:15 -0700261 if (!importPrivateKeyPkcs8IntoTpm(keyName,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700262 privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()))
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800263 return false;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700264
Yingdi Yu2e57a582014-02-20 23:34:43 -0800265 //derive public key
266 OBufferStream publicKeyOs;
267
268 try
269 {
270 RSA::PrivateKey privateKey;
271 privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref());
272 RSAFunction publicKey(privateKey);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700273
Yingdi Yu2e57a582014-02-20 23:34:43 -0800274 FileSink publicKeySink(publicKeyOs);
275 publicKey.DEREncode(publicKeySink);
276 publicKeySink.MessageEnd();
277 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700278 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800279 {
280 return false;
281 }
282
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700283 if (!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size()))
Yingdi Yu2e57a582014-02-20 23:34:43 -0800284 return false;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700285
Yingdi Yu2e57a582014-02-20 23:34:43 -0800286 return true;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800287}
288
289
Yingdi Yufc40d872014-02-18 12:56:04 -0800290} // namespace ndn