blob: 14e71fa0ad57eb804f10547e89a371fc11f1e514 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu8dceb1d2014-02-18 12:45:10 -08002/**
Yingdi Yu99b2a002015-08-12 12:47:44 -07003 * Copyright (c) 2013-2016 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080022 */
23
24#include "sec-tpm.hpp"
25
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070026#include "../encoding/oid.hpp"
27#include "../encoding/buffer-stream.hpp"
Junxiao Shi482ccc52014-03-31 13:05:24 -070028#include "cryptopp.hpp"
Alexander Afanasyeva2ada222015-01-22 18:34:16 -080029#include <unistd.h>
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080030
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080031namespace ndn {
32
Yingdi Yu5ec0ee32014-06-24 16:26:09 -070033using std::string;
34
Yingdi Yu41546342014-11-30 23:37:53 -080035SecTpm::SecTpm(const string& location)
36 : m_location(location)
37{
38}
39
40SecTpm::~SecTpm()
41{
42}
43
44std::string
45SecTpm::getTpmLocator()
46{
Alexander Afanasyev07113802015-01-15 19:14:36 -080047 return this->getScheme() + ":" + m_location;
Yingdi Yu41546342014-11-30 23:37:53 -080048}
49
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080050ConstBufferPtr
Yingdi Yu5e96e002014-04-23 18:32:15 -070051SecTpm::exportPrivateKeyPkcs5FromTpm(const Name& keyName, const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080052{
Yingdi Yu2e57a582014-02-20 23:34:43 -080053 using namespace CryptoPP;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070054
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080055 uint8_t salt[8] = {0};
56 uint8_t iv[8] = {0};
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070057
Yingdi Yu2e57a582014-02-20 23:34:43 -080058 // derive key
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070059 if (!generateRandomBlock(salt, 8) || !generateRandomBlock(iv, 8))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070060 BOOST_THROW_EXCEPTION(Error("Cannot generate salt or iv"));
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080061
Yingdi Yu2e57a582014-02-20 23:34:43 -080062 uint32_t iterationCount = 2048;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070063
Yingdi Yu2e57a582014-02-20 23:34:43 -080064 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
Yingdi Yu99b2a002015-08-12 12:47:44 -070065 size_t derivedLen = 24; // For DES-EDE3-CBC-PAD
Yingdi Yu2e57a582014-02-20 23:34:43 -080066 byte derived[24] = {0};
67 byte purpose = 0;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070068
Yingdi Yu99b2a002015-08-12 12:47:44 -070069 try {
70 keyGenerator.DeriveKey(derived, derivedLen, purpose,
71 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
72 salt, 8, iterationCount);
73 }
74 catch (const CryptoPP::Exception& e) {
75 BOOST_THROW_EXCEPTION(Error("Cannot derived the encryption key"));
76 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -080077
Yingdi Yu99b2a002015-08-12 12:47:44 -070078 // encrypt
Yingdi Yu2e57a582014-02-20 23:34:43 -080079 CBC_Mode< DES_EDE3 >::Encryption e;
80 e.SetKeyWithIV(derived, derivedLen, iv);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070081
Yingdi Yu5e96e002014-04-23 18:32:15 -070082 ConstBufferPtr pkcs8PrivateKey = exportPrivateKeyPkcs8FromTpm(keyName);
Yingdi Yu9d9d5992014-06-25 12:25:16 -070083
Yingdi Yu99b2a002015-08-12 12:47:44 -070084 if (pkcs8PrivateKey == nullptr)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070085 BOOST_THROW_EXCEPTION(Error("Cannot export the private key, #1"));
Yingdi Yu2e57a582014-02-20 23:34:43 -080086
87 OBufferStream encryptedOs;
Yingdi Yu99b2a002015-08-12 12:47:44 -070088 try {
89 StringSource stringSource(pkcs8PrivateKey->buf(), pkcs8PrivateKey->size(), true,
90 new StreamTransformationFilter(e, new FileSink(encryptedOs)));
91 }
92 catch (const CryptoPP::Exception& e) {
93 BOOST_THROW_EXCEPTION(Error("Cannot export the private key, #2"));
94 }
Yingdi Yu2e57a582014-02-20 23:34:43 -080095
Yingdi Yu99b2a002015-08-12 12:47:44 -070096 // encode
Yingdi Yu2e57a582014-02-20 23:34:43 -080097 OID pbes2Id("1.2.840.113549.1.5.13");
98 OID pbkdf2Id("1.2.840.113549.1.5.12");
99 OID pbes2encsId("1.2.840.113549.3.7");
100
101 OBufferStream pkcs8Os;
Yingdi Yu99b2a002015-08-12 12:47:44 -0700102 try {
103 FileSink sink(pkcs8Os);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700104
Yingdi Yu99b2a002015-08-12 12:47:44 -0700105 // EncryptedPrivateKeyInfo ::= SEQUENCE {
106 // encryptionAlgorithm EncryptionAlgorithmIdentifier,
107 // encryptedData OCTET STRING }
108 DERSequenceEncoder encryptedPrivateKeyInfo(sink);
109 {
110 // EncryptionAlgorithmIdentifier ::= SEQUENCE {
111 // algorithm OBJECT IDENTIFIER {{PBES2-id}},
112 // parameters SEQUENCE {{PBES2-params}} }
113 DERSequenceEncoder encryptionAlgorithm(encryptedPrivateKeyInfo);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800114 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700115 pbes2Id.encode(encryptionAlgorithm);
116 // PBES2-params ::= SEQUENCE {
117 // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
118 // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
119 DERSequenceEncoder pbes2Params(encryptionAlgorithm);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800120 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700121 // AlgorithmIdentifier ::= SEQUENCE {
122 // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
123 // parameters SEQUENCE {{PBKDF2-params}} }
124 DERSequenceEncoder pbes2KDFs(pbes2Params);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800125 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700126 pbkdf2Id.encode(pbes2KDFs);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800127 // AlgorithmIdentifier ::= SEQUENCE {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700128 // salt OCTET STRING,
129 // iterationCount INTEGER (1..MAX),
130 // keyLength INTEGER (1..MAX) OPTIONAL,
131 // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
132 DERSequenceEncoder pbkdf2Params(pbes2KDFs);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800133 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700134 DEREncodeOctetString(pbkdf2Params, salt, 8);
135 DEREncodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
Yingdi Yu2e57a582014-02-20 23:34:43 -0800136 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700137 pbkdf2Params.MessageEnd();
Yingdi Yu2e57a582014-02-20 23:34:43 -0800138 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700139 pbes2KDFs.MessageEnd();
140
141 // AlgorithmIdentifier ::= SEQUENCE {
142 // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
143 // parameters OCTET STRING} {{iv}} }
144 DERSequenceEncoder pbes2Encs(pbes2Params);
145 {
146 pbes2encsId.encode(pbes2Encs);
147 DEREncodeOctetString(pbes2Encs, iv, 8);
148 }
149 pbes2Encs.MessageEnd();
Yingdi Yu2e57a582014-02-20 23:34:43 -0800150 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700151 pbes2Params.MessageEnd();
Yingdi Yu2e57a582014-02-20 23:34:43 -0800152 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700153 encryptionAlgorithm.MessageEnd();
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700154
Yingdi Yu99b2a002015-08-12 12:47:44 -0700155 DEREncodeOctetString(encryptedPrivateKeyInfo,
156 encryptedOs.buf()->buf(), encryptedOs.buf()->size());
Yingdi Yu2e57a582014-02-20 23:34:43 -0800157 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700158 encryptedPrivateKeyInfo.MessageEnd();
159
160 return pkcs8Os.buf();
161 }
162 catch (const CryptoPP::Exception& e) {
163 BOOST_THROW_EXCEPTION(Error("Cannot export the private key, #3"));
164 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800165}
166
167bool
Yingdi Yu5e96e002014-04-23 18:32:15 -0700168SecTpm::importPrivateKeyPkcs5IntoTpm(const Name& keyName,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700169 const uint8_t* buf, size_t size,
170 const string& passwordStr)
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800171{
Yingdi Yu2e57a582014-02-20 23:34:43 -0800172 using namespace CryptoPP;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700173
Yingdi Yu2e57a582014-02-20 23:34:43 -0800174 OID pbes2Id;
175 OID pbkdf2Id;
176 SecByteBlock saltBlock;
177 uint32_t iterationCount;
178 OID pbes2encsId;
179 SecByteBlock ivBlock;
180 SecByteBlock encryptedDataBlock;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700181
Yingdi Yu99b2a002015-08-12 12:47:44 -0700182 try {
183 // decode some decoding processes are not necessary for now,
184 // because we assume only one encryption scheme.
185 StringSource source(buf, size, true);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700186
Yingdi Yu99b2a002015-08-12 12:47:44 -0700187 // EncryptedPrivateKeyInfo ::= SEQUENCE {
188 // encryptionAlgorithm EncryptionAlgorithmIdentifier,
189 // encryptedData OCTET STRING }
190 BERSequenceDecoder encryptedPrivateKeyInfo(source);
191 {
192 // EncryptionAlgorithmIdentifier ::= SEQUENCE {
193 // algorithm OBJECT IDENTIFIER {{PBES2-id}},
194 // parameters SEQUENCE {{PBES2-params}} }
195 BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800196 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700197 pbes2Id.decode(encryptionAlgorithm);
198 // PBES2-params ::= SEQUENCE {
199 // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
200 // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
201 BERSequenceDecoder pbes2Params(encryptionAlgorithm);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800202 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700203 // AlgorithmIdentifier ::= SEQUENCE {
204 // algorithm OBJECT IDENTIFIER {{PBKDF2-id}},
205 // parameters SEQUENCE {{PBKDF2-params}} }
206 BERSequenceDecoder pbes2KDFs(pbes2Params);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800207 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700208 pbkdf2Id.decode(pbes2KDFs);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800209 // AlgorithmIdentifier ::= SEQUENCE {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700210 // salt OCTET STRING,
211 // iterationCount INTEGER (1..MAX),
212 // keyLength INTEGER (1..MAX) OPTIONAL,
213 // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
214 BERSequenceDecoder pbkdf2Params(pbes2KDFs);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800215 {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700216 BERDecodeOctetString(pbkdf2Params, saltBlock);
217 BERDecodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800218 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700219 pbkdf2Params.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800220 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700221 pbes2KDFs.MessageEnd();
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800222
Yingdi Yu99b2a002015-08-12 12:47:44 -0700223 // AlgorithmIdentifier ::= SEQUENCE {
224 // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}},
225 // parameters OCTET STRING} {{iv}} }
226 BERSequenceDecoder pbes2Encs(pbes2Params);
227 {
228 pbes2encsId.decode(pbes2Encs);
229 BERDecodeOctetString(pbes2Encs, ivBlock);
230 }
231 pbes2Encs.MessageEnd();
232 }
233 pbes2Params.MessageEnd();
Yingdi Yu2e57a582014-02-20 23:34:43 -0800234 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700235 encryptionAlgorithm.MessageEnd();
236
237 BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock);
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800238 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700239 encryptedPrivateKeyInfo.MessageEnd();
240 }
241 catch (const CryptoPP::Exception& e) {
242 return false;
243 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800244
Yingdi Yu2e57a582014-02-20 23:34:43 -0800245 PKCS5_PBKDF2_HMAC<SHA1> keyGenerator;
246 size_t derivedLen = 24; //For DES-EDE3-CBC-PAD
247 byte derived[24] = {0};
248 byte purpose = 0;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700249
Yingdi Yu99b2a002015-08-12 12:47:44 -0700250 try {
251 keyGenerator.DeriveKey(derived, derivedLen,
252 purpose,
253 reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(),
254 saltBlock.BytePtr(), saltBlock.size(),
255 iterationCount);
256 }
257 catch (const CryptoPP::Exception& e) {
258 return false;
259 }
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800260
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700261 //decrypt
262 CBC_Mode< DES_EDE3 >::Decryption d;
263 d.SetKeyWithIV(derived, derivedLen, ivBlock.BytePtr());
264
265 OBufferStream privateKeyOs;
Yingdi Yu99b2a002015-08-12 12:47:44 -0700266 try {
267 StringSource encryptedSource(encryptedDataBlock.BytePtr(), encryptedDataBlock.size(), true,
268 new StreamTransformationFilter(d, new FileSink(privateKeyOs)));
269 }
270 catch (const CryptoPP::Exception& e) {
271 return false;
272 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700273
Yingdi Yu5e96e002014-04-23 18:32:15 -0700274 if (!importPrivateKeyPkcs8IntoTpm(keyName,
Yingdi Yu4b8c6a22014-04-15 23:00:54 -0700275 privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()))
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800276 return false;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700277
Yingdi Yu99b2a002015-08-12 12:47:44 -0700278 // determine key type
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700279 StringSource privateKeySource(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size(), true);
280
Yingdi Yu99b2a002015-08-12 12:47:44 -0700281 KeyType publicKeyType = KeyType::NONE;
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700282 SecByteBlock rawKeyBits;
283 // PrivateKeyInfo ::= SEQUENCE {
284 // INTEGER,
285 // SEQUENCE,
286 // OCTECT STRING}
287 BERSequenceDecoder privateKeyInfo(privateKeySource);
288 {
289 uint32_t versionNum;
290 BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER);
291 BERSequenceDecoder sequenceDecoder(privateKeyInfo);
292 {
293 OID keyTypeOID;
294 keyTypeOID.decode(sequenceDecoder);
295 if (keyTypeOID == oid::RSA)
Yingdi Yu99b2a002015-08-12 12:47:44 -0700296 publicKeyType = KeyType::RSA;
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700297 else if (keyTypeOID == oid::ECDSA)
Yingdi Yu99b2a002015-08-12 12:47:44 -0700298 publicKeyType = KeyType::EC;
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700299 else
300 return false; // Unsupported key type;
301 }
302 }
303
304
Yingdi Yu99b2a002015-08-12 12:47:44 -0700305 // derive public key
Yingdi Yu2e57a582014-02-20 23:34:43 -0800306 OBufferStream publicKeyOs;
307
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700308 try {
309 switch (publicKeyType) {
Yingdi Yu99b2a002015-08-12 12:47:44 -0700310 case KeyType::RSA: {
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700311 RSA::PrivateKey privateKey;
312 privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref());
313 RSAFunction publicKey(privateKey);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700314
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700315 FileSink publicKeySink(publicKeyOs);
316 publicKey.DEREncode(publicKeySink);
317 publicKeySink.MessageEnd();
318 break;
319 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700320
321 case KeyType::EC: {
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700322 ECDSA<ECP, SHA256>::PrivateKey privateKey;
323 privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref());
324
325 ECDSA<ECP, SHA256>::PublicKey publicKey;
326 privateKey.MakePublicKey(publicKey);
327 publicKey.AccessGroupParameters().SetEncodeAsOID(true);
328
329 FileSink publicKeySink(publicKeyOs);
330 publicKey.DEREncode(publicKeySink);
331 publicKeySink.MessageEnd();
332 break;
333 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700334
335 default:
336 return false;
Yingdi Yu2e57a582014-02-20 23:34:43 -0800337 }
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700338 }
Yingdi Yu99b2a002015-08-12 12:47:44 -0700339 catch (const CryptoPP::Exception& e) {
340 return false;
Yingdi Yu9d9d5992014-06-25 12:25:16 -0700341 }
Yingdi Yu2e57a582014-02-20 23:34:43 -0800342
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700343 if (!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size()))
Yingdi Yu2e57a582014-02-20 23:34:43 -0800344 return false;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700345
Yingdi Yu2e57a582014-02-20 23:34:43 -0800346 return true;
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800347}
348
Yingdi Yu7036ce22014-06-19 18:53:37 -0700349bool
350SecTpm::getImpExpPassWord(std::string& password, const std::string& prompt)
351{
352 bool isInitialized = false;
353
Alexander Afanasyevcf3a6672015-02-01 20:33:22 -0800354#ifdef NDN_CXX_HAVE_GETPASS
Yingdi Yu99b2a002015-08-12 12:47:44 -0700355 char* pw0 = nullptr;
Yingdi Yu7036ce22014-06-19 18:53:37 -0700356
357 pw0 = getpass(prompt.c_str());
Yingdi Yu99b2a002015-08-12 12:47:44 -0700358 if (pw0 == nullptr)
Yingdi Yu7036ce22014-06-19 18:53:37 -0700359 return false;
360 std::string password1 = pw0;
361 memset(pw0, 0, strlen(pw0));
362
363 pw0 = getpass("Confirm:");
Yingdi Yu99b2a002015-08-12 12:47:44 -0700364 if (pw0 == nullptr) {
365 std::fill(password1.begin(), password1.end(), 0);
366 return false;
367 }
Yingdi Yu7036ce22014-06-19 18:53:37 -0700368
Yingdi Yu99b2a002015-08-12 12:47:44 -0700369 if (password1.compare(pw0) == 0) {
370 isInitialized = true;
371 password.swap(password1);
372 }
Yingdi Yu7036ce22014-06-19 18:53:37 -0700373
374 std::fill(password1.begin(), password1.end(), 0);
375 memset(pw0, 0, strlen(pw0));
376
377 if (password.empty())
378 return false;
379
Alexander Afanasyeva2ada222015-01-22 18:34:16 -0800380#endif // NDN_CXX_HAVE_GETPASS
381
Yingdi Yu7036ce22014-06-19 18:53:37 -0700382 return isInitialized;
383}
384
Yingdi Yu8dceb1d2014-02-18 12:45:10 -0800385
Yingdi Yufc40d872014-02-18 12:56:04 -0800386} // namespace ndn