//---------------------------------------------------------------------
      bool PeerContactProfile::usesContactProfileSecret(const char *contactProfileSecret)
      {
        AutoRecursiveLock lock(mLock);
        if (NULL == contactProfileSecret) return false;
        if (!mDocument) return false;

        try {
          ElementPtr contactProfileElement = getContactProfileElement();
          if (!contactProfileElement) return false;
          ElementPtr proofElement = contactProfileElement->findFirstChildElementChecked("private")->findFirstChildElementChecked("proof");
          String proofAsBase64 = proofElement->getText(true);
          SecureByteBlock proofHash;
          convertFromBase64(proofAsBase64, proofHash);

          SecureByteBlock calculatedProofHash(32);
          if (calculatedProofHash.size() != proofHash.size()) return false;

          SHA256 shaProof;
          shaProof.Update((const BYTE *)"proof:", strlen("proof:"));
          shaProof.Update((const BYTE *)contactProfileSecret, strlen(contactProfileSecret));
          shaProof.Final(calculatedProofHash);

          if (0 != memcmp(calculatedProofHash, proofHash, proofHash.size())) return false;

          // this is the secret and it is verified
          mContactProfileSecret = contactProfileSecret;

        } catch (zsLib::XML::Exceptions::CheckFailed &) {
          return false;
        }
        return true;
      }
