blob: f93169d453237ea8249bed2e1c9cdd82588fe547 [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
10#include <cryptopp/rsa.h>
11#include <cryptopp/files.h>
12#include <cryptopp/base64.h>
13#include <cryptopp/hex.h>
14#include <cryptopp/osrng.h>
15#include <cryptopp/sha.h>
16#include <cryptopp/pssr.h>
17#include <cryptopp/modes.h>
18#include <cryptopp/pwdbased.h>
19#include <cryptopp/sha.h>
20#include <cryptopp/des.h>
21
22using namespace std;
23
24namespace ndn {
25
26ConstBufferPtr
Yingdi Yube4150e2014-02-18 13:02:46 -080027SecTpm::exportPrivateKeyPkcs8FromTpm(const Name& keyName, const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080028{
29 uint8_t salt[8] = {0};
30 uint8_t iv[8] = {0};
31
32 try{
33 using namespace CryptoPP;
34
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080035 // derive key
36 if(!generateRandomBlock(salt, 8))
37 return shared_ptr<Buffer>();
38
39 if(!generateRandomBlock(iv, 8))
40 return shared_ptr<Buffer>();
41
42 uint32_t iterationCount = 2048;
43
44 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
45 size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
46 byte derived[24] = {0};
47 byte purpose = 0;
48
49 keyGenerator.DeriveKey(derived, derivedLen,
50 purpose,
Yingdi Yube4150e2014-02-18 13:02:46 -080051 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080052 salt, 8,
Yingdi Yube4150e2014-02-18 13:02:46 -080053 iterationCount);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080054
55 //encrypt
56 CBC_Mode< DES_EDE3 >::Encryption e;
57 e.SetKeyWithIV(derived, derivedLen, iv);
58
59 string encrypted;
60 OBufferStream encryptedOs;
61 ConstBufferPtr pkcs1PrivateKey = exportPrivateKeyPkcs1FromTpm(keyName);
62 StringSource stringSource(pkcs1PrivateKey->buf(), pkcs1PrivateKey->size(), true,
63 new StreamTransformationFilter(e, new FileSink(encryptedOs)));
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 FileSink sink(pkcs8Os);
72
73 // EncryptedPrivateKeyInfo ::= SEQUENCE {
74 // encryptionAlgorithm EncryptionAlgorithmIdentifier,
75 // encryptedData OCTET STRING }
76 DERSequenceEncoder encryptedPrivateKeyInfo(sink);
77 {
78 // EncryptionAlgorithmIdentifier ::= SEQUENCE {
79 // algorithm OBJECT IDENTIFIER {{PBES2-id}},
80 // parameters SEQUENCE {{PBES2-params}} }
81 DERSequenceEncoder encryptionAlgorithm(encryptedPrivateKeyInfo);
82 {
83 pbes2Id.encode(encryptionAlgorithm);
84 // PBES2-params ::= SEQUENCE {
85 // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
86 // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
87 DERSequenceEncoder pbes2Params(encryptionAlgorithm);
88 {
89 // AlgorithmIdentifier ::= SEQUENCE {
90 // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
91 // parameters SEQUENCE {{PBKDF2-params}} }
92 DERSequenceEncoder pbes2KDFs(pbes2Params);
93 {
94 pbkdf2Id.encode(pbes2KDFs);
95 // AlgorithmIdentifier ::= SEQUENCE {
96 // salt OCTET STRING,
97 // iterationCount INTEGER (1..MAX),
98 // keyLength INTEGER (1..MAX) OPTIONAL,
99 // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
100 DERSequenceEncoder pbkdf2Params(pbes2KDFs);
101 {
102 DEREncodeOctetString(pbkdf2Params, salt, 8);
103 DEREncodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
104 }
105 pbkdf2Params.MessageEnd();
106 }
107 pbes2KDFs.MessageEnd();
108
109 // AlgorithmIdentifier ::= SEQUENCE {
110 // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
111 // parameters OCTET STRING} {{iv}} }
112 DERSequenceEncoder pbes2Encs(pbes2Params);
113 {
114 pbes2encsId.encode(pbes2Encs);
115 DEREncodeOctetString(pbes2Encs, iv, 8);
116 }
117 pbes2Encs.MessageEnd();
118 }
119 pbes2Params.MessageEnd();
120 }
121 encryptionAlgorithm.MessageEnd();
122
123 DEREncodeOctetString(encryptedPrivateKeyInfo, encryptedOs.buf()->buf(), encryptedOs.buf()->size());
124 }
125 encryptedPrivateKeyInfo.MessageEnd();
126
127 return pkcs8Os.buf();
128 }catch(...){
129 return shared_ptr<Buffer>();
130 }
131}
132
133bool
Yingdi Yube4150e2014-02-18 13:02:46 -0800134SecTpm::importPrivateKeyPkcs8IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800135{
136 try{
137 using namespace CryptoPP;
138
139 OID pbes2Id;
140 OID pbkdf2Id;
141 SecByteBlock saltBlock;
142 uint32_t iterationCount;
143 OID pbes2encsId;
144 SecByteBlock ivBlock;
145 SecByteBlock encryptedDataBlock;
146
147 //decode some decoding processes are not necessary for now, because we assume only one encryption scheme.
148 StringSource source(buf, size, true);
149
150 // EncryptedPrivateKeyInfo ::= SEQUENCE {
151 // encryptionAlgorithm EncryptionAlgorithmIdentifier,
152 // encryptedData OCTET STRING }
153 BERSequenceDecoder encryptedPrivateKeyInfo(source);
154 {
155 // EncryptionAlgorithmIdentifier ::= SEQUENCE {
156 // algorithm OBJECT IDENTIFIER {{PBES2-id}},
157 // parameters SEQUENCE {{PBES2-params}} }
158 BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo);
159 {
160 pbes2Id.decode(encryptionAlgorithm);
161 // PBES2-params ::= SEQUENCE {
162 // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
163 // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
164 BERSequenceDecoder pbes2Params(encryptionAlgorithm);
165 {
166 // AlgorithmIdentifier ::= SEQUENCE {
167 // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
168 // parameters SEQUENCE {{PBKDF2-params}} }
169 BERSequenceDecoder pbes2KDFs(pbes2Params);
170 {
171 pbkdf2Id.decode(pbes2KDFs);
172 // AlgorithmIdentifier ::= SEQUENCE {
173 // salt OCTET STRING,
174 // iterationCount INTEGER (1..MAX),
175 // keyLength INTEGER (1..MAX) OPTIONAL,
176 // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
177 BERSequenceDecoder pbkdf2Params(pbes2KDFs);
178 {
179 BERDecodeOctetString(pbkdf2Params, saltBlock);
180 BERDecodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
181 }
182 pbkdf2Params.MessageEnd();
183 }
184 pbes2KDFs.MessageEnd();
185
186 // AlgorithmIdentifier ::= SEQUENCE {
187 // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
188 // parameters OCTET STRING} {{iv}} }
189 BERSequenceDecoder pbes2Encs(pbes2Params);
190 {
191 pbes2encsId.decode(pbes2Encs);
192 BERDecodeOctetString(pbes2Encs, ivBlock);
193 }
194 pbes2Encs.MessageEnd();
195 }
196 pbes2Params.MessageEnd();
197 }
198 encryptionAlgorithm.MessageEnd();
199
200 BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock);
201 }
202 encryptedPrivateKeyInfo.MessageEnd();
203
204
205 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
206 size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
207 byte derived[24] = {0};
208 byte purpose = 0;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800209
210 keyGenerator.DeriveKey(derived, derivedLen,
211 purpose,
Yingdi Yube4150e2014-02-18 13:02:46 -0800212 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800213 saltBlock.BytePtr(), saltBlock.size(),
214 iterationCount);
215
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800216
217 //decrypt
218 CBC_Mode< DES_EDE3 >::Decryption d;
219 d.SetKeyWithIV(derived, derivedLen, ivBlock.BytePtr());
220
221 OBufferStream privateKeyOs;
222 StringSource encryptedSource(encryptedDataBlock.BytePtr(), encryptedDataBlock.size(), true,
223 new StreamTransformationFilter(d, new FileSink(privateKeyOs)));
224
225 if(!importPrivateKeyPkcs1IntoTpm(keyName, privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()))
226 return false;
227
228 //derive public key
229 RSA::PrivateKey privateKey;
230 privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref());
231
232 RSAFunction publicKey(privateKey);
233
234 OBufferStream publicKeyOs;
235 FileSink publicKeySink(publicKeyOs);
236 publicKey.DEREncode(publicKeySink);
237 publicKeySink.MessageEnd();
238
239 if(!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size()))
240 return false;
241
242 return true;
243 }catch(std::runtime_error& e){
244 cerr << e.what() << endl;
245 return false;
246 }
247}
248
249
Yingdi Yufc40d872014-02-18 12:56:04 -0800250} // namespace ndn