toolkit/mozapps/update/common/pathhash.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/mozapps/update/common/pathhash.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,139 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include <windows.h>
     1.9 +#include <wincrypt.h>
    1.10 +#include "pathhash.h"
    1.11 +
    1.12 +
    1.13 +/**
    1.14 + * Converts a binary sequence into a hex string
    1.15 + *
    1.16 + * @param hash      The binary data sequence
    1.17 + * @param hashSize  The size of the binary data sequence
    1.18 + * @param hexString A buffer to store the hex string, must be of 
    1.19 + *                  size 2 * @hashSize
    1.20 +*/
    1.21 +static void
    1.22 +BinaryDataToHexString(const BYTE *hash, DWORD &hashSize, 
    1.23 +                      LPWSTR hexString)
    1.24 +{
    1.25 +  WCHAR *p = hexString;
    1.26 +  for (DWORD i = 0; i < hashSize; ++i) {
    1.27 +    wsprintfW(p, L"%.2x", hash[i]);
    1.28 +    p += 2;
    1.29 +  }
    1.30 +}
    1.31 +
    1.32 +/**
    1.33 + * Calculates an MD5 hash for the given input binary data
    1.34 + *
    1.35 + * @param  data     Any sequence of bytes
    1.36 + * @param  dataSize The number of bytes inside @data
    1.37 + * @param  hash     Output buffer to store hash, must be freed by the caller
    1.38 + * @param  hashSize The number of bytes in the output buffer
    1.39 + * @return TRUE on success
    1.40 +*/
    1.41 +static BOOL
    1.42 +CalculateMD5(const char *data, DWORD dataSize, 
    1.43 +             BYTE **hash, DWORD &hashSize)
    1.44 +{
    1.45 +  HCRYPTPROV hProv = 0;
    1.46 +  HCRYPTHASH hHash = 0;
    1.47 +
    1.48 +  if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL,
    1.49 +                           CRYPT_VERIFYCONTEXT)) {
    1.50 +    if (NTE_BAD_KEYSET != GetLastError()) {
    1.51 +      return FALSE;
    1.52 +    }
    1.53 + 
    1.54 +    // Maybe it doesn't exist, try to create it.
    1.55 +    if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_FULL, 
    1.56 +                             CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) {
    1.57 +      return FALSE;
    1.58 +    }
    1.59 +  }
    1.60 +
    1.61 +  if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
    1.62 +    return FALSE;
    1.63 +  }
    1.64 +
    1.65 +  if (!CryptHashData(hHash, reinterpret_cast<const BYTE*>(data), 
    1.66 +                    dataSize, 0)) {
    1.67 +    return FALSE;
    1.68 +  }
    1.69 +
    1.70 +  DWORD dwCount = sizeof(DWORD);
    1.71 +  if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, 
    1.72 +                        &dwCount, 0)) {
    1.73 +    return FALSE;
    1.74 +  }
    1.75 +  
    1.76 +  *hash = new BYTE[hashSize];
    1.77 +  ZeroMemory(*hash, hashSize);
    1.78 +  if (!CryptGetHashParam(hHash, HP_HASHVAL, *hash, &hashSize, 0)) {
    1.79 +    return FALSE;
    1.80 +  }
    1.81 +
    1.82 +  if (hHash) {
    1.83 +    CryptDestroyHash(hHash);
    1.84 +  }
    1.85 +
    1.86 +  if (hProv) {
    1.87 +    CryptReleaseContext(hProv,0);
    1.88 +  }
    1.89 +
    1.90 +  return TRUE;
    1.91 +}
    1.92 +
    1.93 +/**
    1.94 + * Converts a file path into a unique registry location for cert storage
    1.95 + *
    1.96 + * @param  filePath     The input file path to get a registry path from
    1.97 + * @param  registryPath A buffer to write the registry path to, must 
    1.98 + *                      be of size in WCHARs MAX_PATH + 1
    1.99 + * @return TRUE if successful
   1.100 +*/
   1.101 +BOOL
   1.102 +CalculateRegistryPathFromFilePath(const LPCWSTR filePath, 
   1.103 +                                  LPWSTR registryPath)
   1.104 +{
   1.105 +  size_t filePathLen = wcslen(filePath); 
   1.106 +  if (!filePathLen) {
   1.107 +    return FALSE;
   1.108 +  }
   1.109 +
   1.110 +  // If the file path ends in a slash, ignore that character
   1.111 +  if (filePath[filePathLen -1] == L'\\' || 
   1.112 +      filePath[filePathLen - 1] == L'/') {
   1.113 +    filePathLen--;
   1.114 +  }
   1.115 +
   1.116 +  // Copy in the full path into our own buffer.
   1.117 +  // Copying in the extra slash is OK because we calculate the hash
   1.118 +  // based on the filePathLen which excludes the slash.
   1.119 +  // +2 to account for the possibly trailing slash and the null terminator.
   1.120 +  WCHAR *lowercasePath = new WCHAR[filePathLen + 2];
   1.121 +  memset(lowercasePath, 0, (filePathLen + 2) * sizeof(WCHAR));
   1.122 +  wcsncpy(lowercasePath, filePath, filePathLen + 1);
   1.123 +  _wcslwr(lowercasePath);
   1.124 +
   1.125 +  BYTE *hash;
   1.126 +  DWORD hashSize = 0;
   1.127 +  if (!CalculateMD5(reinterpret_cast<const char*>(lowercasePath), 
   1.128 +                    filePathLen * 2, 
   1.129 +                    &hash, hashSize)) {
   1.130 +    delete[] lowercasePath;
   1.131 +    return FALSE;
   1.132 +  }
   1.133 +  delete[] lowercasePath;
   1.134 +
   1.135 +  LPCWSTR baseRegPath = L"SOFTWARE\\Mozilla\\"
   1.136 +    L"MaintenanceService\\";
   1.137 +  wcsncpy(registryPath, baseRegPath, MAX_PATH);
   1.138 +  BinaryDataToHexString(hash, hashSize, 
   1.139 +                        registryPath + wcslen(baseRegPath));
   1.140 +  delete[] hash;
   1.141 +  return TRUE;
   1.142 +}

mercurial