Exemple #2
0
void RandomPool::IncorporateEntropy(const byte *input, size_t length)
{
	SHA256 hash;
	hash.Update(m_key, 32);
	hash.Update(input, length);
	hash.Final(m_key);
	m_keySet = false;
}
Exemple #3
0
void PWSrand::AddEntropy(unsigned char *bytes, unsigned int numBytes)
{
  ASSERT(bytes != nullptr);

  SHA256 s;

  s.Update(K, sizeof(K));
  s.Update(bytes, numBytes);
  s.Final(K);
}
Exemple #4
0
int sha256_test()
{
    SHA256 sha;
    byte   hash[SHA256::DIGEST_SIZE];

    testVector test_sha[] =
    {
        testVector("abc",
                 "\xBA\x78\x16\xBF\x8F\x01\xCF\xEA\x41\x41\x40\xDE\x5D\xAE\x22"
                 "\x23\xB0\x03\x61\xA3\x96\x17\x7A\x9C\xB4\x10\xFF\x61\xF2\x00"
                 "\x15\xAD"),
        testVector("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
                 "\x24\x8D\x6A\x61\xD2\x06\x38\xB8\xE5\xC0\x26\x93\x0C\x3E\x60"
                 "\x39\xA3\x3C\xE4\x59\x64\xFF\x21\x67\xF6\xEC\xED\xD4\x19\xDB"
                 "\x06\xC1")
    };

    int times( sizeof(test_sha) / sizeof(testVector) );
    for (int i = 0; i < times; ++i) {
        sha.Update(test_sha[i].input_, test_sha[i].inLen_);
        sha.Final(hash);

        if (memcmp(hash, test_sha[i].output_, SHA256::DIGEST_SIZE) != 0)
            return -1 - i;
    }

    return 0;
}
Exemple #5
0
/**
 * Clear from clipboard data, that we put there previously
 * @return \c true, if we cleared our data, or stored data don't belong to us
*/
bool PWSclipboard::ClearCBData()
{
  wxMutexLocker clip(m_clipboardMutex);

  if (m_set && wxTheClipboard->Open()) {
    wxTextDataObject obj;
    if (wxTheClipboard->IsSupported(wxDF_UNICODETEXT) && wxTheClipboard->GetData(obj)) {
      StringX buf(obj.GetText().data(), obj.GetText().size());
      if (buf.length()) {
        // check if the data on the clipboard is the same we put there
        unsigned char digest[SHA256::HASHLEN];
        SHA256 ctx;

        ctx.Update(reinterpret_cast<const unsigned char *>(buf.c_str()), buf.length()*sizeof(wchar_t));
        ctx.Final(digest);
        if (memcmp(digest, m_digest, SHA256::HASHLEN) == 0) {
          // clear & reset
          wxTheClipboard->Clear();
          memset(m_digest, 0, SHA256::HASHLEN);
          m_set = false;
          // Also trash data in buffer and clipboard somehow?
          pws_os::Trace0(L"Cleared our data from buffer.\n");
        }
        else{
          pws_os::Trace0(L"Buffer doesn't contain our data. Nothing to clear.\n");
        }
      }
    }
    wxTheClipboard->Close();
  }
  return !m_set;
}
Exemple #6
0
PWSFileSig::PWSFileSig(const stringT &fname)
{
  const long THRESHOLD = 2048; // if file's longer than this, hash only head & tail

  m_length = 0;
  m_iErrorCode = PWSfile::SUCCESS;
  memset(m_digest, 0, sizeof(m_digest));
  FILE *fp = pws_os::FOpen(fname, _T("rb"));
  if (fp != NULL) {
    SHA256 hash;
    unsigned char buf[THRESHOLD];
    m_length = pws_os::fileLength(fp);
    // Minimum size for an empty V3 DB is 232 bytes - pre + post, no hdr or records!
    // Probably smaller for V1 & V2 DBs
    if (m_length > 232) {
      if (m_length <= THRESHOLD) {
        if (fread(buf, m_length, 1, fp) == 1) {
          hash.Update(buf, m_length);
          hash.Final(m_digest);
        }
      } else { // m_length > THRESHOLD
        if (fread(buf, THRESHOLD / 2, 1, fp) == 1 &&
            fseek(fp, -THRESHOLD / 2, SEEK_END) == 0 &&
            fread(buf + THRESHOLD / 2, THRESHOLD / 2, 1, fp) == 1) {
          hash.Update(buf, THRESHOLD);
          hash.Final(m_digest);
        }
      }
    } else {
      // File too small
      m_iErrorCode = PWSfile::TRUNCATED_FILE;
    }

    fclose(fp);
  } else {
    m_iErrorCode = PWSfile::CANT_OPEN_FILE;
  }
}
Exemple #7
0
PWSFileSig::PWSFileSig(const stringT &fname)
{
  const long THRESHOLD = 2048; // if file's longer than this, hash only head & tail

  m_length = 0;
  m_iErrorCode = PWSfile::SUCCESS;
  memset(m_digest, 0, sizeof(m_digest));
  FILE *fp = pws_os::FOpen(fname, _T("rb"));
  if (fp != nullptr) {
    SHA256 hash;
    m_length = pws_os::fileLength(fp);
    // Not the right place to be worried about min size, as this is format
    // version specific (and we're in PWSFile).
    // An empty file, though, should be failed.
    if (m_length > 0) {
      unsigned char buf[THRESHOLD];
      if (m_length <= THRESHOLD) {
        if (fread(buf, size_t(m_length), 1, fp) == 1) {
          hash.Update(buf, size_t(m_length));
          hash.Final(m_digest);
        }
      } else { // m_length > THRESHOLD
        if (fread(buf, THRESHOLD / 2, 1, fp) == 1 &&
            fseek(fp, -THRESHOLD / 2, SEEK_END) == 0 &&
            fread(buf + THRESHOLD / 2, THRESHOLD / 2, 1, fp) == 1) {
          hash.Update(buf, THRESHOLD);
          hash.Final(m_digest);
        }
      }
    } else { // Empty file
      m_iErrorCode = PWSfile::TRUNCATED_FILE;
    }

    fclose(fp);
  } else {
    m_iErrorCode = PWSfile::CANT_OPEN_FILE;
  }
}
Exemple #8
0
void PWSrand::NextRandBlock()
{
  SHA256 s;
  s.Update(K, sizeof(K));
  s.Final(R);
  unsigned int *Kp = reinterpret_cast<unsigned int *>(K);
  unsigned int *Rp = reinterpret_cast<unsigned int *>(R);
  const int N = SHA256::HASHLEN / sizeof(uint32);

  Kp[0]++;

  for (int32 i = 0; i < N; i++)
    Kp[i] += Rp[i];
}
Exemple #9
0
void PWSfile::HashRandom256(unsigned char *p256)
{
  /**
   * This is for random data that will be written to the file directly.
   * The idea is to avoid directly exposing our generated randomness
   * to the attacker, since this might expose state of the RNG.
   * Therefore, we'll hash the randomness.
   *
   * As the names imply, this works on 256 bit (32 byte) arrays.
   */
  PWSrand::GetInstance()->GetRandomData(p256, 32);
  SHA256 salter;
  salter.Update(p256, 32);
  salter.Final(p256);
}
Exemple #10
0
PWSrand::PWSrand()
  : ibRandomData(SHA256::HASHLEN)
{
  m_IsInternalPRNG = !pws_os::InitRandomDataFunction();

  SHA256 s;
  unsigned slen = 0;
  unsigned char *p;

  pws_os::GetRandomSeed(nullptr, slen);
  p = new unsigned char[slen];
  pws_os::GetRandomSeed(p, slen);
  s.Update(p, slen);
  delete[] p;
  s.Final(K);
}
Exemple #11
0
/**
 * Put text data to clipboard
 * @param[in] data data to store in clipboard
 * @param isSensitive if data sensitive, we remember its hash and will clear on ClearCBData() call
 * @return \c true, if we could open the clipboard and put the data
*/
bool PWSclipboard::SetData(const StringX &data)
{
  wxMutexLocker clip(m_clipboardMutex);

  bool res = false;
  if (wxTheClipboard->Open()) {
    res = wxTheClipboard->SetData(new wxTextDataObject(data.c_str()));
    wxTheClipboard->Close();
  }
  m_set = true;
  if (res) {
    // identify data in clipboard as ours, so as not to clear the wrong data later
    // of course, we don't want an extra copy of a password floating around
    // in memory, so we'll use the hash
    SHA256 ctx;
    const wchar_t *str = data.c_str();
    ctx.Update(reinterpret_cast<const unsigned char *>(str), data.length()*sizeof(wchar_t));
    ctx.Final(m_digest);
  }
  return res;
}
      //---------------------------------------------------------------------
      PeerContactProfilePtr PeerContactProfile::createExternalFromPrivateProfile(ElementPtr privateProfileElement)
      {
        if (!privateProfileElement) return PeerContactProfilePtr();

        privateProfileElement = (privateProfileElement->clone())->toElementChecked();

        static const char *contactProfileSkeleton =
        "<contactProfile version=\"0\">\n"
        " <private>\n"
        "  <salt />\n"
        "  <proof cipher=\"sha256/aes256\" />\n"
        "  <encryptedProfile cipher=\"sha256/aes256\" />\n"
        "  <contactProfileSecret cipher=\"sha256/aes256\" />\n"
        " </private>\n"
        "</contactProfile>";

        DocumentPtr contactProfileDoc = Document::create();
        contactProfileDoc->parse(contactProfileSkeleton);

        String contactID = services::IHelper::randomString(32);
        String contactProfileSecret = services::IHelper::randomString(32);

        // generate external profile
        {
          std::string contactSalt;

          // generate salt
          {
            AutoSeededRandomPool rng;

            SecureByteBlock contactSaltRaw(32);
            rng.GenerateBlock(contactSaltRaw, contactSaltRaw.size());
            contactSalt = convertToBase64(contactSaltRaw, contactSaltRaw.size());
          }

          ElementPtr contactProfileElement = contactProfileDoc->getFirstChildElementChecked();
          contactProfileElement->setAttribute("id", contactID);

          ElementPtr privateElement = contactProfileElement->getFirstChildElementChecked();
          ElementPtr saltElement = privateElement->getFirstChildElementChecked();
          TextPtr saltText = Text::create();
          saltText->setValue(contactSalt);
          saltElement->adoptAsLastChild(saltText);

          SecureByteBlock contactProofHash(32);

          SHA256 contactProof;
          contactProof.Update((const BYTE *)"proof:", strlen("proof:"));
          contactProof.Update((const BYTE *)contactProfileSecret.c_str(), contactProfileSecret.size());
          contactProof.Final(contactProofHash);

          String contactProofInBase64 = convertToBase64(contactProofHash, contactProofHash.size());

          ElementPtr proofElement = saltElement->getNextSiblingElementChecked();
          TextPtr proofText = Text::create();
          proofText->setValue(contactProofInBase64);
          proofElement->adoptAsLastChild(proofText);

          DocumentPtr privateProfileDocument = Document::create();
          privateProfileDocument->adoptAsLastChild(privateProfileElement);

          ULONG length = 0;
          boost::shared_array<char> output;
          output = privateProfileDocument->write(&length);

          ElementPtr encryptedProfileElement = proofElement->getNextSiblingElementChecked();
          String encryptedProfileString = encryptToBase64("profile", contactProfileSecret, contactSalt, (const BYTE *)(output.get()), length);
          TextPtr encryptProfileText = Text::create();
          encryptProfileText->setValue(encryptedProfileString);
          encryptedProfileElement->adoptAsLastChild(encryptProfileText);

          ElementPtr contactProfileSecretElement = encryptedProfileElement->getNextSiblingElementChecked();
          TextPtr contactProfileSecretText = Text::create();
          contactProfileSecretText->setValue(contactProfileSecret);
          contactProfileSecretElement->adoptAsLastChild(contactProfileSecretText);
        }

        PeerContactProfilePtr pThis(new PeerContactProfile);
        pThis->mThisWeak = pThis;
        pThis->mDocument = contactProfileDoc;
        pThis->mContactProfileSecret = contactProfileSecret;
        return pThis;
      }