Open-Transactions  0.93.0-ge03d287
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
opentxs::OTCachedKey Class Reference

#include <OTCachedKey.hpp>

Public Member Functions

std::mutex * GetMutex ()
 
EXPORT OTCachedKey (const OTASCIIArmor &ascCachedKey)
 
EXPORT ~OTCachedKey ()
 
EXPORT bool GetIdentifier (OTIdentifier &theIdentifier) const
 
EXPORT bool GetIdentifier (OTString &strIdentifier) const
 
EXPORT bool IsGenerated ()
 
EXPORT bool HasHashCheck ()
 
EXPORT bool IsUsingSystemKeyring () const
 
EXPORT void UseSystemKeyring (bool bUsing=true)
 
EXPORT bool Pause ()
 
EXPORT bool Unpause ()
 
EXPORT bool isPaused ()
 
EXPORT bool SerializeTo (OTASCIIArmor &ascOutput)
 
EXPORT bool SerializeFrom (const OTASCIIArmor &ascInput)
 
EXPORT void SetCachedKey (const OTASCIIArmor &ascCachedKey)
 
EXPORT int32_t GetTimeoutSeconds ()
 
EXPORT void SetTimeoutSeconds (int32_t nTimeoutSeconds)
 
EXPORT bool GetMasterPassword (std::shared_ptr< OTCachedKey > &mySharedPtr, OTPassword &theOutput, const char *szDisplay=nullptr, bool bVerifyTwice=false)
 
EXPORT void DestroyMasterPassword ()
 
EXPORT void ResetMasterPassword ()
 
EXPORT void LowLevelReleaseThread ()
 

Static Public Member Functions

static EXPORT std::shared_ptr
< OTCachedKey
It (OTIdentifier *pIdentifier=nullptr)
 
static EXPORT std::shared_ptr
< OTCachedKey
It (OTCachedKey &theSourceKey)
 
static EXPORT void Cleanup ()
 
static EXPORT std::shared_ptr
< OTCachedKey
CreateMasterPassword (OTPassword &theOutput, const char *szDisplay=nullptr, int32_t nTimeoutSeconds=OT_MASTER_KEY_TIMEOUT)
 
static EXPORT void ThreadTimeout (void *pArg)
 

Detailed Description

Definition at line 311 of file OTCachedKey.hpp.

Constructor & Destructor Documentation

opentxs::OTCachedKey::OTCachedKey ( const OTASCIIArmor ascCachedKey)

Definition at line 364 of file OTCachedKey.cpp.

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 }
EXPORT bool IsUsingSystemKeyring() const
EXPORT void SetCachedKey(const OTASCIIArmor &ascCachedKey)
static EXPORT std::shared_ptr< OTCachedKey > It(OTIdentifier *pIdentifier=nullptr)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
EXPORT int32_t GetTimeoutSeconds()
opentxs::OTCachedKey::~OTCachedKey ( )

Definition at line 444 of file OTCachedKey.cpp.

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 }
EXPORT void LowLevelReleaseThread()

Member Function Documentation

void opentxs::OTCachedKey::Cleanup ( )
static

Definition at line 334 of file OTCachedKey.cpp.

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 }
std::shared_ptr< OTCachedKey > opentxs::OTCachedKey::CreateMasterPassword ( OTPassword theOutput,
const char *  szDisplay = nullptr,
int32_t  nTimeoutSeconds = OT_MASTER_KEY_TIMEOUT 
)
static

Definition at line 593 of file OTCachedKey.cpp.

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 }
void opentxs::OTCachedKey::DestroyMasterPassword ( )

Definition at line 1234 of file OTCachedKey.cpp.

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 }
EXPORT bool IsUsingSystemKeyring() const
OTLOG_IMPORT OTLogStream otOut
static EXPORT bool DeleteSecret(const OTString &strUser, const std::string &str_display)
Definition: OTKeyring.cpp:1395
bool opentxs::OTCachedKey::GetIdentifier ( OTIdentifier theIdentifier) const

Definition at line 557 of file OTCachedKey.cpp.

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 }
EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
bool opentxs::OTCachedKey::GetIdentifier ( OTString strIdentifier) const

Definition at line 568 of file OTCachedKey.cpp.

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 }
EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
bool opentxs::OTCachedKey::GetMasterPassword ( std::shared_ptr< OTCachedKey > &  mySharedPtr,
OTPassword theOutput,
const char *  szDisplay = nullptr,
bool  bVerifyTwice = false 
)

