blob: 3638ca13aa68a021368f9122116d84da9f58e966 [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 Yube4150e2014-02-18 13:02:46 -080017SecTpm::exportPrivateKeyPkcs8FromTpm(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 Yu2e57a582014-02-20 23:34:43 -080050 ConstBufferPtr pkcs1PrivateKey = exportPrivateKeyPkcs1FromTpm(keyName);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070051 if (!static_cast<bool>(pkcs1PrivateKey))
Yingdi Yu2e57a582014-02-20 23:34:43 -080052 throw Error("Cannot export the private key, #1");
53
54 OBufferStream encryptedOs;
55 try
56 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070057 StringSource stringSource(pkcs1PrivateKey->buf(), pkcs1PrivateKey->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 Yu2e57a582014-02-20 23:34:43 -0800125 DEREncodeOctetString(encryptedPrivateKeyInfo, encryptedOs.buf()->buf(), encryptedOs.buf()->size());
126 }
127 encryptedPrivateKeyInfo.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700128
Yingdi Yu2e57a582014-02-20 23:34:43 -0800129 return pkcs8Os.buf();
130 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700131 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800132 {
133 throw Error("Cannot export the private key, #3");
134 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800135}
136
137bool
Yingdi Yube4150e2014-02-18 13:02:46 -0800138SecTpm::importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800139{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800140 using namespace CryptoPP;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700141
Yingdi Yu2e57a582014-02-20 23:34:43 -0800142 OID pbes2Id;
143 OID pbkdf2Id;
144 SecByteBlock saltBlock;
145 uint32_t iterationCount;
146 OID pbes2encsId;
147 SecByteBlock ivBlock;
148 SecByteBlock encryptedDataBlock;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700149
Yingdi Yu2e57a582014-02-20 23:34:43 -0800150 try
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800151 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800152 //decode some decoding processes are not necessary for now, because we assume only one encryption scheme.
153 StringSource source(buf, size, true);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700154
Yingdi Yu2e57a582014-02-20 23:34:43 -0800155 // EncryptedPrivateKeyInfo ::= SEQUENCE {
156 // encryptionAlgorithm EncryptionAlgorithmIdentifier,
157 // encryptedData OCTET STRING }
158 BERSequenceDecoder encryptedPrivateKeyInfo(source);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800159 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800160 // EncryptionAlgorithmIdentifier ::= SEQUENCE {
161 // algorithm OBJECT IDENTIFIER {{PBES2-id}},
162 // parameters SEQUENCE {{PBES2-params}} }
163 BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800164 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800165 pbes2Id.decode(encryptionAlgorithm);
166 // PBES2-params ::= SEQUENCE {
167 // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
168 // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
169 BERSequenceDecoder pbes2Params(encryptionAlgorithm);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800170 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800171 // AlgorithmIdentifier ::= SEQUENCE {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800172 // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
173 // parameters SEQUENCE {{PBKDF2-params}} }
174 BERSequenceDecoder pbes2KDFs(pbes2Params);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800175 {
Yingdi Yu2e57a582014-02-20 23:34:43 -0800176 pbkdf2Id.decode(pbes2KDFs);
177 // AlgorithmIdentifier ::= SEQUENCE {
178 // salt OCTET STRING,
179 // iterationCount INTEGER (1..MAX),
180 // keyLength INTEGER (1..MAX) OPTIONAL,
181 // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
182 BERSequenceDecoder pbkdf2Params(pbes2KDFs);
183 {
184 BERDecodeOctetString(pbkdf2Params, saltBlock);
185 BERDecodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
186 }
187 pbkdf2Params.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800188 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800189 pbes2KDFs.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700190
Yingdi Yu2e57a582014-02-20 23:34:43 -0800191 // AlgorithmIdentifier ::= SEQUENCE {
192 // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
193 // parameters OCTET STRING} {{iv}} }
194 BERSequenceDecoder pbes2Encs(pbes2Params);
195 {
196 pbes2encsId.decode(pbes2Encs);
197 BERDecodeOctetString(pbes2Encs, ivBlock);
198 }
199 pbes2Encs.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800200 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800201 pbes2Params.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800202 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800203 encryptionAlgorithm.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800204
Yingdi Yu2e57a582014-02-20 23:34:43 -0800205 BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock);
206 }
207 encryptedPrivateKeyInfo.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800208 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700209 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800210 {
211 return false;
212 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800213
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700214
Yingdi Yu2e57a582014-02-20 23:34:43 -0800215 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
216 size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
217 byte derived[24] = {0};
218 byte purpose = 0;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700219
Yingdi Yu2e57a582014-02-20 23:34:43 -0800220 try
221 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700222 keyGenerator.DeriveKey(derived, derivedLen,
223 purpose,
224 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
225 saltBlock.BytePtr(), saltBlock.size(),
Yingdi Yu2e57a582014-02-20 23:34:43 -0800226 iterationCount);
227 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700228 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800229 {
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800230 return false;
Yingdi Yu2e57a582014-02-20 23:34:43 -0800231 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800232
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700233 //decrypt
234 CBC_Mode< DES_EDE3 >::Decryption d;
235 d.SetKeyWithIV(derived, derivedLen, ivBlock.BytePtr());
236
237 OBufferStream privateKeyOs;
238 try
239 {
240 StringSource encryptedSource(encryptedDataBlock.BytePtr(), encryptedDataBlock.size(), true,
241 new StreamTransformationFilter(d, new FileSink(privateKeyOs)));
242 }
243 catch (CryptoPP::Exception& e)
244 {
245 return false;
246 }
247
248 if (!importPrivateKeyPkcs1IntoTpm(keyName, privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()))
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800249 return false;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700250
Yingdi Yu2e57a582014-02-20 23:34:43 -0800251 //derive public key
252 OBufferStream publicKeyOs;
253
254 try
255 {
256 RSA::PrivateKey privateKey;
257 privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref());
258 RSAFunction publicKey(privateKey);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700259
Yingdi Yu2e57a582014-02-20 23:34:43 -0800260 FileSink publicKeySink(publicKeyOs);
261 publicKey.DEREncode(publicKeySink);
262 publicKeySink.MessageEnd();
263 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700264 catch (CryptoPP::Exception& e)
Yingdi Yu2e57a582014-02-20 23:34:43 -0800265 {
266 return false;
267 }
268
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700269 if (!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size()))
Yingdi Yu2e57a582014-02-20 23:34:43 -0800270 return false;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700271
Yingdi Yu2e57a582014-02-20 23:34:43 -0800272 return true;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800273}
274
275
Yingdi Yufc40d872014-02-18 12:56:04 -0800276} // namespace ndn