hwid_checker.cc revision 5e3f23d412006dc4db4e659864679f29341e113f
1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/login/hwid_checker.h" 6 7#include <cstdio> 8 9#include "base/chromeos/chromeos_version.h" 10#include "base/command_line.h" 11#include "base/logging.h" 12#include "base/strings/string_util.h" 13#include "chrome/browser/chromeos/system/statistics_provider.h" 14#include "chrome/common/chrome_switches.h" 15#include "chromeos/chromeos_switches.h" 16#include "third_party/re2/re2/re2.h" 17#include "third_party/zlib/zlib.h" 18 19namespace { 20 21unsigned CalculateCRC32(const std::string& data) { 22 return static_cast<unsigned>(crc32( 23 0, 24 reinterpret_cast<const Bytef*>(data.c_str()), 25 data.length())); 26} 27 28std::string CalculateHWIDv2Checksum(const std::string& data) { 29 unsigned crc32 = CalculateCRC32(data); 30 // We take four least significant decimal digits of CRC-32. 31 char checksum[5]; 32 int snprintf_result = 33 snprintf(checksum, 5, "%04u", crc32 % 10000); 34 LOG_ASSERT(snprintf_result == 4); 35 return checksum; 36} 37 38bool IsCorrectHWIDv2(const std::string& hwid) { 39 std::string body; 40 std::string checksum; 41 if (!RE2::FullMatch(hwid, "([\\s\\S]*) (\\d{4})", &body, &checksum)) 42 return false; 43 return CalculateHWIDv2Checksum(body) == checksum; 44} 45 46std::string CalculateHWIDv3Checksum(const std::string& data) { 47 static const char base32_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 48 unsigned crc32 = CalculateCRC32(data); 49 // We take 10 least significant bits of CRC-32 and encode them in 2 characters 50 // using Base32 alphabet. 51 std::string checksum; 52 checksum += base32_alphabet[(crc32 >> 5) & 0x1f]; 53 checksum += base32_alphabet[crc32 & 0x1f]; 54 return checksum; 55} 56 57bool IsCorrectHWIDv3(const std::string& hwid) { 58 std::string bom; 59 if (!RE2::FullMatch(hwid, "[A-Z0-9]+ ((?:[A-Z2-7]{4}-)*[A-Z2-7]{1,4})", &bom)) 60 return false; 61 if (bom.length() < 2) 62 return false; 63 std::string hwid_without_dashes; 64 RemoveChars(hwid, "-", &hwid_without_dashes); 65 LOG_ASSERT(hwid_without_dashes.length() >= 2); 66 std::string not_checksum = 67 hwid_without_dashes.substr(0, hwid_without_dashes.length() - 2); 68 std::string checksum = 69 hwid_without_dashes.substr(hwid_without_dashes.length() - 2); 70 return CalculateHWIDv3Checksum(not_checksum) == checksum; 71} 72 73} // anonymous namespace 74 75namespace chromeos { 76 77bool IsHWIDCorrect(const std::string& hwid) { 78 return IsCorrectHWIDv2(hwid) || IsCorrectHWIDv3(hwid); 79} 80 81bool IsMachineHWIDCorrect() { 82#if !defined(GOOGLE_CHROME_BUILD) 83 return true; 84#endif 85 CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 86 if (cmd_line->HasSwitch(::switches::kTestType) || 87 cmd_line->HasSwitch(chromeos::switches::kSkipHWIDCheck)) 88 return true; 89 if (!base::chromeos::IsRunningOnChromeOS()) 90 return true; 91 std::string hwid; 92 chromeos::system::StatisticsProvider* stats = 93 chromeos::system::StatisticsProvider::GetInstance(); 94 if (!stats->GetMachineStatistic("hardware_class", &hwid)) { 95 LOG(ERROR) << "Couldn't get machine statistic 'hardware_class'."; 96 return false; 97 } 98 if (!chromeos::IsHWIDCorrect(hwid)) { 99 LOG(ERROR) << "Machine has malformed HWID '" << hwid << "'."; 100 return false; 101 } 102 return true; 103} 104 105} // namespace chromeos 106 107