blob: 253ab0241e316a3e0556afd0e51f4e8f0e6d3013 [file] [log] [blame]
Yingdi Yu8dceb1d2014-02-18 12:45:10 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Yingdi Yu <yingdi@cs.ucla.edu>
5 * See COPYING for copyright and distribution information.
6 */
7
8#include "sec-tpm.hpp"
9
Junxiao Shi482ccc52014-03-31 13:05:24 -070010#include "cryptopp.hpp"
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080011
12using namespace std;
13
14namespace ndn {
15
16ConstBufferPtr
Yingdi Yu5e96e002014-04-23 18:32:15 -070017SecTpm::exportPrivateKeyPkcs5FromTpm(const Name& keyName, const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080018{
Yingdi Yu2e57a582014-02-20 23:34:43 -080019 using namespace CryptoPP;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070020
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080021 uint8_t salt[8] = {0};
22 uint8_t iv[8] = {0};
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070023
Yingdi Yu2e57a582014-02-20 23:34:43 -080024 // derive key
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070025 if (!generateRandomBlock(salt, 8) || !generateRandomBlock(iv, 8))
Yingdi Yu2e57a582014-02-20 23:34:43 -080026 throw Error("Cannot generate salt or iv");
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080027
Yingdi Yu2e57a582014-02-20 23:34:43 -080028 uint32_t iterationCount = 2048;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070029
Yingdi Yu2e57a582014-02-20 23:34:43 -080030 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
31 size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
32 byte derived[24] = {0};
33 byte purpose = 0;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070034
Yingdi Yu2e57a582014-02-20 23:34:43 -080035 try
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080036 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070037 keyGenerator.DeriveKey(derived, derivedLen, purpose,
38 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -080039 salt, 8, iterationCount);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080040 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070041 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -080042 {
43 throw Error("Cannot derived the encryption key");
44 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080045
Yingdi Yu2e57a582014-02-20 23:34:43 -080046 //encrypt
47 CBC_Mode< DES_EDE3 >::Encryption e;
48 e.SetKeyWithIV(derived, derivedLen, iv);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070049
Yingdi Yu5e96e002014-04-23 18:32:15 -070050 ConstBufferPtr pkcs8PrivateKey = exportPrivateKeyPkcs8FromTpm(keyName);
51 if (!static_cast<bool>(pkcs8PrivateKey))
Yingdi Yu2e57a582014-02-20 23:34:43 -080052 throw Error("Cannot export the private key, #1");
53
54 OBufferStream encryptedOs;
55 try
56 {
Yingdi Yu5e96e002014-04-23 18:32:15 -070057 StringSource stringSource(pkcs8PrivateKey->buf(), pkcs8PrivateKey->size(), true,
Yingdi Yu2e57a582014-02-20 23:34:43 -080058 new StreamTransformationFilter(e, new FileSink(encryptedOs)));
59 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070060 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -080061 {
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);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070074
Yingdi Yu2e57a582014-02-20 23:34:43 -080075 // 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();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700110
Yingdi Yu2e57a582014-02-20 23:34:43 -0800111 // 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();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700124
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700125 DEREncodeOctetString(encryptedPrivateKeyInfo,
126 encryptedOs.buf()->buf(), encryptedOs.buf()->size());
Yingdi Yu2e57a582014-02-20 23:34:43 -0800127 }
128 encryptedPrivateKeyInfo.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700129
Yingdi Yu2e57a582014-02-20 23:34:43 -0800130 return pkcs8Os.buf();
131 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700132 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800133 {
134 throw Error("Cannot export the private key, #3");
135 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800136}
137
138bool
Yingdi Yu5e96e002014-04-23 18:32:15 -0700139SecTpm::importPrivateKeyPkcs5IntoTpm(const Name& keyName,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700140 const uint8_t* buf, size_t size,
141 const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800142{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800143 using namespace CryptoPP;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700144
Yingdi Yu2e57a582014-02-20 23:34:43 -0800145 OID pbes2Id;
146 OID pbkdf2Id;
147 SecByteBlock saltBlock;
148 uint32_t iterationCount;
149 OID pbes2encsId;
150 SecByteBlock ivBlock;
151 SecByteBlock encryptedDataBlock;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700152
Yingdi Yu2e57a582014-02-20 23:34:43 -0800153 try
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800154 {
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700155 // decode some decoding processes are not necessary for now,
156 // because we assume only one encryption scheme.
Yingdi Yu2e57a582014-02-20 23:34:43 -0800157 StringSource source(buf, size, true);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700158
Yingdi Yu2e57a582014-02-20 23:34:43 -0800159 // EncryptedPrivateKeyInfo ::= SEQUENCE {
160 // encryptionAlgorithm EncryptionAlgorithmIdentifier,
161 // encryptedData OCTET STRING }
162 BERSequenceDecoder encryptedPrivateKeyInfo(source);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800163 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800164 // EncryptionAlgorithmIdentifier ::= SEQUENCE {
165 // algorithm OBJECT IDENTIFIER {{PBES2-id}},
166 // parameters SEQUENCE {{PBES2-params}} }
167 BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800168 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800169 pbes2Id.decode(encryptionAlgorithm);
170 // PBES2-params ::= SEQUENCE {
171 // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
172 // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
173 BERSequenceDecoder pbes2Params(encryptionAlgorithm);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800174 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800175 // AlgorithmIdentifier ::= SEQUENCE {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800176 // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
177 // parameters SEQUENCE {{PBKDF2-params}} }
178 BERSequenceDecoder pbes2KDFs(pbes2Params);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800179 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800180 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();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800192 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800193 pbes2KDFs.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700194
Yingdi Yu2e57a582014-02-20 23:34:43 -0800195 // 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();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800204 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800205 pbes2Params.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800206 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800207 encryptionAlgorithm.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800208
Yingdi Yu2e57a582014-02-20 23:34:43 -0800209 BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock);
210 }
211 encryptedPrivateKeyInfo.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800212 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700213 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800214 {
215 return false;
216 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800217
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700218
Yingdi Yu2e57a582014-02-20 23:34:43 -0800219 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
220 size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
221 byte derived[24] = {0};
222 byte purpose = 0;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700223
Yingdi Yu2e57a582014-02-20 23:34:43 -0800224 try
225 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700226 keyGenerator.DeriveKey(derived, derivedLen,
227 purpose,
228 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
229 saltBlock.BytePtr(), saltBlock.size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -0800230 iterationCount);
231 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700232 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800233 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800234 return false;
Yingdi Yu2e57a582014-02-20 23:34:43 -0800235 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800236
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700237 //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
Yingdi Yu5e96e002014-04-23 18:32:15 -0700252 if (!importPrivateKeyPkcs8IntoTpm(keyName,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700253 privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()))
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800254 return false;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700255
Yingdi Yu2e57a582014-02-20 23:34:43 -0800256 //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);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700264
Yingdi Yu2e57a582014-02-20 23:34:43 -0800265 FileSink publicKeySink(publicKeyOs);
266 publicKey.DEREncode(publicKeySink);
267 publicKeySink.MessageEnd();
268 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700269 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800270 {
271 return false;
272 }
273
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700274 if (!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size()))
Yingdi Yu2e57a582014-02-20 23:34:43 -0800275 return false;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700276
Yingdi Yu2e57a582014-02-20 23:34:43 -0800277 return true;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800278}
279
280
Yingdi Yufc40d872014-02-18 12:56:04 -0800281} // namespace ndn