Definition at line 623 of file OTCachedKey.cpp.

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 }
static EXPORT OTCrypto * It()
Definition: OTCrypto.cpp:630
EXPORT OTPassword * CalculateNewDerivedKeyFromPassphrase(const OTPassword &thePassphrase)
virtual OTPassword * InstantiateBinarySecret() const =0
#define OT_DEFAULT_PASSWORD
EXPORT void LowLevelReleaseThread()
EXPORT bool IsUsingSystemKeyring() const
OTLOG_IMPORT OTLogStream otOut
EXPORT bool GetRawKeyFromPassphrase(const OTPassword &thePassphrase, OTPassword &theRawKeyOutput, OTPassword *pDerivedKey=nullptr) const
EXPORT bool GetRawKeyFromDerivedKey(const OTPassword &theDerivedKey, OTPassword &theRawKeyOutput) const
EXPORT bool GenerateKey(const OTPassword &thePassphrase, OTPassword **ppDerivedKey=nullptr)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTLOG_IMPORT OTLogStream otInfo
EXPORT OTPassword * CalculateDerivedKeyFromPassphrase(const OTPassword &thePassphrase, bool bCheckForHashCheck=true) const
static EXPORT void ThreadTimeout(void *pArg)
OTLOG_IMPORT OTLogStream otWarn
OTLOG_IMPORT OTLogStream otErr
static EXPORT OT_OPENSSL_CALLBACK * GetPasswordCallback()
static EXPORT bool RetrieveSecret(const OTString &strUser, OTPassword &thePassword, const std::string &str_display)
Definition: OTKeyring.cpp:1365
static EXPORT bool StoreSecret(const OTString &strUser, const OTPassword &thePassword, const std::string &str_display)
Definition: OTKeyring.cpp:1335
std::mutex* opentxs::OTCachedKey::GetMutex ( )
inline

Definition at line 360 of file OTCachedKey.hpp.

361  {
362  return &m_Mutex;
363  } // So static functions using this CachedKey can also lock its mutex.
int32_t opentxs::OTCachedKey::GetTimeoutSeconds ( )

Definition at line 476 of file OTCachedKey.cpp.

477 {
478  std::lock_guard<std::mutex> lock(m_Mutex);
479 
480  const int32_t nTimeout = m_nTimeoutSeconds;
481 
482  return nTimeout;
483 }
bool opentxs::OTCachedKey::HasHashCheck ( )

Definition at line 176 of file OTCachedKey.cpp.

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 }
bool opentxs::OTCachedKey::IsGenerated ( )

Definition at line 163 of file OTCachedKey.cpp.

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 }
bool opentxs::OTCachedKey::isPaused ( )

Definition at line 388 of file OTCachedKey.cpp.

389 {
390  // std::lock_guard<std::mutex> lock(m_Mutex);
391 
392  return m_bPaused;
393 }
EXPORT bool opentxs::OTCachedKey::IsUsingSystemKeyring ( ) const
inline

Definition at line 386 of file OTCachedKey.hpp.

387  {
388  return m_bUse_System_Keyring;
389  }
std::shared_ptr< OTCachedKey > opentxs::OTCachedKey::It ( OTIdentifier pIdentifier = nullptr)
static

Definition at line 194 of file OTCachedKey.cpp.

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 }
std::shared_ptr< OTCachedKey > opentxs::OTCachedKey::It ( OTCachedKey theSourceKey)
static

Definition at line 261 of file OTCachedKey.cpp.

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 }
EXPORT bool IsGenerated()
OTLOG_IMPORT OTLogStream otErr
EXPORT bool SerializeTo(OTASCIIArmor &ascOutput)
void opentxs::OTCachedKey::LowLevelReleaseThread ( )

Definition at line 431 of file OTCachedKey.cpp.

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 }
bool opentxs::OTCachedKey::Pause ( )

Definition at line 402 of file OTCachedKey.cpp.

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 }
void opentxs::OTCachedKey::ResetMasterPassword ( )

Definition at line 1291 of file OTCachedKey.cpp.

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 }
EXPORT void LowLevelReleaseThread()
EXPORT bool IsUsingSystemKeyring() const
OTLOG_IMPORT OTLogStream otOut
static EXPORT bool DeleteSecret(const OTString &strUser, const std::string &str_display)
Definition: OTKeyring.cpp:1395
bool opentxs::OTCachedKey::SerializeFrom ( const OTASCIIArmor ascInput)

Definition at line 535 of file OTCachedKey.cpp.

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 }
EXPORT bool SerializeFrom(OTPayload &theInput)
bool opentxs::OTCachedKey::SerializeTo ( OTASCIIArmor ascOutput)

Definition at line 544 of file OTCachedKey.cpp.

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 }
EXPORT bool SerializeTo(OTPayload &theOutput) const
void opentxs::OTCachedKey::SetCachedKey ( const OTASCIIArmor ascCachedKey)

Definition at line 500 of file OTCachedKey.cpp.

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 }
EXPORT bool SerializeFrom(OTPayload &theInput)
#define OT_ASSERT(x)
Definition: Assert.hpp:150
OTLOG_IMPORT OTLogStream otErr
void opentxs::OTCachedKey::SetTimeoutSeconds ( int32_t  nTimeoutSeconds)

Definition at line 485 of file OTCachedKey.cpp.

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 }
#define OT_ASSERT_MSG(x, s)
Definition: Assert.hpp:155
void opentxs::OTCachedKey::ThreadTimeout ( void *  pArg)
static

Definition at line 1183 of file OTCachedKey.cpp.

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 }
#define OT_FAIL_MSG(s)
Definition: Assert.hpp:144
bool opentxs::OTCachedKey::Unpause ( )

Definition at line 413 of file OTCachedKey.cpp.

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 }
EXPORT void opentxs::OTCachedKey::UseSystemKeyring ( bool  bUsing = true)
inline

Definition at line 390 of file OTCachedKey.hpp.

391  {
392  m_bUse_System_Keyring = bUsing;
393  } // Start using system keyring.

The documentation for this class was generated from the following files: