1 /*
2 * Copyright (c) 2016-2019, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /**
30 * @file
31 * This file implements MAC types.
32 */
33
34 #include "mac_types.hpp"
35
36 #include <stdio.h>
37
38 #include "common/code_utils.hpp"
39 #include "common/random.hpp"
40 #include "common/string.hpp"
41
42 namespace ot {
43 namespace Mac {
44
GenerateRandomPanId(void)45 PanId GenerateRandomPanId(void)
46 {
47 PanId panId;
48
49 do
50 {
51 panId = Random::NonCrypto::GetUint16();
52 } while (panId == kPanIdBroadcast);
53
54 return panId;
55 }
56
57 #if OPENTHREAD_FTD || OPENTHREAD_MTD
GenerateRandom(void)58 void ExtAddress::GenerateRandom(void)
59 {
60 IgnoreError(Random::Crypto::Fill(*this));
61 SetGroup(false);
62 SetLocal(true);
63 }
64 #endif
65
operator ==(const ExtAddress & aOther) const66 bool ExtAddress::operator==(const ExtAddress &aOther) const { return (memcmp(m8, aOther.m8, sizeof(m8)) == 0); }
67
ToString(void) const68 ExtAddress::InfoString ExtAddress::ToString(void) const
69 {
70 InfoString string;
71
72 string.AppendHexBytes(m8, sizeof(ExtAddress));
73
74 return string;
75 }
76
CopyAddress(uint8_t * aDst,const uint8_t * aSrc,CopyByteOrder aByteOrder)77 void ExtAddress::CopyAddress(uint8_t *aDst, const uint8_t *aSrc, CopyByteOrder aByteOrder)
78 {
79 switch (aByteOrder)
80 {
81 case kNormalByteOrder:
82 memcpy(aDst, aSrc, sizeof(ExtAddress));
83 break;
84
85 case kReverseByteOrder:
86 aSrc += sizeof(ExtAddress) - 1;
87 for (uint8_t len = sizeof(ExtAddress); len > 0; len--)
88 {
89 *aDst++ = *aSrc--;
90 }
91 break;
92 }
93 }
94
operator ==(const Address & aOther) const95 bool Address::operator==(const Address &aOther) const
96 {
97 bool ret = false;
98
99 VerifyOrExit(GetType() == aOther.GetType());
100
101 switch (GetType())
102 {
103 case kTypeNone:
104 ret = true;
105 break;
106
107 case kTypeShort:
108 ret = (GetShort() == aOther.GetShort());
109 break;
110
111 case kTypeExtended:
112 ret = (GetExtended() == aOther.GetExtended());
113 break;
114
115 default:
116 OT_ASSERT(false);
117 break;
118 }
119
120 exit:
121 return ret;
122 }
123
ToString(void) const124 Address::InfoString Address::ToString(void) const
125 {
126 InfoString string;
127
128 if (mType == kTypeExtended)
129 {
130 string.AppendHexBytes(GetExtended().m8, sizeof(ExtAddress));
131 }
132 else if (mType == kTypeNone)
133 {
134 string.Append("None");
135 }
136 else
137 {
138 string.Append("0x%04x", GetShort());
139 }
140
141 return string;
142 }
143
SetSource(PanId aPanId)144 void PanIds::SetSource(PanId aPanId)
145 {
146 mSource = aPanId;
147 mIsSourcePresent = true;
148 }
149
SetDestination(PanId aPanId)150 void PanIds::SetDestination(PanId aPanId)
151 {
152 mDestination = aPanId;
153 mIsDestinationPresent = true;
154 }
155
SetBothSourceDestination(PanId aPanId)156 void PanIds::SetBothSourceDestination(PanId aPanId)
157 {
158 SetSource(aPanId);
159 SetDestination(aPanId);
160 }
161
162 #if OPENTHREAD_CONFIG_MULTI_RADIO
163
164 const RadioType RadioTypes::kAllRadioTypes[kNumRadioTypes] = {
165 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
166 kRadioTypeIeee802154,
167 #endif
168 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
169 kRadioTypeTrel,
170 #endif
171 };
172
AddAll(void)173 void RadioTypes::AddAll(void)
174 {
175 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
176 Add(kRadioTypeIeee802154);
177 #endif
178 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
179 Add(kRadioTypeTrel);
180 #endif
181 }
182
ToString(void) const183 RadioTypes::InfoString RadioTypes::ToString(void) const
184 {
185 InfoString string;
186 bool addComma = false;
187
188 string.Append("{");
189 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
190 if (Contains(kRadioTypeIeee802154))
191 {
192 string.Append("%s%s", addComma ? ", " : " ", RadioTypeToString(kRadioTypeIeee802154));
193 addComma = true;
194 }
195 #endif
196
197 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
198 if (Contains(kRadioTypeTrel))
199 {
200 string.Append("%s%s", addComma ? ", " : " ", RadioTypeToString(kRadioTypeTrel));
201 addComma = true;
202 }
203 #endif
204
205 OT_UNUSED_VARIABLE(addComma);
206
207 string.Append(" }");
208
209 return string;
210 }
211
RadioTypeToString(RadioType aRadioType)212 const char *RadioTypeToString(RadioType aRadioType)
213 {
214 const char *str = "unknown";
215
216 switch (aRadioType)
217 {
218 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
219 case kRadioTypeIeee802154:
220 str = "15.4";
221 break;
222 #endif
223
224 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
225 case kRadioTypeTrel:
226 str = "trel";
227 break;
228 #endif
229 }
230
231 return str;
232 }
233
Get(RadioType aRadioType) const234 uint32_t LinkFrameCounters::Get(RadioType aRadioType) const
235 {
236 uint32_t counter = 0;
237
238 switch (aRadioType)
239 {
240 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
241 case kRadioTypeIeee802154:
242 counter = m154Counter;
243 break;
244 #endif
245
246 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
247 case kRadioTypeTrel:
248 counter = mTrelCounter;
249 break;
250 #endif
251 }
252
253 return counter;
254 }
255
Set(RadioType aRadioType,uint32_t aCounter)256 void LinkFrameCounters::Set(RadioType aRadioType, uint32_t aCounter)
257 {
258 switch (aRadioType)
259 {
260 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
261 case kRadioTypeIeee802154:
262 m154Counter = aCounter;
263 break;
264 #endif
265
266 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
267 case kRadioTypeTrel:
268 mTrelCounter = aCounter;
269 break;
270 #endif
271 }
272 }
273
274 #endif // OPENTHREAD_CONFIG_MULTI_RADIO
275
GetMaximum(void) const276 uint32_t LinkFrameCounters::GetMaximum(void) const
277 {
278 uint32_t counter = 0;
279
280 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
281 counter = Max(counter, m154Counter);
282 #endif
283
284 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
285 counter = Max(counter, mTrelCounter);
286 #endif
287
288 return counter;
289 }
290
SetAll(uint32_t aCounter)291 void LinkFrameCounters::SetAll(uint32_t aCounter)
292 {
293 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
294 m154Counter = aCounter;
295 #endif
296 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
297 mTrelCounter = aCounter;
298 #endif
299 }
300
301 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
operator =(const KeyMaterial & aOther)302 KeyMaterial &KeyMaterial::operator=(const KeyMaterial &aOther)
303 {
304 VerifyOrExit(GetKeyRef() != aOther.GetKeyRef());
305 DestroyKey();
306 SetKeyRef(aOther.GetKeyRef());
307
308 exit:
309 return *this;
310 }
311 #endif
312
Clear(void)313 void KeyMaterial::Clear(void)
314 {
315 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
316 DestroyKey();
317 SetKeyRef(kInvalidKeyRef);
318 #else
319 GetKey().Clear();
320 #endif
321 }
322
SetFrom(const Key & aKey,bool aIsExportable)323 void KeyMaterial::SetFrom(const Key &aKey, bool aIsExportable)
324 {
325 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
326 {
327 KeyRef keyRef = 0;
328
329 DestroyKey();
330
331 SuccessOrAssert(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes,
332 Crypto::Storage::kKeyAlgorithmAesEcb,
333 (aIsExportable ? Crypto::Storage::kUsageExport : 0) |
334 Crypto::Storage::kUsageEncrypt | Crypto::Storage::kUsageDecrypt,
335 Crypto::Storage::kTypeVolatile, aKey.GetBytes(), Key::kSize));
336
337 SetKeyRef(keyRef);
338 }
339 #else
340 SetKey(aKey);
341 OT_UNUSED_VARIABLE(aIsExportable);
342 #endif
343 }
344
ExtractKey(Key & aKey) const345 void KeyMaterial::ExtractKey(Key &aKey) const
346 {
347 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
348 aKey.Clear();
349
350 if (Crypto::Storage::IsKeyRefValid(GetKeyRef()))
351 {
352 size_t keySize;
353
354 SuccessOrAssert(Crypto::Storage::ExportKey(GetKeyRef(), aKey.m8, Key::kSize, keySize));
355 }
356 #else
357 aKey = GetKey();
358 #endif
359 }
360
ConvertToCryptoKey(Crypto::Key & aCryptoKey) const361 void KeyMaterial::ConvertToCryptoKey(Crypto::Key &aCryptoKey) const
362 {
363 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
364 aCryptoKey.SetAsKeyRef(GetKeyRef());
365 #else
366 aCryptoKey.Set(GetKey().GetBytes(), Key::kSize);
367 #endif
368 }
369
370 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
DestroyKey(void)371 void KeyMaterial::DestroyKey(void)
372 {
373 Crypto::Storage::DestroyKey(GetKeyRef());
374 SetKeyRef(kInvalidKeyRef);
375 }
376 #endif
377
operator ==(const KeyMaterial & aOther) const378 bool KeyMaterial::operator==(const KeyMaterial &aOther) const
379 {
380 return
381 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
382 (GetKeyRef() == aOther.GetKeyRef());
383 #else
384 (GetKey() == aOther.GetKey());
385 #endif
386 }
387
388 } // namespace Mac
389 } // namespace ot
390