Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | #include <windows.h> |
michael@0 | 6 | #include <wincrypt.h> |
michael@0 | 7 | #include "pathhash.h" |
michael@0 | 8 | |
michael@0 | 9 | |
michael@0 | 10 | /** |
michael@0 | 11 | * Converts a binary sequence into a hex string |
michael@0 | 12 | * |
michael@0 | 13 | * @param hash The binary data sequence |
michael@0 | 14 | * @param hashSize The size of the binary data sequence |
michael@0 | 15 | * @param hexString A buffer to store the hex string, must be of |
michael@0 | 16 | * size 2 * @hashSize |
michael@0 | 17 | */ |
michael@0 | 18 | static void |
michael@0 | 19 | BinaryDataToHexString(const BYTE *hash, DWORD &hashSize, |
michael@0 | 20 | LPWSTR hexString) |
michael@0 | 21 | { |
michael@0 | 22 | WCHAR *p = hexString; |
michael@0 | 23 | for (DWORD i = 0; i < hashSize; ++i) { |
michael@0 | 24 | wsprintfW(p, L"%.2x", hash[i]); |
michael@0 | 25 | p += 2; |
michael@0 | 26 | } |
michael@0 | 27 | } |
michael@0 | 28 | |
michael@0 | 29 | /** |
michael@0 | 30 | * Calculates an MD5 hash for the given input binary data |
michael@0 | 31 | * |
michael@0 | 32 | * @param data Any sequence of bytes |
michael@0 | 33 | * @param dataSize The number of bytes inside @data |
michael@0 | 34 | * @param hash Output buffer to store hash, must be freed by the caller |
michael@0 | 35 | * @param hashSize The number of bytes in the output buffer |
michael@0 | 36 | * @return TRUE on success |
michael@0 | 37 | */ |
michael@0 | 38 | static BOOL |
michael@0 | 39 | CalculateMD5(const char *data, DWORD dataSize, |
michael@0 | 40 | BYTE **hash, DWORD &hashSize) |
michael@0 | 41 | { |
michael@0 | 42 | HCRYPTPROV hProv = 0; |
michael@0 | 43 | HCRYPTHASH hHash = 0; |
michael@0 | 44 | |
michael@0 | 45 | if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL, |
michael@0 | 46 | CRYPT_VERIFYCONTEXT)) { |
michael@0 | 47 | if (NTE_BAD_KEYSET != GetLastError()) { |
michael@0 | 48 | return FALSE; |
michael@0 | 49 | } |
michael@0 | 50 | |
michael@0 | 51 | // Maybe it doesn't exist, try to create it. |
michael@0 | 52 | if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL, |
michael@0 | 53 | CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) { |
michael@0 | 54 | return FALSE; |
michael@0 | 55 | } |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { |
michael@0 | 59 | return FALSE; |
michael@0 | 60 | } |
michael@0 | 61 | |
michael@0 | 62 | if (!CryptHashData(hHash, reinterpret_cast<const BYTE*>(data), |
michael@0 | 63 | dataSize, 0)) { |
michael@0 | 64 | return FALSE; |
michael@0 | 65 | } |
michael@0 | 66 | |
michael@0 | 67 | DWORD dwCount = sizeof(DWORD); |
michael@0 | 68 | if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, |
michael@0 | 69 | &dwCount, 0)) { |
michael@0 | 70 | return FALSE; |
michael@0 | 71 | } |
michael@0 | 72 | |
michael@0 | 73 | *hash = new BYTE[hashSize]; |
michael@0 | 74 | ZeroMemory(*hash, hashSize); |
michael@0 | 75 | if (!CryptGetHashParam(hHash, HP_HASHVAL, *hash, &hashSize, 0)) { |
michael@0 | 76 | return FALSE; |
michael@0 | 77 | } |
michael@0 | 78 | |
michael@0 | 79 | if (hHash) { |
michael@0 | 80 | CryptDestroyHash(hHash); |
michael@0 | 81 | } |
michael@0 | 82 | |
michael@0 | 83 | if (hProv) { |
michael@0 | 84 | CryptReleaseContext(hProv,0); |
michael@0 | 85 | } |
michael@0 | 86 | |
michael@0 | 87 | return TRUE; |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | /** |
michael@0 | 91 | * Converts a file path into a unique registry location for cert storage |
michael@0 | 92 | * |
michael@0 | 93 | * @param filePath The input file path to get a registry path from |
michael@0 | 94 | * @param registryPath A buffer to write the registry path to, must |
michael@0 | 95 | * be of size in WCHARs MAX_PATH + 1 |
michael@0 | 96 | * @return TRUE if successful |
michael@0 | 97 | */ |
michael@0 | 98 | BOOL |
michael@0 | 99 | CalculateRegistryPathFromFilePath(const LPCWSTR filePath, |
michael@0 | 100 | LPWSTR registryPath) |
michael@0 | 101 | { |
michael@0 | 102 | size_t filePathLen = wcslen(filePath); |
michael@0 | 103 | if (!filePathLen) { |
michael@0 | 104 | return FALSE; |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | // If the file path ends in a slash, ignore that character |
michael@0 | 108 | if (filePath[filePathLen -1] == L'\\' || |
michael@0 | 109 | filePath[filePathLen - 1] == L'/') { |
michael@0 | 110 | filePathLen--; |
michael@0 | 111 | } |
michael@0 | 112 | |
michael@0 | 113 | // Copy in the full path into our own buffer. |
michael@0 | 114 | // Copying in the extra slash is OK because we calculate the hash |
michael@0 | 115 | // based on the filePathLen which excludes the slash. |
michael@0 | 116 | // +2 to account for the possibly trailing slash and the null terminator. |
michael@0 | 117 | WCHAR *lowercasePath = new WCHAR[filePathLen + 2]; |
michael@0 | 118 | memset(lowercasePath, 0, (filePathLen + 2) * sizeof(WCHAR)); |
michael@0 | 119 | wcsncpy(lowercasePath, filePath, filePathLen + 1); |
michael@0 | 120 | _wcslwr(lowercasePath); |
michael@0 | 121 | |
michael@0 | 122 | BYTE *hash; |
michael@0 | 123 | DWORD hashSize = 0; |
michael@0 | 124 | if (!CalculateMD5(reinterpret_cast<const char*>(lowercasePath), |
michael@0 | 125 | filePathLen * 2, |
michael@0 | 126 | &hash, hashSize)) { |
michael@0 | 127 | delete[] lowercasePath; |
michael@0 | 128 | return FALSE; |
michael@0 | 129 | } |
michael@0 | 130 | delete[] lowercasePath; |
michael@0 | 131 | |
michael@0 | 132 | LPCWSTR baseRegPath = L"SOFTWARE\\Mozilla\\" |
michael@0 | 133 | L"MaintenanceService\\"; |
michael@0 | 134 | wcsncpy(registryPath, baseRegPath, MAX_PATH); |
michael@0 | 135 | BinaryDataToHexString(hash, hashSize, |
michael@0 | 136 | registryPath + wcslen(baseRegPath)); |
michael@0 | 137 | delete[] hash; |
michael@0 | 138 | return TRUE; |
michael@0 | 139 | } |