Пример #1
0
int PWSfileV1V2::CheckPasskey(const StringX &filename,
                              const StringX &passkey, FILE *a_fd)
{
  FILE *fd = a_fd;
  if (fd == NULL) {
    fd = pws_os::FOpen(filename.c_str(), _T("rb"));
  }
  if (fd == NULL)
    return CANT_OPEN_FILE;

  unsigned char randstuff[StuffSize];
  unsigned char randhash[20];   // HashSize

  fread(randstuff, 1, 8, fd);
  randstuff[8] = randstuff[9] = '\0'; // Gross fugbix
  fread(randhash, 1, 20, fd);

  if (a_fd == NULL) // if we opened the file, we close it...
    fclose(fd);

  unsigned char temphash[20]; // HashSize
  GenRandhash(passkey, randstuff, temphash);

  if (0 != memcmp(reinterpret_cast<char *>(randhash), reinterpret_cast<char *>(temphash), MIN(sizeof(randhash), sizeof(temphash)))) { // HashSize
      return WRONG_PASSWORD;
  } else {
    return SUCCESS;
  }
}
Пример #2
0
bool PWSfile::Decrypt(const stringT &fn, const StringX &passwd, stringT &errmess)
{
  size_t len;
  unsigned char* buf = NULL;
  bool status = true;
  unsigned char salt[SaltLength];
  unsigned char ipthing[8];
  unsigned char randstuff[StuffSize];
  unsigned char randhash[SHA1::HASHLEN];
  unsigned char temphash[SHA1::HASHLEN];

  FILE *in = pws_os::FOpen(fn, _T("rb"));
  if (in == NULL) {
    status = false;
    goto exit;
  }

#ifdef KEEP_FILE_MODE_BWD_COMPAT
  uint32 i32;
  fread(&i32, 1, sizeof(uint32), in); // XXX portability issue
  len = i32;
#else
  fread(randstuff, 1, 8, in);
  randstuff[8] = randstuff[9] = TCHAR('\0'); // ugly bug workaround
  fread(randhash, 1, sizeof(randhash), in);

  GenRandhash(passwd, randstuff, temphash);
  if (memcmp(reinterpret_cast<char *>(randhash), reinterpret_cast<char *>(temphash), SHA1::HASHLEN) != 0) {
    fclose(in);
    LoadAString(errmess, IDSC_BADPASSWORD);
    return false;
  }
#endif // KEEP_FILE_MODE_BWD_COMPAT

  { // decryption in a block, since we use goto
    fread(salt,    1, SaltLength, in);
    fread(ipthing, 1, 8,          in);

    unsigned char dummyType;
    unsigned char *pwd = NULL;
    size_t passlen = 0;
    long file_len = pws_os::fileLength(in);
    ConvertString(passwd, pwd, passlen);
    Fish *fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<int &>(passlen), salt, SaltLength);
    trashMemory(pwd, passlen);
#ifdef UNICODE
    delete[] pwd; // gross - ConvertString allocates only if UNICODE.
#endif
    if (_readcbc(in, buf, len,dummyType, fish, ipthing, 0, file_len) == 0) {
      delete fish;
      delete[] buf; // if not yet allocated, delete[] NULL, which is OK
      return false;
    }
    delete fish;
    fclose(in);
  } // decrypt

  { // write decrypted data
    size_t suffix_len = CIPHERTEXT_SUFFIX.length();
    size_t filepath_len = fn.length();

    stringT out_fn = fn;
    out_fn = out_fn.substr(0,filepath_len - suffix_len);

    FILE *out = pws_os::FOpen(out_fn, _T("wb"));
    if (out != NULL) {
      size_t fret = fwrite(buf, 1, len, out);
      if (fret != len) {
        int save_errno = errno;
        fclose(out);
        errno = save_errno;
        goto exit;
      }
      if (fclose(out) != 0) {
        status = false;
        goto exit;
      }
    } else { // open failed
      status = false;
      goto exit;
    }
  } // write decrypted
 exit:
  if (!status)
    errmess = ErrorMessages();
  delete[] buf; // allocated by _readcbc
  return status;
}
Пример #3
0
bool PWSfile::Encrypt(const stringT &fn, const StringX &passwd, stringT &errmess)
{
  unsigned int len = 0;
  unsigned char* buf = NULL;
  Fish *fish = NULL;
  bool status = true;
  stringT out_fn;
  unsigned char *pwd = NULL;
  size_t passlen = 0;
  FILE *out = NULL;

  FILE *in = pws_os::FOpen(fn, _T("rb"));;
  if (in != NULL) {
    len = pws_os::fileLength(in);
    buf = new unsigned char[len];

    fread(buf, 1, len, in);
    if (ferror(in)) { // this is how to detect fread errors
      status = false;
      int save_error = errno;
      fclose(in);
      errno = save_error;
      goto exit;
    }
    if (fclose(in) != 0) {
      status = false;
      goto exit;
    }
  } else {
    status = false; goto exit;
  }

  out_fn = fn;
  out_fn += CIPHERTEXT_SUFFIX;

  out = pws_os::FOpen(out_fn, _T("wb"));
  if (out == NULL) {
    status = false; goto exit;
  }
#ifdef KEEP_FILE_MODE_BWD_COMPAT
  uint32 i32 = len;
  SAFE_FWRITE(&i32, 1, sizeof(uint32), out);
#else
  unsigned char randstuff[StuffSize];
  unsigned char randhash[SHA1::HASHLEN];   // HashSize
  PWSrand::GetInstance()->GetRandomData( randstuff, 8 );
  // miserable bug - have to fix this way to avoid breaking existing files
  randstuff[8] = randstuff[9] = TCHAR('\0');
  GenRandhash(passwd, randstuff, randhash);
  SAFE_FWRITE(randstuff, 1,  8, out);
  SAFE_FWRITE(randhash,  1, sizeof(randhash), out);
#endif // KEEP_FILE_MODE_BWD_COMPAT

  unsigned char thesalt[SaltLength];
  PWSrand::GetInstance()->GetRandomData( thesalt, SaltLength );
  SAFE_FWRITE(thesalt, 1, SaltLength, out);

  unsigned char ipthing[8];
  PWSrand::GetInstance()->GetRandomData( ipthing, 8 );
  SAFE_FWRITE(ipthing, 1, 8, out);

  ConvertString(passwd, pwd, passlen);
  fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<int &>(passlen), thesalt, SaltLength);
  trashMemory(pwd, passlen);
