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