hwid_checker.cc revision 5e3f23d412006dc4db4e659864679f29341e113f
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/login/hwid_checker.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cstdio> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/chromeos/chromeos_version.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/chromeos/system/statistics_provider.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chromeos/chromeos_switches.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/re2/re2/re2.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/zlib/zlib.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)unsigned CalculateCRC32(const std::string& data) { 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return static_cast<unsigned>(crc32( 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<const Bytef*>(data.c_str()), 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.length())); 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string CalculateHWIDv2Checksum(const std::string& data) { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned crc32 = CalculateCRC32(data); 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We take four least significant decimal digits of CRC-32. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char checksum[5]; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int snprintf_result = 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) snprintf(checksum, 5, "%04u", crc32 % 10000); 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG_ASSERT(snprintf_result == 4); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return checksum; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsCorrectHWIDv2(const std::string& hwid) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string body; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string checksum; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!RE2::FullMatch(hwid, "([\\s\\S]*) (\\d{4})", &body, &checksum)) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CalculateHWIDv2Checksum(body) == checksum; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string CalculateHWIDv3Checksum(const std::string& data) { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const char base32_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned crc32 = CalculateCRC32(data); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We take 10 least significant bits of CRC-32 and encode them in 2 characters 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // using Base32 alphabet. 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string checksum; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) checksum += base32_alphabet[(crc32 >> 5) & 0x1f]; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) checksum += base32_alphabet[crc32 & 0x1f]; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return checksum; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsCorrectHWIDv3(const std::string& hwid) { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string bom; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!RE2::FullMatch(hwid, "[A-Z0-9]+ ((?:[A-Z2-7]{4}-)*[A-Z2-7]{1,4})", &bom)) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (bom.length() < 2) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string hwid_without_dashes; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveChars(hwid, "-", &hwid_without_dashes); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG_ASSERT(hwid_without_dashes.length() >= 2); 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string not_checksum = 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hwid_without_dashes.substr(0, hwid_without_dashes.length() - 2); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string checksum = 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hwid_without_dashes.substr(hwid_without_dashes.length() - 2); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CalculateHWIDv3Checksum(not_checksum) == checksum; 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // anonymous namespace 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsHWIDCorrect(const std::string& hwid) { 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return IsCorrectHWIDv2(hwid) || IsCorrectHWIDv3(hwid); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsMachineHWIDCorrect() { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(GOOGLE_CHROME_BUILD) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (cmd_line->HasSwitch(::switches::kTestType) || 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cmd_line->HasSwitch(chromeos::switches::kSkipHWIDCheck)) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!base::chromeos::IsRunningOnChromeOS()) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string hwid; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::system::StatisticsProvider* stats = 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chromeos::system::StatisticsProvider::GetInstance(); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!stats->GetMachineStatistic("hardware_class", &hwid)) { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Couldn't get machine statistic 'hardware_class'."; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!chromeos::IsHWIDCorrect(hwid)) { 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Machine has malformed HWID '" << hwid << "'."; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace chromeos 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 107