1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "wifi_randommac_helper.h"
17
18 #if defined(FEATURE_ENCRYPTION_SUPPORT) || defined(SUPPORT_LOCAL_RANDOM_MAC)
19 #include "wifi_encryption_util.h"
20 #endif
21 #include "wifi_logger.h"
22
23 static const std::string STA_RANDOMMAC_KEY_ALIAS = "WiFiRandMacSecret";
24
25 namespace OHOS {
26 namespace Wifi {
27 DEFINE_WIFILOG_LABEL("WifiRandomMacHelper");
28 const unsigned long long MAC_ADDRESS_VALID_LONG_MASK = (1ULL << 48) - 1;
29 const unsigned long long MAC_ADDRESSS_AIASSIGNED_MASK = 1ULL << 43;
30 const unsigned long long MAC_ADDRESS_ELIASSIGNED_MASK = 1ULL << 42;
31 const unsigned long long MAC_ADDRESS_LOCALLY_ASSIGNED_MASK = 1ULL << 41;
32 const unsigned long long MAC_ADDRESS_MULTICAST_MASK = 1ULL << 40;
33 constexpr int MAX_MAC_SIZE = 18;
34 constexpr int LONG_TO_BYTE_SIZE = 8;
35 constexpr int MAC_ADDRESS_ETHER_ADDR_LEN = 6;
36 constexpr unsigned int WIFI2_RANDOM_MAC_CHANGE_POS = 9;
37 constexpr unsigned int WIFI2_RANDOM_MAC_CHANGE_LEN = 2;
38 constexpr unsigned int WIFI2_RANDOM_MAC_MASK = 0x80;
39
40 constexpr int OFFSET_VALUE_56 = 56;
41 constexpr int OFFSET_VALUE_48 = 48;
42 constexpr int OFFSET_VALUE_40 = 40;
43 constexpr int OFFSET_VALUE_32 = 32;
44 constexpr int OFFSET_VALUE_24 = 24;
45 constexpr int OFFSET_VALUE_16 = 16;
46 constexpr int OFFSET_VALUE_8 = 8;
47 constexpr int OFFSET_VALUE_7 = 7;
48 constexpr int OFFSET_VALUE_6 = 6;
49 constexpr int OFFSET_VALUE_5 = 5;
50 constexpr int OFFSET_VALUE_4 = 4;
51 constexpr int OFFSET_VALUE_3 = 3;
52 constexpr int OFFSET_VALUE_2 = 2;
53 constexpr int OFFSET_VALUE_1 = 1;
54 constexpr int OFFSET_VALUE_0 = 0;
55
56 #ifdef SUPPORT_LOCAL_RANDOM_MAC
CalculateRandomMacForWifiDeviceConfig(const std::string & content,std::string & randomMacAddr)57 int WifiRandomMacHelper::CalculateRandomMacForWifiDeviceConfig(const std::string &content, std::string &randomMacAddr)
58 {
59 WIFI_LOGI("%{public}s enter", __func__);
60 std::vector<uint8_t> outPlant = {};
61 int ret = WifiGenerateMacRandomizationSecret(STA_RANDOMMAC_KEY_ALIAS, content, outPlant);
62 if (ret != 0) {
63 WIFI_LOGE("%{public}s WifiGenerateMacRandomizationSecret failed %{public}d", __func__, ret);
64 return -1;
65 }
66 if (outPlant.size() < LONG_TO_BYTE_SIZE) {
67 WIFI_LOGE("%{public}s WifiGenerateMacRandomizationSecret size is illeage", __func__);
68 return -1;
69 }
70 std::vector<uint8_t> bytesToLong = {};
71 bytesToLong.assign(outPlant.begin(), outPlant.begin() + LONG_TO_BYTE_SIZE);
72 unsigned long long data = WifiRandomMacHelper::BytesToLonglong(bytesToLong);
73 ret = GenerateRandomMacAddressByLong(data, randomMacAddr);
74 if (ret != 0) {
75 WIFI_LOGE("%{public}s GenerateRandomMacAddressByLong failed:%{public}d", __func__, ret);
76 return -1;
77 }
78 return 0;
79 }
80 #endif
81
GenerateRandomMacAddressByBssid(std::string peerBssid,std::string & randomMacAddr)82 void WifiRandomMacHelper::GenerateRandomMacAddressByBssid(std::string peerBssid, std::string &randomMacAddr)
83 {
84 WIFI_LOGD("enter %{public}s", __func__);
85 constexpr int arraySize = 4;
86 constexpr int macBitSize = 12;
87 constexpr int firstBit = 1;
88 constexpr int lastBit = 11;
89 constexpr int two = 2;
90 constexpr int hexBase = 16;
91 constexpr int octBase = 8;
92 int ret = 0;
93 char strMacTmp[arraySize] = {0};
94 unsigned long long hashSeed = std::hash<std::string>{}(peerBssid);
95 unsigned long long genSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
96 if (std::numeric_limits<unsigned long long>::max() - genSeed > hashSeed) {
97 genSeed += hashSeed;
98 } else {
99 WIFI_LOGW("%{public}s hashSeed Value beyond max limit!", __func__);
100 }
101 std::mt19937_64 gen(genSeed);
102 for (int i = 0; i < macBitSize; i++) {
103 if (i != firstBit) {
104 std::uniform_int_distribution<> distribution(0, hexBase - 1);
105 ret = sprintf_s(strMacTmp, arraySize, "%x", distribution(gen));
106 } else {
107 std::uniform_int_distribution<> distribution(0, octBase - 1);
108 ret = sprintf_s(strMacTmp, arraySize, "%x", two * distribution(gen));
109 }
110 if (ret == -1) {
111 WIFI_LOGE("%{public}s failed, sprintf_s return -1!", __func__);
112 }
113 randomMacAddr += strMacTmp;
114 if ((i % two) != 0 && (i != lastBit)) {
115 randomMacAddr.append(":");
116 }
117 }
118 WIFI_LOGD("exit %{public}s, randomMacAddr:%{private}s", __func__, randomMacAddr.c_str());
119 }
120
GetRandom()121 long int WifiRandomMacHelper::GetRandom()
122 {
123 long random = 0;
124 do {
125 int fd = open("/dev/random", O_RDONLY);
126 ssize_t length = 0;
127 if (fd >= 0) {
128 length = read(fd, &random, sizeof(random));
129 close(fd);
130 } else {
131 WIFI_LOGW("%{public}s: failed to open, try again", __func__);
132 }
133 if (random == 0) {
134 fd = open("/dev/random", O_RDONLY);
135 if (fd >= 0) {
136 length = read(fd, &random, sizeof(random));
137 close(fd);
138 } else {
139 WIFI_LOGE("%{public}s: retry failed", __func__);
140 }
141 }
142 } while (0);
143 return (random >= 0 ? random : -random);
144 }
145
GenerateRandomMacAddress(std::string & randomMacAddr)146 void WifiRandomMacHelper::GenerateRandomMacAddress(std::string &randomMacAddr)
147 {
148 GenerateRandomMacAddressByBssid("", randomMacAddr);
149 return;
150 }
151
LongLongToBytes(unsigned long long value,std::vector<uint8_t> & outPlant)152 void WifiRandomMacHelper::LongLongToBytes(unsigned long long value, std::vector<uint8_t> &outPlant)
153 {
154 outPlant.clear();
155 outPlant.emplace_back((value >> OFFSET_VALUE_56) & 0xFF);
156 outPlant.emplace_back((value >> OFFSET_VALUE_48) & 0xFF);
157 outPlant.emplace_back((value >> OFFSET_VALUE_40) & 0xFF);
158 outPlant.emplace_back((value >> OFFSET_VALUE_32) & 0xFF);
159 outPlant.emplace_back((value >> OFFSET_VALUE_24) & 0xFF);
160 outPlant.emplace_back((value >> OFFSET_VALUE_16) & 0xFF);
161 outPlant.emplace_back((value >> OFFSET_VALUE_8) & 0xFF);
162 outPlant.emplace_back(value & 0xFF);
163 return;
164 }
165
BytesToLonglong(const std::vector<uint8_t> & byte)166 unsigned long long WifiRandomMacHelper::BytesToLonglong(const std::vector<uint8_t> &byte)
167 {
168 if (byte.size() != LONG_TO_BYTE_SIZE) {
169 WIFI_LOGI("%{public}s byte size is invalid :%{public}zu", __func__, byte.size());
170 return 0;
171 }
172 unsigned long long value = 0;
173 value = (
174 (((unsigned long long)byte[OFFSET_VALUE_0] << OFFSET_VALUE_56) & 0xFF00000000000000L) |
175 (((unsigned long long)byte[OFFSET_VALUE_1] << OFFSET_VALUE_48) & 0xFF000000000000L) |
176 (((unsigned long long)byte[OFFSET_VALUE_2] << OFFSET_VALUE_40) & 0xFF0000000000L) |
177 (((unsigned long long)byte[OFFSET_VALUE_3] << OFFSET_VALUE_32) & 0xFF00000000L) |
178 (((unsigned long long)byte[OFFSET_VALUE_4] << OFFSET_VALUE_24) & 0xFF000000L)|
179 (((unsigned long long)byte[OFFSET_VALUE_5] << OFFSET_VALUE_16) & 0xFF0000L)|
180 (((unsigned long long)byte[OFFSET_VALUE_6] << OFFSET_VALUE_8) & 0xFF00L)|
181 ((unsigned long long)byte[OFFSET_VALUE_7] & 0xFFL));
182 return value;
183 }
184
BytesArrayToString(const std::vector<uint8_t> & bytes)185 std::string WifiRandomMacHelper::BytesArrayToString(const std::vector<uint8_t> &bytes)
186 {
187 if (bytes.empty()) {
188 return "size:0 []";
189 }
190 size_t size = bytes.size();
191 std::string str = "size:" + std::to_string(size) + " [";
192 for (size_t i = 0; i < size; i++) {
193 str += std::to_string(bytes[i]);
194 if (i != size - 1) {
195 str += ",";
196 }
197 }
198 str += "]";
199 return str;
200 }
201
StringAddrFromLongAddr(unsigned long long addr,std::string & randomMacAddr)202 int WifiRandomMacHelper::StringAddrFromLongAddr(unsigned long long addr, std::string &randomMacAddr)
203 {
204 WIFI_LOGD("%{public}s %{public}llu 0x%{public}02llx:0x%{public}02llx:0x%{public}02llx:0x%{public}02llx"
205 ":0x%{public}02llx:0x%{public}02llx", __func__, addr,
206 (addr >> OFFSET_VALUE_40) & 0XFF,
207 (addr >> OFFSET_VALUE_32) & 0XFF,
208 (addr >> OFFSET_VALUE_24) & 0XFF,
209 (addr >> OFFSET_VALUE_16) & 0XFF,
210 (addr >> OFFSET_VALUE_8) & 0XFF,
211 addr & 0XFF);
212 char strMac[MAX_MAC_SIZE] = { 0 };
213 int ret = sprintf_s(strMac, MAX_MAC_SIZE, "%02llx:%02llx:%02llx:%02llx:%02llx:%02llx",
214 (addr >> OFFSET_VALUE_40) & 0XFF,
215 (addr >> OFFSET_VALUE_32) & 0XFF,
216 (addr >> OFFSET_VALUE_24) & 0XFF,
217 (addr >> OFFSET_VALUE_16) & 0XFF,
218 (addr >> OFFSET_VALUE_8) & 0XFF,
219 addr & 0XFF);
220 if (ret < 0) {
221 WIFI_LOGI("%{public}s: failed to sprintf_s", __func__);
222 return -1;
223 }
224 randomMacAddr = strMac;
225 return 0;
226 }
227
LongAddrFromByteAddr(std::vector<uint8_t> & addr)228 unsigned long long WifiRandomMacHelper::LongAddrFromByteAddr(std::vector<uint8_t> &addr)
229 {
230 if (addr.size() != MAC_ADDRESS_ETHER_ADDR_LEN) {
231 WIFI_LOGE("%{public}s %{public}s is not a valid MAC address", __func__,
232 BytesArrayToString(addr).c_str());
233 return 0;
234 }
235 unsigned long long longAddr = 0;
236 for (auto &b : addr) {
237 uint32_t uint8Byte = b & 0xff;
238 longAddr = (longAddr << OFFSET_VALUE_8) + uint8Byte;
239 }
240 return longAddr;
241 }
242
243
GenerateRandomMacAddressByLong(unsigned long long random,std::string & randomMacAddr)244 int WifiRandomMacHelper::GenerateRandomMacAddressByLong(unsigned long long random, std::string &randomMacAddr)
245 {
246 if (random == 0) {
247 WIFI_LOGI("%{public}s: random is invalid :%{public}llu!", __func__, random);
248 return -1;
249 }
250
251 WIFI_LOGD("%{public}s: calculate start is 0x%{public}llx==%{public}llu", __func__, random, random);
252 random &= MAC_ADDRESS_VALID_LONG_MASK;
253 random &= ~MAC_ADDRESSS_AIASSIGNED_MASK;
254 random &= ~MAC_ADDRESS_ELIASSIGNED_MASK;
255 random |= MAC_ADDRESS_LOCALLY_ASSIGNED_MASK;
256 random &= ~MAC_ADDRESS_MULTICAST_MASK;
257 WIFI_LOGD("%{public}s: calculate end is 0x%{public}llx==%{public}llu", __func__, random, random);
258
259 std::vector<uint8_t> bytes = {};
260 WifiRandomMacHelper::LongLongToBytes(random, bytes);
261 if (bytes.size() != LONG_TO_BYTE_SIZE) {
262 WIFI_LOGE("%{public}s LongLongToBytes failed size:%{public}zu", __func__, bytes.size());
263 return -1;
264 }
265 std::vector<uint8_t> addrBytes = {};
266 addrBytes.assign(bytes.begin() + OFFSET_VALUE_2, bytes.end());
267 unsigned long long lngAddr = WifiRandomMacHelper::LongAddrFromByteAddr(addrBytes);
268
269 int ret = StringAddrFromLongAddr(lngAddr, randomMacAddr);
270 WIFI_LOGD("%{public}s: StringAddrFromLongAddr: %{public}llu -> %{public}s", __func__,
271 lngAddr, MacAnonymize(randomMacAddr).c_str());
272 return ret;
273 }
274
GetWifi2RandomMac(std::string & wifi2RandomMac)275 bool WifiRandomMacHelper::GetWifi2RandomMac(std::string &wifi2RandomMac)
276 {
277 std::string inputStrMac = wifi2RandomMac.substr(WIFI2_RANDOM_MAC_CHANGE_POS, WIFI2_RANDOM_MAC_CHANGE_LEN);
278 std::stringstream inputSsMac;
279 inputSsMac << std::hex <<inputStrMac;
280 unsigned int inputHexMac;
281 if (inputSsMac >> inputHexMac) {
282 WIFI_LOGD("%{public}s conver pos 3 mac to hex success", __func__);
283 } else {
284 WIFI_LOGE("%{public}s conver pos 3 mac to hex fail", __func__);
285 return false;
286 }
287 unsigned int outputHexMac = inputHexMac ^ WIFI2_RANDOM_MAC_MASK;
288 std::stringstream outSsMac;
289 outSsMac << std::hex <<outputHexMac;
290 wifi2RandomMac.replace(WIFI2_RANDOM_MAC_CHANGE_POS, WIFI2_RANDOM_MAC_CHANGE_LEN, outSsMac.str());
291 return true;
292 }
293
294 } // Wifi
295 } // OHOS
296