Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OTCachedKey.cpp
Go to the documentation of this file.
1 /************************************************************
2  *
3  * OTCachedKey.cpp
4  *
5  */
6 
7 /************************************************************
8  -----BEGIN PGP SIGNED MESSAGE-----
9  Hash: SHA1
10 
11  * OPEN TRANSACTIONS
12  *
13  * Financial Cryptography and Digital Cash
14  * Library, Protocol, API, Server, CLI, GUI
15  *
16  * -- Anonymous Numbered Accounts.
17  * -- Untraceable Digital Cash.
18  * -- Triple-Signed Receipts.
19  * -- Cheques, Vouchers, Transfers, Inboxes.
20  * -- Basket Currencies, Markets, Payment Plans.
21  * -- Signed, XML, Ricardian-style Contracts.
22  * -- Scripted smart contracts.
23  *
24  * Copyright (C) 2010-2013 by "Fellow Traveler" (A pseudonym)
25  *
26  * EMAIL:
28  *
29  * BITCOIN: 1NtTPVVjDsUfDWybS4BwvHpG2pdS9RnYyQ
30  *
31  * KEY FINGERPRINT (PGP Key in license file):
32  * 9DD5 90EB 9292 4B48 0484 7910 0308 00ED F951 BB8E
33  *
34  * OFFICIAL PROJECT WIKI(s):
35  * https://github.com/FellowTraveler/Moneychanger
36  * https://github.com/FellowTraveler/Open-Transactions/wiki
37  *
38  * WEBSITE:
39  * http://www.OpenTransactions.org/
40  *
41  * Components and licensing:
42  * -- Moneychanger..A Java client GUI.....LICENSE:.....GPLv3
43  * -- otlib.........A class library.......LICENSE:...LAGPLv3
44  * -- otapi.........A client API..........LICENSE:...LAGPLv3
45  * -- opentxs/ot....Command-line client...LICENSE:...LAGPLv3
46  * -- otserver......Server Application....LICENSE:....AGPLv3
47  * Github.com/FellowTraveler/Open-Transactions/wiki/Components
48  *
49  * All of the above OT components were designed and written by
50  * Fellow Traveler, with the exception of Moneychanger, which
51  * was contracted out to Vicky C ([email protected]).
52  * The open-source community has since actively contributed.
53  *
54  * -----------------------------------------------------
55  *
56  * LICENSE:
57  * This program is free software: you can redistribute it
58  * and/or modify it under the terms of the GNU Affero
59  * General Public License as published by the Free Software
60  * Foundation, either version 3 of the License, or (at your
61  * option) any later version.
62  *
63  * ADDITIONAL PERMISSION under the GNU Affero GPL version 3
64  * section 7: (This paragraph applies only to the LAGPLv3
65  * components listed above.) If you modify this Program, or
66  * any covered work, by linking or combining it with other
67  * code, such other code is not for that reason alone subject
68  * to any of the requirements of the GNU Affero GPL version 3.
69  * (==> This means if you are only using the OT API, then you
70  * don't have to open-source your code--only your changes to
71  * Open-Transactions itself must be open source. Similar to
72  * LGPLv3, except it applies to software-as-a-service, not
73  * just to distributing binaries.)
74  *
75  * Extra WAIVER for OpenSSL, Lucre, and all other libraries
76  * used by Open Transactions: This program is released under
77  * the AGPL with the additional exemption that compiling,
78  * linking, and/or using OpenSSL is allowed. The same is true
79  * for any other open source libraries included in this
80  * project: complete waiver from the AGPL is hereby granted to
81  * compile, link, and/or use them with Open-Transactions,
82  * according to their own terms, as long as the rest of the
83  * Open-Transactions terms remain respected, with regard to
84  * the Open-Transactions code itself.
85  *
86  * Lucre License:
87  * This code is also "dual-license", meaning that Ben Lau-
88  * rie's license must also be included and respected, since
89  * the code for Lucre is also included with Open Transactions.
90  * See Open-Transactions/src/otlib/lucre/LUCRE_LICENSE.txt
91  * The Laurie requirements are light, but if there is any
92  * problem with his license, simply remove the Lucre code.
93  * Although there are no other blind token algorithms in Open
94  * Transactions (yet. credlib is coming), the other functions
95  * will continue to operate.
96  * See Lucre on Github: https://github.com/benlaurie/lucre
97  * -----------------------------------------------------
98  * You should have received a copy of the GNU Affero General
99  * Public License along with this program. If not, see:
100  * http://www.gnu.org/licenses/
101  *
102  * If you would like to use this software outside of the free
103  * software license, please contact FellowTraveler.
104  * (Unfortunately many will run anonymously and untraceably,
105  * so who could really stop them?)
106  *
107  * DISCLAIMER:
108  * This program is distributed in the hope that it will be
109  * useful, but WITHOUT ANY WARRANTY; without even the implied
110  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
111  * PURPOSE. See the GNU Affero General Public License for
112  * more details.
113 
114  -----BEGIN PGP SIGNATURE-----
115  Version: GnuPG v1.4.9 (Darwin)
116 
117  iQIcBAEBAgAGBQJRSsfJAAoJEAMIAO35UbuOQT8P/RJbka8etf7wbxdHQNAY+2cC
118  vDf8J3X8VI+pwMqv6wgTVy17venMZJa4I4ikXD/MRyWV1XbTG0mBXk/7AZk7Rexk
119  KTvL/U1kWiez6+8XXLye+k2JNM6v7eej8xMrqEcO0ZArh/DsLoIn1y8p8qjBI7+m
120  aE7lhstDiD0z8mwRRLKFLN2IH5rAFaZZUvj5ERJaoYUKdn4c+RcQVei2YOl4T0FU
121  LWND3YLoH8naqJXkaOKEN4UfJINCwxhe5Ke9wyfLWLUO7NamRkWD2T7CJ0xocnD1
122  sjAzlVGNgaFDRflfIF4QhBx1Ddl6wwhJfw+d08bjqblSq8aXDkmFA7HeunSFKkdn
123  oIEOEgyj+veuOMRJC5pnBJ9vV+7qRdDKQWaCKotynt4sWJDGQ9kWGWm74SsNaduN
124  TPMyr9kNmGsfR69Q2Zq/FLcLX/j8ESxU+HYUB4vaARw2xEOu2xwDDv6jt0j3Vqsg
125  x7rWv4S/Eh18FDNDkVRChiNoOIilLYLL6c38uMf1pnItBuxP3uhgY6COm59kVaRh
126  nyGTYCDYD2TK+fI9o89F1297uDCwEJ62U0Q7iTDp5QuXCoxkPfv8/kX6lS6T3y9G
127  M9mqIoLbIQ1EDntFv7/t6fUTS2+46uCrdZWbQ5RjYXdrzjij02nDmJAm2BngnZvd
128  kamH0Y/n11lCvo1oQxM+
129  =uSzz
130  -----END PGP SIGNATURE-----
131  **************************************************************/
132 
133 #include "stdafx.hpp"
134 
135 #include "crypto/OTCachedKey.hpp"
136 #include "crypto/OTASCIIArmor.hpp"
138 #include "crypto/OTCrypto.hpp"
139 #include "OTIdentifier.hpp"
140 #include "crypto/OTKeyring.hpp"
141 #include "OTLog.hpp"
142 #include "crypto/OTPassword.hpp"
143 #include "crypto/OTPasswordData.hpp"
144 #include "crypto/OTSymmetricKey.hpp"
145 
146 #include <memory>
147 
148 #if defined(OT_CRYPTO_USING_OPENSSL)
149 extern "C" {
150 #include <openssl/opensslconf.h>
151 }
152 #endif
153 
154 #define OT_DEFAULT_PASSWORD "test"
155 
156 namespace opentxs
157 {
158 
159 std::mutex OTCachedKey::s_mutexThreadTimeout;
160 std::mutex OTCachedKey::s_mutexCachedKeys;
161 mapOfCachedKeys OTCachedKey::s_mapCachedKeys;
162 
164 {
165  std::lock_guard<std::mutex> lock(m_Mutex);
166 
167  bool bReturnVal = false;
168 
169  if (nullptr != m_pSymmetricKey) {
170  bReturnVal = m_pSymmetricKey->IsGenerated();
171  }
172 
173  return bReturnVal;
174 }
175 
177 {
178  std::lock_guard<std::mutex> lock(m_Mutex);
179 
180  bool bReturnVal = false;
181 
182  if (nullptr != m_pSymmetricKey) {
183  bReturnVal = m_pSymmetricKey->HasHashCheck();
184  }
185 
186  return bReturnVal;
187 }
188 
189 // if you pass in a master key ID, it will look it up on an existing cached map
190 // of master keys.
191 // Otherwise it will use "the" global Master Key (the one used for the Nyms.)
192 //
193 // static
194 std::shared_ptr<OTCachedKey> OTCachedKey::It(OTIdentifier* pIdentifier)
195 {
196  // For now we're only allowing a single global instance, unless you pass in
197  // an ID, in which case we keep a map.
198 
199  // Default is 0 ("you have to type your PW a million times"), but it's
200  // overridden in config file.
201  static std::shared_ptr<OTCachedKey> s_theSingleton(new OTCachedKey);
202 
203  if (nullptr == pIdentifier)
204  return s_theSingleton; // Notice if you pass nullptr (no args) then it
205  // ALWAYS returns a good pointer here.
206 
207  // There is a chance of failure if you pass an ID, since maybe it's not
208  // already on the map.
209  // But at least by this point we know FOR SURE that pIdentifier is NOT
210  // nullptr.
211  //
212  std::lock_guard<std::mutex> lock(OTCachedKey::s_mutexCachedKeys);
213 
214  const OTString strIdentifier(*pIdentifier);
215  const std::string str_identifier(strIdentifier.Get());
216 
217  auto it_keys = s_mapCachedKeys.find(str_identifier);
218 
219  if (s_mapCachedKeys.end() != it_keys) // found it!
220  {
221  std::shared_ptr<OTCachedKey> pShared(it_keys->second);
222 
223  if (pShared) {
224  return pShared;
225  }
226  else
227  s_mapCachedKeys.erase(it_keys);
228  }
229 
230  // else: We can't instantiate it, since we don't have the corresponding
231  // CachedKey, just its
232  // Identifier. We're forced simply to return nullptr in this case.
233  //
234  // Therefore you should normally pass in the master key (the same one that
235  // you want to cache a copy
236  // of) using the below version of It(). That version creates the copy, if
237  // it's not already there.
238  //
239  return std::shared_ptr<OTCachedKey>();
240 }
241 
242 // if you pass in a master key, it will look it up on an existing cached map of
243 // master keys,
244 // based on the ID of the master key passed in. (Where it stores its own cached
245 // copy of the same
246 // master key.)
247 // NOTE: If you use it this way, then you must NEVER use the actual master key
248 // being cached (such as
249 // the one stored in a password-protected purse.) Instead, you must always look
250 // up the cached version,
251 // and use THAT master key, instead of the actual one in your OTPurse. The only
252 // time
253 // you can use your master key itself is when loading it (such as when OTPurse
254 // loads
255 // its internal Master Key.) But thereafter, use the cached version of it for
256 // all operations
257 // and for saving.
258 
259 // Note: parameter no longer const due to need to lock its mutex.
260 // static
261 std::shared_ptr<OTCachedKey> OTCachedKey::It(OTCachedKey& theSourceKey)
262 {
263  // std::lock_guard<std::mutex> lock(*(theSourceKey.GetMutex()));
264 
265  // There is no chance of failure since he passed the master key itself,
266  // since even if it's not already on the map, we'll just create a copy and
267  // put
268  // it there ourselves, returning a pointer either way.
269  //
270  // Except... if theSourceKey isn't generated...
271  //
272  if (!(const_cast<OTCachedKey&>(theSourceKey))
273  .IsGenerated()) // it's only not const due to the mutex inside
274  {
275  otErr << "OTCachedKey::" << __FUNCTION__
276  << ": theSourceKey.IsGenerated() returned false. "
277  "(Returning nullptr.)\n";
278  return std::shared_ptr<OTCachedKey>();
279  }
280 
281  std::lock_guard<std::mutex> lock_keys(OTCachedKey::s_mutexCachedKeys);
282 
283  const OTIdentifier theSourceID(theSourceKey);
284 
285  const OTString strIdentifier(theSourceID);
286  const std::string str_identifier(strIdentifier.Get());
287 
288  // Let's see if it's already there on the map...
289  //
290  auto it_keys = s_mapCachedKeys.find(str_identifier);
291 
292  if (s_mapCachedKeys.end() != it_keys) // found it!
293  {
294  std::shared_ptr<OTCachedKey> pMaster(it_keys->second);
295 
296  if (pMaster)
297  return pMaster;
298  else
299  s_mapCachedKeys.erase(it_keys);
300  }
301 
302  // By this point, pMaster is definitely nullptr. (Not found on the map,
303  // needs
304  // to be added.)
305  //
306 
307  // Here we make a copy of the master key and insert it into the map.
308  // Then we return a pointer to it.
309  //
310  OTASCIIArmor ascCachedKey;
311  if ((const_cast<OTCachedKey&>(theSourceKey)).SerializeTo(
312  ascCachedKey)) // it's only not const due to the mutex inside
313  {
314  std::shared_ptr<OTCachedKey> pMaster(
315  new OTCachedKey); // int32_t nTimeoutSeconds=OT_MASTER_KEY_TIMEOUT;
316 
317  pMaster->SetCachedKey(ascCachedKey);
318 
319  s_mapCachedKeys.insert(
320  std::pair<std::string, std::shared_ptr<OTCachedKey>>(
321  str_identifier, pMaster)); // takes ownership here.
322  return pMaster;
323  }
324  // theSourceKey WAS generated, but SerializeTo FAILED? Very strange...
325  else
326  otErr << __FUNCTION__
327  << ": theSourceKey.SerializeTo(ascCachedKey) failed. "
328  "Returning nullptr.\n";
329 
330  return std::shared_ptr<OTCachedKey>();
331 }
332 
333 // static
335 {
336  std::lock_guard<std::mutex> lock(OTCachedKey::s_mutexCachedKeys);
337 
338  s_mapCachedKeys.clear();
339 
340  // while (!s_mapCachedKeys.empty())
341  // {
342  // OTCachedKey * pTemp = s_mapCachedKeys.begin()->second;
343  // OT_ASSERT(nullptr != pTemp);
344  // s_mapCachedKeys.erase(s_mapCachedKeys.begin());
345  // delete pTemp; pTemp = nullptr;
346  // }
347 }
348 
349 OTCachedKey::OTCachedKey(int32_t nTimeoutSeconds)
350  : m_pThread(nullptr)
351  , m_nTimeoutSeconds(nTimeoutSeconds)
352  , m_pMasterPassword(nullptr)
353  , // This is created in GetMasterPassword, and destroyed by a timer thread
354  // sometime soon after.
355  m_bUse_System_Keyring(false)
356  , // the config file might turn this on.
357  m_pSymmetricKey(nullptr)
358  , // OTServer OR OTWallet owns this key, and sets this pointer. It's the
359  // encrypted form of s_pMasterPassword.
360  m_bPaused(false)
361 {
362 }
363 
364 OTCachedKey::OTCachedKey(const OTASCIIArmor& ascCachedKey)
365  : m_pThread(nullptr)
366  , m_nTimeoutSeconds(OTCachedKey::It()->GetTimeoutSeconds())
367  , m_pMasterPassword(nullptr)
368  , // This is created in GetMasterPassword, and destroyed by a timer thread
369  // sometime soon after.
370  m_bUse_System_Keyring(OTCachedKey::It()->IsUsingSystemKeyring())
371  , // this master key instance will decide to use the system keyring based on
372  // what the global master key instance is set to do. (So we get the same
373  // settings from config file, etc.)
374  m_pSymmetricKey(nullptr)
375  , // OTServer OR OTWallet owns this key, and sets this pointer. It's the
376  // encrypted form of s_pMasterPassword.
377  m_bPaused(false)
378 {
379  OT_ASSERT(ascCachedKey.Exists());
380  SetCachedKey(ascCachedKey);
381 }
382 
383 // We don't lock the mutex here because otherwise we'll freeze ourselves.
384 //
385 // UPDATE: Adding lock since we now use recursive mutexes. SHOULD be fine.
386 // HMM, weird: it's still freezing here. Commenting this one out for now.
387 //
389 {
390  // std::lock_guard<std::mutex> lock(m_Mutex);
391 
392  return m_bPaused;
393 }
394 
395 // When the master key is on pause, it won't work (Nyms will just use their
396 // own passwords instead of the master password.) This is important, for
397 // example,
398 // if you are loading up a bunch of Old Nyms. You pause before and after each
399 // one,
400 // and THEN convert them to the master key.
401 //
403 {
404  std::lock_guard<std::mutex> lock(m_Mutex);
405 
406  if (!m_bPaused) {
407  m_bPaused = true;
408  return true;
409  }
410  return false;
411 }
412 
414 {
415  std::lock_guard<std::mutex> lock(m_Mutex);
416 
417  if (m_bPaused) {
418  m_bPaused = false;
419  return true;
420  }
421  return false;
422 }
423 
424 // This should ONLY be called from a function that locks the Mutex first!
425 //
426 // UPDATE: SHOULD be fine to lock the mutex since we now use recursive mutexes.
427 // However, I did verify that this function is only called in other functions
428 // that
429 // have already locked it, so I'm leaving the call out for now.
430 //
432 {
433  // NO NEED TO LOCK THIS ONE -- BUT ONLY CALL IT FROM A LOCKED FUNCTION.
434  if (nullptr != m_pThread) {
435  std::unique_ptr<std::thread> pThread(m_pThread);
436  m_pThread = nullptr;
437 
438  if (pThread->joinable()) {
439  pThread->detach();
440  }
441  }
442 }
443 
445 {
446  std::lock_guard<std::mutex> lock(
447  m_Mutex); // I figured this would cause some kind of problem but how
448  // else can I mess with the members unless I lock this?
449 
451 
452  if (nullptr != m_pMasterPassword) // Only stored temporarily, the purpose of
453  // this class is to destoy it after a timer.
454  {
455  OTPassword* pPassword = m_pMasterPassword;
456 
457  m_pMasterPassword = nullptr;
458 
459  delete pPassword;
460  pPassword = nullptr;
461  }
462 
463  if (nullptr !=
464  m_pSymmetricKey) // Owned / based on a string passed in. Stored
465  // somewhere else (OTServer, OTWallet...)
466  {
467  OTSymmetricKey* pSymmetricKey = m_pSymmetricKey;
468 
469  m_pSymmetricKey = nullptr;
470 
471  delete pSymmetricKey;
472  pSymmetricKey = nullptr;
473  }
474 }
475 
477 {
478  std::lock_guard<std::mutex> lock(m_Mutex);
479 
480  const int32_t nTimeout = m_nTimeoutSeconds;
481 
482  return nTimeout;
483 }
484 
485 void OTCachedKey::SetTimeoutSeconds(int32_t nTimeoutSeconds) // So we can load
486  // from the config
487  // file.
488 {
489  std::lock_guard<std::mutex> lock(m_Mutex);
490 
491  OT_ASSERT_MSG(nTimeoutSeconds >= (-1), "OTCachedKey::SetTimeoutSeconds: "
492  "ASSERT: nTimeoutSeconds must be >= "
493  "(-1)\n");
494 
495  m_nTimeoutSeconds = nTimeoutSeconds;
496 }
497 
498 // Called by OTServer or OTWallet, or whatever instantiates those.
499 //
500 void OTCachedKey::SetCachedKey(const OTASCIIArmor& ascCachedKey)
501 {
502  std::lock_guard<std::mutex> lock(m_Mutex);
503 
504  OT_ASSERT(ascCachedKey.Exists());
505 
506  if (nullptr != m_pSymmetricKey) {
507  otErr << "OTCachedKey::SetCachedKey: Warning: This was already set. "
508  "(Re-setting.)\n";
509 
510  OTSymmetricKey* pSymmetricKey = m_pSymmetricKey;
511 
512  m_pSymmetricKey = nullptr;
513 
514  delete pSymmetricKey;
515  pSymmetricKey = nullptr;
516  }
517 
518  m_pSymmetricKey = new OTSymmetricKey;
519  OT_ASSERT(nullptr != m_pSymmetricKey);
520 
521  // const bool bSerialized =
522  m_pSymmetricKey->SerializeFrom(ascCachedKey);
523 }
524 
525 // Above version deletes the internal symmetric key if it already exists,
526 // and then below that, creates it again if it does not exist. Then serializes
527 // it up from storage via ascCachedKey (input.)
528 // Whereas below version, if internal symmetric key doesn't exist, simply
529 // returns false. Therefore if it's "not generated" and you want to load it
530 // up from some input, call the above function, SetCachedKey().
531 
532 // Apparently SerializeFrom (as of this writing) is only used in OTEnvelope.cpp
533 // whereas SetCachedKey (above) is used in OTWallet and OTServer.
534 //
536 {
537  std::lock_guard<std::mutex> lock(m_Mutex);
538 
539  if (nullptr == m_pSymmetricKey) return false;
540 
541  return m_pSymmetricKey->SerializeFrom(ascInput);
542 }
543 
545 {
546  std::lock_guard<std::mutex> lock(m_Mutex);
547 
548  if (nullptr == m_pSymmetricKey) return false;
549 
550  return m_pSymmetricKey->SerializeTo(ascOutput);
551 }
552 
553 // Note: this calculates its ID based only on m_dataEncryptedKey,
554 // and does NOT include salt, IV, iteration count, etc when
555 // generating the hash for the ID.
556 //
557 bool OTCachedKey::GetIdentifier(OTIdentifier& theIdentifier) const
558 {
559  std::lock_guard<std::mutex> lock((const_cast<OTCachedKey*>(this))->m_Mutex);
560 
561  if ((nullptr == m_pSymmetricKey) || !m_pSymmetricKey->IsGenerated())
562  return false;
563 
564  m_pSymmetricKey->GetIdentifier(theIdentifier);
565  return true;
566 }
567 
568 bool OTCachedKey::GetIdentifier(OTString& strIdentifier) const
569 {
570  std::lock_guard<std::mutex> lock((const_cast<OTCachedKey*>(this))->m_Mutex);
571 
572  if ((nullptr == m_pSymmetricKey) || !m_pSymmetricKey->IsGenerated())
573  return false;
574 
575  m_pSymmetricKey->GetIdentifier(strIdentifier);
576  return true;
577 }
578 
579 /*
580  // TOdo: make this so you can pass in a password, or you can pass nullptr
581  // and then it will use the GetPasswordCallback() method to collect one
582  // from the user.
583 
584  OT_OPENSSL_CALLBACK * OTAsymmetricKey::GetPasswordCallback()
585 
586  #define OPENSSL_CALLBACK_FUNC(name) extern "C" (name)(char* buf, int32_t size,
587  int32_t rwflag, void* userdata)
588 
589  */
590 
591 // Caller must delete!
592 // static
593 std::shared_ptr<OTCachedKey> OTCachedKey::CreateMasterPassword(
594  OTPassword& theOutput, const char* szDisplay, int32_t nTimeoutSeconds)
595 {
596  std::shared_ptr<OTCachedKey> pMaster(new OTCachedKey(nTimeoutSeconds));
597 
598  const OTString strDisplay(
599  (nullptr == szDisplay)
600  ? "Creating a passphrase..."
601  : szDisplay); // todo internationalization / hardcoding.
602 
603  const bool bGotPassphrase =
604  pMaster->GetMasterPassword(pMaster, theOutput, strDisplay.Get(),
605  true); // bool bVerifyTwice=false by default.
606  // Really we didn't have to pass true
607  // here, since it asks twice anyway,
608  // when first generating the key.
609 
610  if (bGotPassphrase) // success!
611  return pMaster;
612 
613  // If we're still here, that means bGotPassphrase failed.
614  //
615  // delete pMaster; pMaster = nullptr;
616  return std::shared_ptr<OTCachedKey>();
617 }
618 
619 // Called by the password callback function.
620 // The password callback uses this to get the password for any individual Nym.
621 // This will also generate the master password, if one does not already exist.
622 //
623 bool OTCachedKey::GetMasterPassword(std::shared_ptr<OTCachedKey>& mySharedPtr,
624  OTPassword& theOutput,
625  const char* szDisplay, bool bVerifyTwice)
626 {
627  std::lock_guard<std::mutex> lock(m_Mutex);
628 
629  std::string str_display(
630  nullptr != szDisplay ? szDisplay : "(Display string was blank.)");
631 
632  const char* szFunc = "OTCachedKey::GetMasterPassword";
633 
634  // OT_ASSERT(nullptr != m_pSymmetricKey); // (This had better be set
635  // already.)
636  // // Took this out because calling Generate inside here now.
637 
638  //
639  if (nullptr != m_pMasterPassword) {
640  otInfo << szFunc
641  << ": Master password was available. (Returning it now.)\n";
642 
643  theOutput = *m_pMasterPassword;
644  return true;
645  }
646 
647  otInfo << szFunc << ": Master password wasn't loaded. Instantiating...\n";
648 
649  // If m_pMasterPassword is nullptr, (which below this point it is) then...
650  //
651  // Either it hasn't been created yet, in which case we need to instantiate
652  // it,
653  // OR it expired, in which case m_pMasterPassword is nullptr,
654  // but m_pThread isn't, and still needs cleaning up before we instantiate
655  // another one!
656  //
658 
659  m_pMasterPassword =
660  OTCrypto::It()->InstantiateBinarySecret(); // already asserts.
661 
662  /*
663  How does this work?
664 
665  When trying to open a normal nym, the password callback realizes we are
666  calling it
667  in "NOT master mode", so instead of just collecting the passphrase and
668  giving it
669  back to OpenSSL, it calls this function first, which returns the master
670  password
671  (so that IT can be given to OpenSSL instead.)
672 
673  If the master wasn't already loaded (common) then we call the callback in
674  here ourselves.
675  Notice it's recursive! But this time, the callback sees we ARE in master
676  mode, so it doesn't
677  call this function again (which would be an infinite loop.) Instead, it
678  collects the password
679  as normal, only instead of passing it back to the caller via the buffer, it
680  uses the
681  passUserInput by attaching it to thePWData before the call. That way the
682  callback function
683  can set passUserInput with whatever it retrieved from the user, and then
684  back in this function
685  again we can get the passUserInput and use it to unlock the MASTER
686  passphrase, which we set
687  onto theOutput.
688 
689  When this function returns true, the callback (0th level of recursion) uses
690  theOutput
691  as the "passphrase" for all Nyms, passing it to OpenSSL.
692 
693  This way, OpenSSL gets a random key instead of a passphrase, and the
694  passphrase is just used
695  for encrypting that random key whenever its timer has run out.
696 
697  */
698 
699  bool bReturnVal = false;
700 
701  // CALL the callback directly. (To retrieve a passphrase so I can use it in
702  // GenerateKey
703  // and GetRawKey.)
704  //
705  // int32_t OT_OPENSSL_CALLBACK (char* buf, int32_t size, int32_t rwflag,
706  // void *userdata);
707  //
708  // For us, it will set passUserInput to the password from the user, and
709  // return
710  // a simple 1 or 0 (instead of the length.) buf and size can be nullptr / 0,
711  // and
712  // rwflag should be passed in from somewhere.
713  //
714  // m_pSymmetricKey is the encrypted form of the master key. Therefore we
715  // want to hash
716  // it, in order to get the ID for lookups on the keychain.
717  //
718  OTPassword* pDerivedKey = nullptr;
719  std::unique_ptr<OTPassword> theDerivedAngel;
720 
721  if (nullptr == m_pSymmetricKey) {
722  m_pSymmetricKey = new OTSymmetricKey;
723  OT_ASSERT(nullptr != m_pSymmetricKey);
724  }
725 
726  if (!m_pSymmetricKey->IsGenerated()) // doesn't already exist.
727  {
728  otWarn << szFunc << ": Master key didn't exist. Need to collect a "
729  "passphrase from the user, "
730  "so we can generate a master key...\n ";
731 
732  bVerifyTwice = true; // we force it, in this case.
733  }
734  else // If the symmetric key itself ALREADY exists (which it usually
735  // will...)
736  { // then we might have also already stashed the derived key on the system
737  // keychain. Let's check there first before asking the user to enter his
738  // passphrase...
739  //
740 
741  const OTIdentifier idCachedKey(
742  *m_pSymmetricKey); // Grab the ID of this symmetric key.
743  const OTString strCachedKeyHash(
744  idCachedKey); // Same thing, in string form.
745  //
746  // This only happens in here where we KNOW m_pSymmetricKey was already
747  // generated.
748  //
749  // OTString strCachedKeyHash;
750  // m_pSymmetricKey->GetIdentifier(strCachedKeyHash);
751 
752  pDerivedKey =
753  OTCrypto::It()->InstantiateBinarySecret(); // pDerivedKey is
754  // instantiated here to
755  // use as output argument
756  // below.
757 
758  //
759  // *** ATTEMPT to RETRIEVE the *Derived Key* from THE SYSTEM KEYCHAIN
760  // ***
761  //
762  const bool bFoundOnKeyring =
765  strCachedKeyHash, // HASH OF ENCRYPTED MASTER KEY
766  *pDerivedKey, // (Output) RETRIEVED PASSWORD.
767  str_display); // optional display string.
768 
769  if (bFoundOnKeyring) // We found it -- but does it WORK?
770  {
771  const bool bCachedKey = m_pSymmetricKey->GetRawKeyFromDerivedKey(
772  *pDerivedKey, *m_pMasterPassword);
773 
774  //
775  // Note: What IS the secret? We don't want it to be the user's
776  // passphrase that he TYPES.
777  // We also don't want it to be the eventual (random) key that
778  // unlocks the private keys.
779  // Rather, we want it to be the intermediary key, generated from the
780  // user's passphrase via
781  // a key-derivation algorithm, which is then used to unlock the
782  // (random) symmetric key that
783  // actually unlocks the private keys.
784  // This way the symmetric key itself can be kept locked at ALL
785  // times, and instead, we have the
786  // derived key on the timer, use it to unlock the symmetric key
787  // EVERY TIME we use that, and
788  // IMMEDIATELY throw it away afterwards, since we can still open it
789  // again (until the timeout) by
790  // using the derived key.
791  // This is slick because the user doesn't directly enter the derived
792  // key, and neither is it
793  // directly used for unlocking private keys -- so it's preferable to
794  // store in RAM than those things.
795  //
796  //
797  // 1. Make sure the above description is actually what we DO do now.
798  // (UPDATE: for keyring, yes. For OT internally, no.)
799  // 2. Make sure the derived key, as described above, is also what is
800  // stored as the SECRET, here! (UPDATE: Yes!)
801  // (i.e. in other processes such as Mac Keychain or Gnome.)
802  // 3. Done. Need to add ability for OTIdentifier to hash
803  // OTSymmetricKey, so we can use it for strUser above. DONE.
804  //
805  // UPDATE: the master key cached inside OT (on a timer) is not the
806  // derived key, but the master key itself
807  // that's used on the private keys. However, the one we're caching
808  // in the system keyring IS the derived key,
809  // and not the master key. So for example, if an attacker obtained
810  // the derived key from the system keyring,
811  //
812 
813  if (bCachedKey) // It works!
814  {
815  otWarn << szFunc << ": Finished calling "
816  "m_pSymmetricKey->GetRawKeyFromDerivedKey "
817  "(Success.)\n";
818  theOutput = *m_pMasterPassword; // Return it to the caller.
819  theDerivedAngel.reset(
820  pDerivedKey); // Set our own copy to be destroyed later. It
821  // continues below as "NOT nullptr".
822  bReturnVal = true; // Success.
823  }
824  else // It didn't unlock with the one we found.
825  {
826  otOut << szFunc << ": Unable to unlock master key using "
827  "derived key found on system keyring.\n";
828  delete pDerivedKey;
829  pDerivedKey = nullptr; // Below, this function checks
830  // pDerivedKey for nullptr.
831  }
832  }
833  else // NOT found on keyring.
834  {
835  if (IsUsingSystemKeyring()) // We WERE using the keying, but
836  // we DIDN'T find the derived key.
837  otWarn << szFunc
838  << ": Unable to find derived key on system keyring.\n";
839  // (Otherwise if we WEREN'T using the system keyring, then of course
840  // we didn't find any derived key cached there.)
841  delete pDerivedKey;
842  pDerivedKey =
843  nullptr; // Below, this function checks pDerivedKey for nullptr.
844  }
845  }
846 
847  // NOT found on Keyring...
848  //
849  if (nullptr == pDerivedKey) // Master key was not cached in OT, nor was it
850  // found in the system keychain.
851  { // Therefore we HAVE to ask the user for a passphrase and decrypt it
852  // ourselves,
853  // since we DO have an encrypted version of the key...
854 
855  // This time we DEFINITELY force the user input, since we already played
856  // our hand.
857  // If the master key was still in memory we would have returned already,
858  // above.
859  // Then we tried to find it on the keyring and we couldn't find it, so
860  // now we have
861  // to actually ask the user to enter it.
862  //
863 
864  std::string default_password(OT_DEFAULT_PASSWORD); // default password
865  OTPassword passwordDefault;
866  passwordDefault.zeroMemory();
867  passwordDefault.setPassword(
868  default_password.c_str(),
869  static_cast<int32_t>(default_password.length()));
870 
871  OTPassword passUserInput;
872  passUserInput.zeroMemory(); // text mode.
873  OTPasswordData thePWData(str_display.c_str(), &passUserInput,
874  mySharedPtr); // these pointers are only passed
875  // in the case where it's for a
876  // master key.
877  // otInfo << "*********Begin OTCachedKey::GetMasterPassword:
878  // Calling souped-up password cb...\n * * * * * * * * * ");
879 
880  // It's possible this is the first time this is happening, and the
881  // master key
882  // hasn't even been generated yet. In which case, we generate it here...
883  //
884  bool bGenerated = m_pSymmetricKey->IsGenerated();
885 
886  if (!bGenerated) // This Symmetric Key hasn't been generated before....
887  {
888 
890  nullptr, 0, bVerifyTwice ? 1 : 0,
891  static_cast<void*>(&thePWData))) {
892  otErr << __FUNCTION__ << ": Failed to get password from user!";
893  return false;
894  }
895 
896  // If the length of the user supplied password is less than 4
897  // characters int64_t, we are going to use the default password!
898  bool bUsingDefaultPassword = false;
899  {
900  if (4 > std::string(passUserInput.getPassword()).length()) {
901  otOut << "\n Password entered was less than 4 characters "
902  "int64_t! This is NOT secure!!\n"
903  "... Assuming password is for testing only... "
904  "setting to default password: "
905  << OT_DEFAULT_PASSWORD << " \n";
906  bUsingDefaultPassword = true;
907  }
908  }
909 
910  // otOut << "%s: Calling
911  // m_pSymmetricKey->GenerateKey()...\n", szFunc);
912 
913  bGenerated = m_pSymmetricKey->GenerateKey(
914  bUsingDefaultPassword ? passwordDefault : passUserInput,
915  &pDerivedKey); // derived key is optional here.
916  //
917  // Note: since I passed &pDerivedKey in the above call, then **I**
918  // am responsible to
919  // check it for nullptr, and delete it if there's something there!
920  //
921  if (nullptr != pDerivedKey)
922  theDerivedAngel.reset(pDerivedKey);
923  else
924  otErr << __FUNCTION__ << ": FYI: Derived key is still nullptr "
925  "after calling "
926  "OTSymmetricKey::GenerateKey.\n";
927 
928  // otOut << "%s: Finished calling
929  // m_pSymmetricKey->GenerateKey()...\n", szFunc);
930  }
931  else // m_pSymmetricKey->IsGenerated() == true. (Symmetric Key is
932  // already generated.)
933  {
934 
935  // Generate derived key from passphrase.
936  //
937  // We generate the derived key here so that
938  // GetRawKeyFromPassphrase() call (below)
939  // works with it being passed in. (Because the above call to
940  // GenerateKey also grabs
941  // a copy of the derived key and passes it in below to the same
942  // GetRawKeyFromPassphrase.)
943  //
944  // So WHY are we keeping a copy of the derived key through these
945  // calls? Otherwise they
946  // would all individually generate it, which is a waste of
947  // resources. Also, we want to have
948  // our grubby hands on the derived key at the end so we can add it
949  // to the system keyring
950  // (below), and we'd just end up having to derive it AGAIN in order
951  // to do so.
952  //
953  if (m_pSymmetricKey->HasHashCheck()) {
954  pDerivedKey =
955  m_pSymmetricKey->CalculateDerivedKeyFromPassphrase(
956  passwordDefault); // asserts already.
957 
958  if (nullptr == pDerivedKey) {
959  otOut << "\n\n" << __FUNCTION__
960  << ": Please enter your password.\n\n";
961 
962  for (;;) // bad passphase (as the calculate key returned
963  // nullptr)
964  {
966  nullptr, 0, false,
967  static_cast<void*>(&thePWData))) {
968  otErr << "\n\n" << __FUNCTION__
969  << ": Failed to get password from user!\n\n";
970  return false;
971  }
972  pDerivedKey =
973  m_pSymmetricKey->CalculateDerivedKeyFromPassphrase(
974  passUserInput); // asserts already.
975  if (nullptr != pDerivedKey) break; // success
976 
977  otOut << "\n\n" << __FUNCTION__
978  << ": Wrong Password, Please Try Again.\n\n";
979  }
980  }
981  }
982  else {
983  otOut << "\n Please enter your current password twice, (not a "
984  "new password!!) \n";
985 
987  nullptr, 0, true, static_cast<void*>(&thePWData))) {
988  otErr << __FUNCTION__
989  << ": Failed to get password from user!";
990  return false;
991  }
992 
993  pDerivedKey =
994  m_pSymmetricKey->CalculateNewDerivedKeyFromPassphrase(
995  passUserInput); // asserts already.
996  OT_ASSERT(nullptr != pDerivedKey);
997  }
998  theDerivedAngel.reset(pDerivedKey);
999 
1000  otWarn << szFunc << ": FYI, symmetric key was already generated. "
1001  "Proceeding to try and use it...\n";
1002 
1003  // bGenerated is true, if we're even in this block in the first
1004  // place.
1005  // (No need to set it twice.)
1006  }
1007 
1008  // Below this point, pDerivedKey could still be null.
1009  // (And we only clean it up later if we created it.)
1010  // Also, bGenerated could still be false. (Like if it wasn't
1011  // generated, then generation itself failed, then it's still false.)
1012  //
1013  // Also, even if it was already generated, or if it wasn't but then
1014  // successfully did,
1015  //
1016 
1017  if (bGenerated) // If SymmetricKey (*this) is already generated.
1018  {
1019  otInfo
1020  << szFunc
1021  << ": Calling m_pSymmetricKey->GetRawKeyFromPassphrase()...\n";
1022 
1023  // Once we have the user's password, then we use it to GetKey from
1024  // the OTSymmetricKey (which
1025  // is encrypted) and that retrieves the cleartext master password
1026  // which we set here and also
1027  // return a copy of.
1028  //
1029  // Note: if pDerivedKey was derived above already, which it should
1030  // have been, then it will
1031  // be not-nullptr, and will be used here, and will be used
1032  // subsequently
1033  // for adding to the system
1034  // keychain. Otherwise, it will be nullptr, and
1035  // GetRawKeyFromPassphrase
1036  // will thus just derive its
1037  // own copy of the derived key internally. It will still work, but
1038  // then back up here, it will
1039  // NOT be added to the system keyring, since it's still nullptr back
1040  // up
1041  // here.
1042  // (FYI.)
1043  //
1044  const bool bCachedKey = m_pSymmetricKey->GetRawKeyFromPassphrase(
1045  passUserInput, *m_pMasterPassword, pDerivedKey);
1046  if (bCachedKey) {
1047  otInfo << szFunc << ": Finished calling "
1048  "m_pSymmetricKey->GetRawKeyFromPassphrase "
1049  "(Success.)\n";
1050  theOutput = *m_pMasterPassword; // Success!
1051 
1052  // Store the derived key to the system keyring.
1053  //
1054  if (IsUsingSystemKeyring() && (nullptr != pDerivedKey)) {
1055  const std::string str_display(
1056  nullptr != szDisplay ? szDisplay
1057  : "(Display string was blank.)");
1058 
1059  const OTIdentifier idCachedKey(*m_pSymmetricKey);
1060  const OTString strCachedKeyHash(
1061  idCachedKey); // Same thing, in string form.
1062 
1063  // const bool bStored =
1065  strCachedKeyHash, // HASH OF ENCRYPTED MASTER KEY
1066  *pDerivedKey, // (Input) Derived Key BEING STORED.
1067  str_display); // optional display string.
1068  }
1069  else
1070  otWarn << szFunc << ": Strange: Problem with either: "
1071  "IsUsingSystemKeyring"
1072  " ("
1073  << (IsUsingSystemKeyring() ? "true" : "false")
1074  << ") "
1075  "or: (nullptr != pDerivedKey) ("
1076  << ((nullptr != pDerivedKey) ? "true" : "false")
1077  << ")\n";
1078 
1079  bReturnVal = true;
1080  }
1081  else
1082  otOut
1083  << szFunc
1084  << ": m_pSymmetricKey->GetRawKeyFromPassphrase() failed.\n";
1085  } // bGenerated
1086  else
1087  otErr << szFunc << ": bGenerated is still false, even after trying "
1088  "to generate it, yadda yadda yadda.\n";
1089 
1090  } // nullptr == pDerivedKey
1091 
1092  if (bReturnVal) // Start the thread!
1093  {
1094 // otLog4 << "%s: starting up new thread, so we can expire the master key
1095 // from RAM.\n", szFunc);
1096 
1097 #if defined(OT_CRYPTO_USING_OPENSSL)
1098 
1099 #if defined(OPENSSL_THREADS)
1100  // thread support enabled
1101 
1102  otInfo << szFunc << ": Starting thread for Master Key...\n";
1103 
1104  std::shared_ptr<OTCachedKey>* pthreadSharedPtr =
1105  new std::shared_ptr<OTCachedKey>(mySharedPtr); // TODO: memory leak.
1106 
1107  m_pThread = new std::thread(OTCachedKey::ThreadTimeout,
1108  static_cast<void*>(pthreadSharedPtr));
1109 
1110 #else
1111  // no thread support
1112 
1113  otErr << szFunc
1114  << ": WARNING: OpenSSL was NOT compiled with thread support. "
1115  "(Master Key will not expire.)\n";
1116 
1117 #endif
1118 
1119 #elif defined(OT_CRYPTO_USING_GPG)
1120 
1121  otErr << szFunc << ": WARNING: OT was compiled for GPG, which is not "
1122  "yet supported. "
1123  "(Master Key will not expire.)\n";
1124 
1125 #else // OT_CRYPTO_USING_ ... nothing?
1126 
1127  otErr << szFunc
1128  << ": WARNING: OT wasn't compiled for any crypto library "
1129  "(such as OpenSSL or GPG). Which is very strange, and I doubt "
1130  "things will even work, with it in this condition. (Plus, "
1131  "Master "
1132  "Key will not expire.)\n";
1133 
1134 #endif // if defined(OT_CRYPTO_USING_OPENSSL), elif
1135  // defined(OT_CRYPTO_USING_GPG), else, endif.
1136 
1137  }
1138  else if (m_nTimeoutSeconds != (-1)) {
1139  if (nullptr != m_pMasterPassword) {
1140  OTPassword* pMasterPassword = m_pMasterPassword;
1141 
1142  m_pMasterPassword = nullptr;
1143 
1144  delete pMasterPassword;
1145  pMasterPassword = nullptr;
1146  }
1147  }
1148  // Since we have set the cleartext master password, We also have to fire up
1149  // the thread
1150  // so it can timeout and be destroyed. In the meantime, it'll be stored in
1151  // an OTPassword
1152  // which has these security precautions:
1153  /*
1154  1. Zeros memory in a secure and cross-platform way, in its destructor.
1155  2. OT_Init() uses setrlimit to prevent core dumps.
1156  3. Uses VirtualLock and mlock to reduce/prevent swapping RAM to hard drive.
1157  4. (SOON) will use VirtualProtect on Windows (standard API for protected
1158  memory)
1159  5. (SOON) and similarly have option in config file for ssh-agent, gpg-agent,
1160  etc.
1161  6. Even without those things,the master password is stored in an encrypted
1162  form after it times out.
1163  7. While decrypted (while timer is going) it's still got the above security
1164  mechanisms,
1165  plus options for standard protected-memory APIs are made available wherever
1166  possible.
1167  8. The actual passphrase the user types is not stored in memory, except just
1168  int64_t enough to
1169  use it to derive another key, used to unlock the actual key (for a temporary
1170  period of time.)
1171  9. Meanwhile the actual key is stored in encrypted form on disk, and the
1172  derived key isn't stored anywhere.
1173  10. Ultimately external hardware, and smart cards, are the way to go. But OT
1174  should still do the best possible.
1175  */
1176 
1177  return bReturnVal;
1178 }
1179 
1180 // static
1181 // This is the thread itself.
1182 //
1184 {
1185  // TODO: Save a copy of pArg, in the cached key object, and delete it
1186  // whenever LowLevelRemoveThread
1187  // is called. Otherwise it's a memory leak.
1188  //
1189  std::shared_ptr<OTCachedKey>* pthreadSharedPtr =
1190  static_cast<std::shared_ptr<OTCachedKey>*>(pArg);
1191  std::shared_ptr<OTCachedKey> pMyself = *pthreadSharedPtr;
1192 
1193  if (!pMyself) {
1194  OT_FAIL_MSG("OTCachedKey::ThreadTimeout: Need ptr to master key here, "
1195  "that activated this thread.\n");
1196  }
1197 
1198  // std::lock_guard<std::mutex> lock(*(pMyself->GetMutex()));
1199 
1200  int32_t nTimeoutSeconds = 0;
1201 
1202  {
1203  std::lock_guard<std::mutex> lock(OTCachedKey::s_mutexThreadTimeout);
1204 
1205  if (pMyself) {
1206  nTimeoutSeconds =
1207  pMyself->GetTimeoutSeconds(); // locks mutex internally.
1208  }
1209  }
1210 
1211  if (nTimeoutSeconds > 0) {
1212  if (pMyself)
1213  std::this_thread::sleep_for(
1214  std::chrono::seconds(nTimeoutSeconds)); // <===== ASLEEP!
1215  }
1216 
1217  {
1218  std::lock_guard<std::mutex> lock(OTCachedKey::s_mutexThreadTimeout);
1219 
1220  if (pMyself && (nTimeoutSeconds != (-1))) {
1221  pMyself->DestroyMasterPassword(); // locks mutex internally.
1222  }
1223  }
1224 }
1225 
1226 // Called by the thread.
1227 // The cleartext version (m_pMasterPassword) is deleted and set nullptr after a
1228 // Timer of X seconds.
1229 // (Timer thread calls this.) The instance that owns each thread will pass its
1230 // instance pointer
1231 // as pArg so we can access the timeout seconds and the mutex, and the password
1232 // we're destroying.
1233 //
1235 {
1236  std::lock_guard<std::mutex> lock(m_Mutex);
1237  //
1238  if (m_nTimeoutSeconds != (-1)) {
1239  // (m_pSymmetricKey stays.
1240  // m_pMasterPassword only is destroyed.)
1241  //
1242  if (nullptr != m_pMasterPassword) {
1243  OTPassword* pPassword = m_pMasterPassword;
1244 
1245  m_pMasterPassword = nullptr;
1246 
1247  delete pPassword;
1248  pPassword = nullptr;
1249  }
1250  }
1251  // (We do NOT call LowLevelReleaseThread(); here, since the thread is
1252  // what CALLED this function. Instead, we destroy / nullptr the master
1253  // password,
1254  // so that next time around we will see it is nullptr and THEN we will know
1255  // to
1256  // call LowLevelReleaseThread(); before instantiating a new one.)
1257 
1258  // New: When the master password is destroyed here, we also remove it from
1259  // the system keychain:
1260  //
1261  if (nullptr != m_pSymmetricKey) {
1262  const std::string str_display;
1263 
1264  const OTIdentifier idCachedKey(*m_pSymmetricKey);
1265  const OTString strCachedKeyHash(
1266  idCachedKey); // Same thing, in string form.
1267 
1268  const bool bDeletedSecret =
1271  strCachedKeyHash, // HASH OF ENCRYPTED MASTER KEY
1272  str_display); // "optional" display string.
1273  if (bDeletedSecret) {
1274  otOut << "OTCachedKey::DestroyMasterPassword: FYI, deleted "
1275  "the derived key (used for unlocking the master key "
1276  "password) "
1277  "from system keychain at the same time as we deleted the "
1278  "master key "
1279  "password from OT internally, due to password timeout.\n";
1280  }
1281  }
1282 }
1283 
1284 // If you actually want to create a new key, and a new passphrase, then use this
1285 // to destroy every last vestige of the old one. (Which will cause a new one to
1286 // be automatically generated the next time OT requests the master key.) NOTE:
1287 // Make SURE you have all your Nyms loaded up and unlocked before you call this.
1288 // Then save them all again so they will be properly stored with the new master
1289 // key.
1290 
1292 {
1293  std::lock_guard<std::mutex> lock(m_Mutex);
1294 
1296 
1297  if (nullptr != m_pMasterPassword) {
1298  OTPassword* pPassword = m_pMasterPassword;
1299 
1300  m_pMasterPassword = nullptr;
1301 
1302  delete pPassword;
1303  pPassword = nullptr;
1304  }
1305 
1306  if (nullptr != m_pSymmetricKey) {
1307  // We also remove it from the system keychain:
1308  //
1309  const std::string str_display;
1310 
1311  const OTIdentifier idCachedKey(
1312  *m_pSymmetricKey); // Symmetric Key ID of the Master key.
1313  const OTString strCachedKeyHash(
1314  idCachedKey); // Same thing, in string form.
1315 
1316  const bool bDeletedSecret =
1319  strCachedKeyHash, // HASH OF ENCRYPTED MASTER KEY
1320  str_display); // "optional" display string.
1321  if (bDeletedSecret) {
1322  otOut << "OTCachedKey::ResetMasterPassword: FYI, deleted "
1323  "the derived key (used for unlocking the master key "
1324  "password) "
1325  "from system keychain at the same time as we deleted the "
1326  "master key "
1327  "itself, presumably due to the passphrase being reset.\n";
1328  }
1329 
1330  // Now wipe the symmetric key itself (so it can later be
1331  // re-created as a new key.)
1332  //
1333  if (nullptr != m_pSymmetricKey) {
1334  OTSymmetricKey* pSymmetricKey = m_pSymmetricKey;
1335 
1336  m_pSymmetricKey = nullptr;
1337 
1338  delete pSymmetricKey;
1339  pSymmetricKey = nullptr;
1340  }
1341  }
1342 }
1343 
1344 } // namespace opentxs
static EXPORT OTCrypto * It()
Definition: OTCrypto.cpp:630
static EXPORT void Cleanup()
EXPORT OTPassword * CalculateNewDerivedKeyFromPassphrase(const OTPassword &thePassphrase)
EXPORT void ResetMasterPassword()
virtual OTPassword * InstantiateBinarySecret() const =0
static EXPORT std::shared_ptr< OTCachedKey > CreateMasterPassword(OTPassword &theOutput, const char *szDisplay=nullptr, int32_t nTimeoutSeconds=OT_MASTER_KEY_TIMEOUT)
#define OT_DEFAULT_PASSWORD
EXPORT void LowLevelReleaseThread()
EXPORT bool IsUsingSystemKeyring() const
EXPORT void SetCachedKey(const OTASCIIArmor &ascCachedKey)
EXPORT bool Pause()
EXPORT bool SerializeFrom(OTPayload &theInput)
EXPORT void zeroMemory()
Definition: OTPassword.cpp:281
OTLOG_IMPORT OTLogStream otOut
std::map< std::string, std::shared_ptr< OTCachedKey > > mapOfCachedKeys
EXPORT int32_t setPassword(const char *input, int32_t size)
Definition: OTPassword.cpp:665
EXPORT void DestroyMasterPassword()
EXPORT bool GetRawKeyFromPassphrase(const OTPassword &thePassphrase, OTPassword &theRawKeyOutput, OTPassword *pDerivedKey=nullptr) const
EXPORT bool Exists() const
Definition: OTString.cpp:1035
static EXPORT std::shared_ptr< OTCachedKey > It(OTIdentifier *pIdentifier=nullptr)
EXPORT bool GetRawKeyFromDerivedKey(const OTPassword &theDerivedKey, OTPassword &theRawKeyOutput) const
EXPORT void SetTimeoutSeconds(int32_t nTimeoutSeconds)
EXPORT bool GenerateKey(const OTPassword &thePassphrase, OTPassword **ppDerivedKey=nullptr)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT bool SerializeTo(OTPayload &theOutput) const
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
EXPORT bool IsGenerated()
OTLOG_IMPORT OTLogStream otInfo
EXPORT OTPassword * CalculateDerivedKeyFromPassphrase(const OTPassword &thePassphrase, bool bCheckForHashCheck=true) const
EXPORT bool GetIdentifier(OTIdentifier &theIdentifier) const
EXPORT bool HasHashCheck()
EXPORT bool Unpause()
static EXPORT void ThreadTimeout(void *pArg)
EXPORT const char * getPassword() const
Definition: OTPassword.cpp:547
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
EXPORT bool SerializeFrom(const OTASCIIArmor &ascInput)
OTLOG_IMPORT OTLogStream otWarn
EXPORT const char * Get() const
Definition: OTString.cpp:1045
EXPORT int32_t GetTimeoutSeconds()
OTLOG_IMPORT OTLogStream otErr
EXPORT bool isPaused()
static EXPORT OT_OPENSSL_CALLBACK * GetPasswordCallback()
EXPORT bool SerializeTo(OTASCIIArmor &ascOutput)
static EXPORT bool RetrieveSecret(const OTString &strUser, OTPassword &thePassword, const std::string &str_display)
Definition: OTKeyring.cpp:1365
EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
EXPORT bool GetMasterPassword(std::shared_ptr< OTCachedKey > &mySharedPtr, OTPassword &theOutput, const char *szDisplay=nullptr, bool bVerifyTwice=false)
static EXPORT bool DeleteSecret(const OTString &strUser, const std::string &str_display)
Definition: OTKeyring.cpp:1395
static EXPORT bool StoreSecret(const OTString &strUser, const OTPassword &thePassword, const std::string &str_display)
Definition: OTKeyring.cpp:1335