This source file includes following definitions.
- GetUserPassFromData
- GetUrlHash
- DecryptPasswords
#include "components/os_crypt/ie7_password_win.h"
#include <wincrypt.h>
#include <string>
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "base/sha1.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
namespace {
struct PreHeader {
DWORD pre_header_size;
DWORD header_size;
DWORD data_size;
};
struct Header {
char wick[4];
DWORD fixed_header_size;
DWORD item_count;
wchar_t two_letters[2];
DWORD unknown[2];
};
struct Entry {
DWORD offset;
FILETIME time_stamp;
DWORD string_length;
};
struct PasswordEntry {
PreHeader pre_header;
Header header;
Entry entry[1];
};
}
namespace ie7_password {
bool GetUserPassFromData(const std::vector<unsigned char>& data,
std::vector<DecryptedCredentials>* credentials) {
const PasswordEntry* information =
reinterpret_cast<const PasswordEntry*>(&data.front());
if (information->pre_header.pre_header_size != sizeof(PreHeader))
return false;
const int entry_count = information->header.item_count;
if (entry_count % 2)
return false;
if (information->header.fixed_header_size != sizeof(Header))
return false;
const uint8* offset_to_data = &data[0] +
information->pre_header.header_size +
information->pre_header.pre_header_size;
for (int i = 0; i < entry_count / 2; ++i) {
const Entry* user_entry = &information->entry[2*i];
const Entry* pass_entry = user_entry+1;
DecryptedCredentials c;
c.username = reinterpret_cast<const wchar_t*>(offset_to_data +
user_entry->offset);
c.password = reinterpret_cast<const wchar_t*>(offset_to_data +
pass_entry->offset);
credentials->push_back(c);
}
return true;
}
std::wstring GetUrlHash(const std::wstring& url) {
std::wstring lower_case_url = StringToLowerASCII(url);
std::string url_buffer(
reinterpret_cast<const char*>(lower_case_url.c_str()),
(lower_case_url.size() + 1) * sizeof(wchar_t));
std::string hash_bin = base::SHA1HashString(url_buffer);
std::wstring url_hash;
unsigned char checksum = 0;
for (size_t i = 0; i < hash_bin.size(); ++i) {
unsigned char hash_byte = static_cast<unsigned char>(hash_bin[i]);
checksum += hash_byte;
url_hash += base::StringPrintf(L"%2.2X", static_cast<unsigned>(hash_byte));
}
url_hash += base::StringPrintf(L"%2.2X", checksum);
return url_hash;
}
bool DecryptPasswords(const std::wstring& url,
const std::vector<unsigned char>& data,
std::vector<DecryptedCredentials>* credentials) {
std::wstring lower_case_url = StringToLowerASCII(url);
DATA_BLOB input = {0};
DATA_BLOB output = {0};
DATA_BLOB url_key = {0};
input.pbData = const_cast<unsigned char*>(&data.front());
input.cbData = static_cast<DWORD>((data.size()) *
sizeof(std::string::value_type));
url_key.pbData = reinterpret_cast<unsigned char*>(
const_cast<wchar_t*>(lower_case_url.data()));
url_key.cbData = static_cast<DWORD>((lower_case_url.size() + 1) *
sizeof(std::wstring::value_type));
if (CryptUnprotectData(&input, NULL, &url_key, NULL, NULL,
CRYPTPROTECT_UI_FORBIDDEN, &output)) {
std::vector<unsigned char> decrypted_data;
decrypted_data.resize(output.cbData);
memcpy(&decrypted_data.front(), output.pbData, output.cbData);
GetUserPassFromData(decrypted_data, credentials);
LocalFree(output.pbData);
return true;
}
return false;
}
}