#ifdef UNICODE
  delete[] pwd; // gross - ConvertString allocates only if UNICODE.
#endif
  try {
    _writecbc(out, buf, len, 0, fish, ipthing);
  } catch (...) { // _writecbc throws an exception if it fails to write
    fclose(out);
    errno = EIO;
    status = false;
    goto exit;
  }
  status = (fclose(out) == 0);
 exit:
  if (!status)
    errmess = ErrorMessages();
  delete fish;
  delete[] buf;
  return status;
}
Пример #4
0
bool PWSfile::Decrypt(const stringT &fn, const StringX &passwd, stringT &errmess)
{
  ulong64 file_len;
  size_t len;
  unsigned char* buf = nullptr;
  bool status = true;
  unsigned char salt[SaltLength];
  unsigned char ipthing[8];
  unsigned char randstuff[StuffSize];
  unsigned char randhash[SHA1::HASHLEN];
  unsigned char temphash[SHA1::HASHLEN];

  FILE *in = pws_os::FOpen(fn, _T("rb"));
  if (in == nullptr) {
    status = false;
    goto exit;
  }

  file_len = pws_os::fileLength(in);

  if (file_len < (8 + sizeof(randhash) + 8 + SaltLength)) {
    fclose(in);
    LoadAString(errmess, IDSC_FILE_TOO_SHORT);
    return false;
  }

  fread(randstuff, 1, 8, in);
  randstuff[8] = randstuff[9] = TCHAR('\0'); // ugly bug workaround
  fread(randhash, 1, sizeof(randhash), in);

  GenRandhash(passwd, randstuff, temphash);
  if (memcmp(reinterpret_cast<char *>(randhash), reinterpret_cast<char *>(temphash), SHA1::HASHLEN) != 0) {
    fclose(in);
    LoadAString(errmess, IDSC_BADPASSWORD);
    return false;
  }

  { // decryption in a block, since we use goto
    fread(salt,    1, SaltLength, in);
    fread(ipthing, 1, 8,          in);

    unsigned char dummyType;
    unsigned char *pwd = nullptr;
    size_t passlen = 0;
    ConvertPasskey(passwd, pwd, passlen);
    Fish *fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<unsigned int &>(passlen), salt, SaltLength);
    trashMemory(pwd, passlen);
    delete[] pwd; // gross - ConvertPasskey allocates.
    if (_readcbc(in, buf, len,dummyType, fish, ipthing, 0, file_len) == 0) {
      delete fish;
      delete[] buf; // if not yet allocated, delete[] nullptr, which is OK
      return false;
    }
    delete fish;
    fclose(in);
  } // decrypt

  { // write decrypted data
    size_t suffix_len = CIPHERTEXT_SUFFIX.length();
    size_t filepath_len = fn.length();

    stringT out_fn = fn;
    out_fn = out_fn.substr(0,filepath_len - suffix_len);

    FILE *out = pws_os::FOpen(out_fn, _T("wb"));
    if (out != nullptr) {
      size_t fret = fwrite(buf, 1, len, out);
      if (fret != len) {
        int save_errno = errno;
        fclose(out);
        errno = save_errno;
        goto exit;
      }
      if (fclose(out) != 0) {
        status = false;
        goto exit;
      }
    } else { // open failed
      status = false;
      goto exit;
    }
  } // write decrypted
 exit:
  if (!status)
    errmess = ErrorMessages();
  delete[] buf; // allocated by _readcbc
  return status;
}
Пример #5
0
bool PWSfile::Encrypt(const stringT &fn, const StringX &passwd, stringT &errmess)
{
  ulong64 len = 0;
  size_t slen = 0;
  unsigned char* buf = nullptr;
  Fish *fish = nullptr;
  bool status = true;
  const stringT out_fn = fn + CIPHERTEXT_SUFFIX;
  unsigned char *pwd = nullptr;
  size_t passlen = 0;
  FILE *out = nullptr;

  FILE *in = pws_os::FOpen(fn, _T("rb"));
  if (in == nullptr) {
    status = false; goto exit;
  }

  len = pws_os::fileLength(in);

  if (len > std::numeric_limits<uint32>::max()) {
    fclose(in);
    errno = EFBIG;
    status = false;
    goto exit;
  }

  slen = static_cast<size_t>(len);
  buf = new unsigned char[slen];

  fread(buf, 1, slen, in);
  if (ferror(in)) { // this is how to detect fread errors
    status = false;
    int save_error = errno;
    fclose(in);
    errno = save_error;
    goto exit;
  }
  if (fclose(in) != 0) {
    status = false;
    goto exit;
  }

  out = pws_os::FOpen(out_fn, _T("wb"));
  if (out == nullptr) {
    status = false; goto exit;
  }
  unsigned char randstuff[StuffSize];
  unsigned char randhash[SHA1::HASHLEN];   // HashSize
  PWSrand::GetInstance()->GetRandomData( randstuff, 8 );
  // miserable bug - have to fix this way to avoid breaking existing files
  randstuff[8] = randstuff[9] = TCHAR('\0');
  GenRandhash(passwd, randstuff, randhash);
  SAFE_FWRITE(randstuff, 1,  8, out);
  SAFE_FWRITE(randhash,  1, sizeof(randhash), out);

  unsigned char thesalt[SaltLength];
  PWSrand::GetInstance()->GetRandomData( thesalt, SaltLength );
  SAFE_FWRITE(thesalt, 1, SaltLength, out);

  unsigned char ipthing[8];
  PWSrand::GetInstance()->GetRandomData( ipthing, 8 );
  SAFE_FWRITE(ipthing, 1, 8, out);

  ConvertPasskey(passwd, pwd, passlen);
  fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<unsigned int &>(passlen), thesalt, SaltLength);
  trashMemory(pwd, passlen);
  delete[] pwd; // gross - ConvertPasskey allocates.
  try {
    _writecbc(out, buf, slen, 0, fish, ipthing);
  } catch (...) { // _writecbc throws an exception if it fails to write
    fclose(out);
    errno = EIO;
    status = false;
    goto exit;
  }
  status = (fclose(out) == 0);
 exit:
  if (!status)
    errmess = ErrorMessages();
  delete fish;
  delete[] buf;
  return status;
}
Пример #6
0
int PWSfileV1V2::Open(const StringX &passkey)
{
  int status = SUCCESS;

  ASSERT(m_curversion == V17 || m_curversion == V20);

  m_passkey = passkey;
  FOpen();
  if (m_fd == NULL)
    return CANT_OPEN_FILE;

  LPCTSTR passstr = m_passkey.c_str();
  size_t passLen = passkey.length();
  unsigned char *pstr;

#ifdef UNICODE
  size_t pstr_len = 3 * passLen;
  pstr = new unsigned char[pstr_len];
  size_t len = pws_os::wcstombs(reinterpret_cast<char *>(pstr), 3 * passLen, passstr, passLen, false);
  ASSERT(len != 0);
  // hack around OS-dependent semantics - too widespread to fix systematically :-(
  pstr[len < pstr_len ? len : pstr_len - 1] = '\0';
  passLen = strlen(reinterpret_cast<const char *>(pstr));
#else
  pstr = reinterpret_cast<unsigned char *>(passstr);
#endif

  if (m_rw == Write) {
    // Following used to verify passkey against file's passkey
    unsigned char randstuff[StuffSize];
    unsigned char randhash[20];   // HashSize

    PWSrand::GetInstance()->GetRandomData( randstuff, 8 );
    randstuff[8] = randstuff[9] = TCHAR('\0');
    GenRandhash(m_passkey, randstuff, randhash);

    SAFE_FWRITE(randstuff, 1, 8, m_fd);
    SAFE_FWRITE(randhash, 1, 20, m_fd);

    PWSrand::GetInstance()->GetRandomData(m_salt, SaltLength);

    SAFE_FWRITE(m_salt, 1, SaltLength, m_fd);

    PWSrand::GetInstance()->GetRandomData( m_ipthing, 8);
    SAFE_FWRITE(m_ipthing, 1, 8, m_fd);

    m_fish = BlowFish::MakeBlowFish(pstr, reinterpret_cast<int &>(passLen),
                                    m_salt, SaltLength);
    if (m_curversion == V20) {
      status = WriteV2Header();
    }
  } else { // open for read
    status = CheckPasskey(m_filename, m_passkey, m_fd);
    if (status != SUCCESS) {
#ifdef UNICODE
      trashMemory(pstr, pstr_len);
      delete[] pstr;
#endif
      Close();
      return status;
    }
    fread(m_salt, 1, SaltLength, m_fd);
    fread(m_ipthing, 1, 8, m_fd);

    m_fish = BlowFish::MakeBlowFish(pstr, reinterpret_cast<int &>(passLen),
                                    m_salt, SaltLength);
    if (m_curversion == V20)
      status = ReadV2Header();
  } // read mode
 exit:
  if (status != SUCCESS)
    Close();
#ifdef UNICODE
  trashMemory(pstr, pstr_len);
  delete[] pstr;
#endif
  return status;
}