1// Copyright 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/extensions/api/music_manager_private/device_id.h" 6 7#include "base/bind.h" 8#include "base/strings/string_number_conversions.h" 9#include "base/strings/string_util.h" 10#include "content/public/browser/browser_thread.h" 11#include "crypto/hmac.h" 12 13namespace { 14 15using extensions::api::DeviceId; 16 17// Compute HMAC-SHA256(|key|, |text|) as a string. 18bool ComputeHmacSha256(const std::string& key, 19 const std::string& text, 20 std::string* signature_return) { 21 crypto::HMAC hmac(crypto::HMAC::SHA256); 22 const size_t digest_length = hmac.DigestLength(); 23 std::vector<uint8> digest(digest_length); 24 bool result = hmac.Init(key) && 25 hmac.Sign(text, &digest[0], digest.size()); 26 if (result) { 27 *signature_return = base::StringToLowerASCII( 28 base::HexEncode(digest.data(), digest.size())); 29 } 30 return result; 31} 32 33void GetRawDeviceIdCallback(const std::string& extension_id, 34 const DeviceId::IdCallback& callback, 35 const std::string& raw_device_id) { 36 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 37 38 if (raw_device_id.empty()) { 39 callback.Run(""); 40 return; 41 } 42 43 std::string device_id; 44 if (!ComputeHmacSha256(raw_device_id, extension_id, &device_id)) { 45 DLOG(ERROR) << "Error while computing HMAC-SHA256 of device id."; 46 callback.Run(""); 47 return; 48 } 49 callback.Run(device_id); 50} 51 52bool IsValidMacAddressImpl(const void* bytes, size_t size) { 53 const size_t MAC_LENGTH = 6; 54 const size_t OUI_LENGTH = 3; 55 struct InvalidMacEntry { 56 size_t size; 57 unsigned char address[MAC_LENGTH]; 58 }; 59 60 // VPN, virtualization, tethering, bluetooth, etc. 61 static InvalidMacEntry invalidAddresses[] = { 62 // Empty address 63 {MAC_LENGTH, {0, 0, 0, 0, 0, 0}}, 64 // VMware 65 {OUI_LENGTH, {0x00, 0x50, 0x56}}, 66 {OUI_LENGTH, {0x00, 0x05, 0x69}}, 67 {OUI_LENGTH, {0x00, 0x0c, 0x29}}, 68 {OUI_LENGTH, {0x00, 0x1c, 0x14}}, 69 // VirtualBox 70 {OUI_LENGTH, {0x08, 0x00, 0x27}}, 71 // PdaNet 72 {MAC_LENGTH, {0x00, 0x26, 0x37, 0xbd, 0x39, 0x42}}, 73 // Cisco AnyConnect VPN 74 {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x7a, 0x00}}, 75 // Marvell sometimes uses this as a dummy address 76 {MAC_LENGTH, {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}}, 77 // Apple uses this across machines for Bluetooth ethernet adapters. 78 {MAC_LENGTH-1, {0x65, 0x90, 0x07, 0x42, 0xf1}}, 79 // Juniper uses this for their Virtual Adapter, the other 4 bytes are 80 // reassigned at every boot. 00-ff-xx is not assigned to anyone. 81 {2, {0x00, 0xff}}, 82 // T-Mobile Wireless Ethernet 83 {MAC_LENGTH, {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}}, 84 // Generic Bluetooth device 85 {MAC_LENGTH, {0x00, 0x15, 0x83, 0x3d, 0x0a, 0x57}}, 86 // RAS Async Adapter 87 {MAC_LENGTH, {0x20, 0x41, 0x53, 0x59, 0x4e, 0xff}}, 88 // Qualcomm USB ethernet adapter 89 {MAC_LENGTH, {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00}}, 90 // Windows VPN 91 {MAC_LENGTH, {0x00, 0x53, 0x45, 0x00, 0x00, 0x00}}, 92 // Bluetooth 93 {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x08, 0x30}}, 94 {MAC_LENGTH, {0x00, 0x1b, 0x10, 0x00, 0x2a, 0xec}}, 95 {MAC_LENGTH, {0x00, 0x15, 0x83, 0x15, 0xa3, 0x10}}, 96 {MAC_LENGTH, {0x00, 0x15, 0x83, 0x07, 0xC6, 0x5A}}, 97 {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x02, 0x00}}, 98 {MAC_LENGTH, {0x00, 0x1f, 0x81, 0x00, 0x02, 0xdd}}, 99 // Ceton TV tuner 100 {MAC_LENGTH, {0x00, 0x22, 0x2c, 0xff, 0xff, 0xff}}, 101 // Check Point VPN 102 {MAC_LENGTH, {0x54, 0x55, 0x43, 0x44, 0x52, 0x09}}, 103 {MAC_LENGTH, {0x54, 0xEF, 0x14, 0x71, 0xE4, 0x0E}}, 104 {MAC_LENGTH, {0x54, 0xBA, 0xC6, 0xFF, 0x74, 0x10}}, 105 // Cisco VPN 106 {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x7a, 0x00}}, 107 // Cisco VPN 108 {MAC_LENGTH, {0x00, 0x05, 0x9a, 0x3c, 0x78, 0x00}}, 109 // Intel USB cell modem 110 {MAC_LENGTH, {0x00, 0x1e, 0x10, 0x1f, 0x00, 0x01}}, 111 // Microsoft tethering 112 {MAC_LENGTH, {0x80, 0x00, 0x60, 0x0f, 0xe8, 0x00}}, 113 // Nortel VPN 114 {MAC_LENGTH, {0x44, 0x45, 0x53, 0x54, 0x42, 0x00}}, 115 // AEP VPN 116 {MAC_LENGTH, {0x00, 0x30, 0x70, 0x00, 0x00, 0x01}}, 117 // Positive VPN 118 {MAC_LENGTH, {0x00, 0x02, 0x03, 0x04, 0x05, 0x06}}, 119 // Bluetooth 120 {MAC_LENGTH, {0x00, 0x15, 0x83, 0x0B, 0x13, 0xC0}}, 121 // Kerio Virtual Network Adapter 122 {MAC_LENGTH, {0x44, 0x45, 0x53, 0x54, 0x4f, 0x53}}, 123 // Sierra Wireless cell modems. 124 {OUI_LENGTH, {0x00, 0xA0, 0xD5}}, 125 // FRITZ!web DSL 126 {MAC_LENGTH, {0x00, 0x04, 0x0E, 0xFF, 0xFF, 0xFF}}, 127 // VirtualPC 128 {MAC_LENGTH, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, 129 // Bluetooth 130 {MAC_LENGTH, {0x00, 0x1F, 0x81, 0x00, 0x01, 0x00}}, 131 {MAC_LENGTH, {0x00, 0x30, 0x91, 0x10, 0x00, 0x26}}, 132 {MAC_LENGTH, {0x00, 0x25, 0x00, 0x5A, 0xC3, 0xD0}}, 133 {MAC_LENGTH, {0x00, 0x15, 0x83, 0x0C, 0xBF, 0xEB}}, 134 // Huawei cell modem 135 {MAC_LENGTH, {0x58, 0x2C, 0x80, 0x13, 0x92, 0x63}}, 136 // Fortinet VPN 137 {OUI_LENGTH, {0x00, 0x09, 0x0F}}, 138 // Realtek 139 {MAC_LENGTH, {0x00, 0x00, 0x00, 0x00, 0x00, 0x30}}, 140 // Other rare dupes. 141 {MAC_LENGTH, {0x00, 0x11, 0xf5, 0x0d, 0x8a, 0xe8}}, // Atheros 142 {MAC_LENGTH, {0x00, 0x20, 0x07, 0x01, 0x16, 0x06}}, // Atheros 143 {MAC_LENGTH, {0x0d, 0x0b, 0x00, 0x00, 0xe0, 0x00}}, // Atheros 144 {MAC_LENGTH, {0x90, 0x4c, 0xe5, 0x0b, 0xc8, 0x8e}}, // Atheros 145 {MAC_LENGTH, {0x00, 0x1c, 0x23, 0x38, 0x49, 0xa4}}, // Broadcom 146 {MAC_LENGTH, {0x00, 0x12, 0x3f, 0x82, 0x7c, 0x32}}, // Broadcom 147 {MAC_LENGTH, {0x00, 0x11, 0x11, 0x32, 0xc3, 0x77}}, // Broadcom 148 {MAC_LENGTH, {0x00, 0x24, 0xd6, 0xae, 0x3e, 0x39}}, // Microsoft 149 {MAC_LENGTH, {0x00, 0x0f, 0xb0, 0x3a, 0xb4, 0x80}}, // Realtek 150 {MAC_LENGTH, {0x08, 0x10, 0x74, 0xa1, 0xda, 0x1b}}, // Realtek 151 {MAC_LENGTH, {0x00, 0x21, 0x9b, 0x2a, 0x0a, 0x9c}}, // Realtek 152 }; 153 154 if (size != MAC_LENGTH) { 155 return false; 156 } 157 158 if (static_cast<const unsigned char *>(bytes)[0] & 0x02) { 159 // Locally administered. 160 return false; 161 } 162 163 // Note: Use ARRAYSIZE_UNSAFE() instead of arraysize() because InvalidMacEntry 164 // is declared inside this function. 165 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(invalidAddresses); ++i) { 166 size_t count = invalidAddresses[i].size; 167 if (memcmp(invalidAddresses[i].address, bytes, count) == 0) { 168 return false; 169 } 170 } 171 return true; 172} 173 174} // namespace 175 176namespace extensions { 177namespace api { 178 179// static 180void DeviceId::GetDeviceId(const std::string& extension_id, 181 const IdCallback& callback) { 182 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 183 CHECK(!extension_id.empty()); 184 185 // Forward call to platform specific implementation, then compute the HMAC 186 // in the callback. 187 GetRawDeviceId(base::Bind(&GetRawDeviceIdCallback, extension_id, callback)); 188} 189 190// static 191bool DeviceId::IsValidMacAddress(const void* bytes, size_t size) { 192 return IsValidMacAddressImpl(bytes, size); 193} 194 195} // namespace api 196} // namespace extensions 197