1 // Copyright (c) 2012 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 "rlz/lib/machine_id.h" 6 7 #include "base/sha1.h" 8 #include "rlz/lib/assert.h" 9 #include "rlz/lib/crc8.h" 10 #include "rlz/lib/string_utils.h" 11 12 namespace rlz_lib { 13 14 bool GetMachineId(std::string* machine_id) { 15 if (!machine_id) 16 return false; 17 18 static std::string calculated_id; 19 static bool calculated = false; 20 if (calculated) { 21 *machine_id = calculated_id; 22 return true; 23 } 24 25 string16 sid_string; 26 int volume_id; 27 if (!GetRawMachineId(&sid_string, &volume_id)) 28 return false; 29 30 if (!testing::GetMachineIdImpl(sid_string, volume_id, machine_id)) 31 return false; 32 33 calculated = true; 34 calculated_id = *machine_id; 35 return true; 36 } 37 38 namespace testing { 39 40 bool GetMachineIdImpl(const string16& sid_string, 41 int volume_id, 42 std::string* machine_id) { 43 machine_id->clear(); 44 45 // The ID should be the SID hash + the Hard Drive SNo. + checksum byte. 46 static const int kSizeWithoutChecksum = base::kSHA1Length + sizeof(int); 47 std::basic_string<unsigned char> id_binary(kSizeWithoutChecksum + 1, 0); 48 49 if (!sid_string.empty()) { 50 // In order to be compatible with the old version of RLZ, the hash of the 51 // SID must be done with all the original bytes from the unicode string. 52 // However, the chromebase SHA1 hash function takes only an std::string as 53 // input, so the unicode string needs to be converted to std::string 54 // "as is". 55 size_t byte_count = sid_string.size() * sizeof(string16::value_type); 56 const char* buffer = reinterpret_cast<const char*>(sid_string.c_str()); 57 std::string sid_string_buffer(buffer, byte_count); 58 59 // Note that digest can have embedded nulls. 60 std::string digest(base::SHA1HashString(sid_string_buffer)); 61 VERIFY(digest.size() == base::kSHA1Length); 62 std::copy(digest.begin(), digest.end(), id_binary.begin()); 63 } 64 65 // Convert from int to binary (makes big-endian). 66 for (size_t i = 0; i < sizeof(int); i++) { 67 int shift_bits = 8 * (sizeof(int) - i - 1); 68 id_binary[base::kSHA1Length + i] = static_cast<unsigned char>( 69 (volume_id >> shift_bits) & 0xFF); 70 } 71 72 // Append the checksum byte. 73 if (!sid_string.empty() || (0 != volume_id)) 74 rlz_lib::Crc8::Generate(id_binary.c_str(), 75 kSizeWithoutChecksum, 76 &id_binary[kSizeWithoutChecksum]); 77 78 return rlz_lib::BytesToString( 79 id_binary.c_str(), kSizeWithoutChecksum + 1, machine_id); 80 } 81 82 } // namespace testing 83 84 } // namespace rlz_lib 85