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_RADIO
GenerateRandom(void)58 void ExtAddress::GenerateRandom(void)
59 {
60 IgnoreError(Random::Crypto::Fill(*this));
61 SetGroup(false);
62 SetLocal(true);
63 }
64 #endif
65
ToString(void) const66 ExtAddress::InfoString ExtAddress::ToString(void) const
67 {
68 InfoString string;
69
70 string.AppendHexBytes(m8, sizeof(ExtAddress));
71
72 return string;
73 }
74
CopyAddress(uint8_t * aDst,const uint8_t * aSrc,CopyByteOrder aByteOrder)75 void ExtAddress::CopyAddress(uint8_t *aDst, const uint8_t *aSrc, CopyByteOrder aByteOrder)
76 {
77 switch (aByteOrder)
78 {
79 case kNormalByteOrder:
80 memcpy(aDst, aSrc, sizeof(ExtAddress));
81 break;
82
83 case kReverseByteOrder:
84 aSrc += sizeof(ExtAddress) - 1;
85 for (uint8_t len = sizeof(ExtAddress); len > 0; len--)
86 {
87 *aDst++ = *aSrc--;
88 }
89 break;
90 }
91 }
92
ToString(void) const93 Address::InfoString Address::ToString(void) const
94 {
95 InfoString string;
96
97 if (mType == kTypeExtended)
98 {
99 string.AppendHexBytes(GetExtended().m8, sizeof(ExtAddress));
100 }
101 else if (mType == kTypeNone)
102 {
103 string.Append("None");
104 }
105 else
106 {
107 string.Append("0x%04x", GetShort());
108 }
109
110 return string;
111 }
112
SetSource(PanId aPanId)113 void PanIds::SetSource(PanId aPanId)
114 {
115 mSource = aPanId;
116 mIsSourcePresent = true;
117 }
118
SetDestination(PanId aPanId)119 void PanIds::SetDestination(PanId aPanId)
120 {
121 mDestination = aPanId;
122 mIsDestinationPresent = true;
123 }
124
SetBothSourceDestination(PanId aPanId)125 void PanIds::SetBothSourceDestination(PanId aPanId)
126 {
127 SetSource(aPanId);
128 SetDestination(aPanId);
129 }
130
131 #if OPENTHREAD_CONFIG_MULTI_RADIO
132
133 const RadioType RadioTypes::kAllRadioTypes[kNumRadioTypes] = {
134 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
135 kRadioTypeIeee802154,
136 #endif
137 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
138 kRadioTypeTrel,
139 #endif
140 };
141
AddAll(void)142 void RadioTypes::AddAll(void)
143 {
144 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
145 Add(kRadioTypeIeee802154);
146 #endif
147 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
148 Add(kRadioTypeTrel);
149 #endif
150 }
151
ToString(void) const152 RadioTypes::InfoString RadioTypes::ToString(void) const
153 {
154 InfoString string;
155 bool addComma = false;
156
157 string.Append("{");
158 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
159 if (Contains(kRadioTypeIeee802154))
160 {
161 string.Append("%s%s", addComma ? ", " : " ", RadioTypeToString(kRadioTypeIeee802154));
162 addComma = true;
163 }
164 #endif
165
166 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
167 if (Contains(kRadioTypeTrel))
168 {
169 string.Append("%s%s", addComma ? ", " : " ", RadioTypeToString(kRadioTypeTrel));
170 addComma = true;
171 }
172 #endif
173
174 OT_UNUSED_VARIABLE(addComma);
175
176 string.Append(" }");
177
178 return string;
179 }
180
RadioTypeToString(RadioType aRadioType)181 const char *RadioTypeToString(RadioType aRadioType)
182 {
183 const char *str = "unknown";
184
185 switch (aRadioType)
186 {
187 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
188 case kRadioTypeIeee802154:
189 str = "15.4";
190 break;
191 #endif
192
193 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
194 case kRadioTypeTrel:
195 str = "trel";
196 break;
197 #endif
198 }
199
200 return str;
201 }
202
Get(RadioType aRadioType) const203 uint32_t LinkFrameCounters::Get(RadioType aRadioType) const
204 {
205 uint32_t counter = 0;
206
207 switch (aRadioType)
208 {
209 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
210 case kRadioTypeIeee802154:
211 counter = m154Counter;
212 break;
213 #endif
214
215 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
216 case kRadioTypeTrel:
217 counter = mTrelCounter;
218 break;
219 #endif
220 }
221
222 return counter;
223 }
224
Set(RadioType aRadioType,uint32_t aCounter)225 void LinkFrameCounters::Set(RadioType aRadioType, uint32_t aCounter)
226 {
227 switch (aRadioType)
228 {
229 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
230 case kRadioTypeIeee802154:
231 m154Counter = aCounter;
232 break;
233 #endif
234
235 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
236 case kRadioTypeTrel:
237 mTrelCounter = aCounter;
238 break;
239 #endif
240 }
241 }
242
243 #endif // OPENTHREAD_CONFIG_MULTI_RADIO
244
GetMaximum(void) const245 uint32_t LinkFrameCounters::GetMaximum(void) const
246 {
247 uint32_t counter = 0;
248
249 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
250 counter = Max(counter, m154Counter);
251 #endif
252
253 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
254 counter = Max(counter, mTrelCounter);
255 #endif
256
257 return counter;
258 }
259
SetAll(uint32_t aCounter)260 void LinkFrameCounters::SetAll(uint32_t aCounter)
261 {
262 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
263 m154Counter = aCounter;
264 #endif
265 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
266 mTrelCounter = aCounter;
267 #endif
268 }
269
270 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
operator =(const KeyMaterial & aOther)271 KeyMaterial &KeyMaterial::operator=(const KeyMaterial &aOther)
272 {
273 VerifyOrExit(GetKeyRef() != aOther.GetKeyRef());
274 DestroyKey();
275 SetKeyRef(aOther.GetKeyRef());
276
277 exit:
278 return *this;
279 }
280 #endif
281
Clear(void)282 void KeyMaterial::Clear(void)
283 {
284 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
285 DestroyKey();
286 SetKeyRef(kInvalidKeyRef);
287 #else
288 GetKey().Clear();
289 #endif
290 }
291
SetFrom(const Key & aKey,bool aIsExportable)292 void KeyMaterial::SetFrom(const Key &aKey, bool aIsExportable)
293 {
294 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
295 {
296 KeyRef keyRef = 0;
297
298 DestroyKey();
299
300 SuccessOrAssert(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes,
301 Crypto::Storage::kKeyAlgorithmAesEcb,
302 (aIsExportable ? Crypto::Storage::kUsageExport : 0) |
303 Crypto::Storage::kUsageEncrypt | Crypto::Storage::kUsageDecrypt,
304 Crypto::Storage::kTypeVolatile, aKey.GetBytes(), Key::kSize));
305
306 SetKeyRef(keyRef);
307 }
308 #else
309 SetKey(aKey);
310 OT_UNUSED_VARIABLE(aIsExportable);
311 #endif
312 }
313
ExtractKey(Key & aKey) const314 void KeyMaterial::ExtractKey(Key &aKey) const
315 {
316 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
317 aKey.Clear();
318
319 if (Crypto::Storage::IsKeyRefValid(GetKeyRef()))
320 {
321 size_t keySize;
322
323 SuccessOrAssert(Crypto::Storage::ExportKey(GetKeyRef(), aKey.m8, Key::kSize, keySize));
324 }
325 #else
326 aKey = GetKey();
327 #endif
328 }
329
ConvertToCryptoKey(Crypto::Key & aCryptoKey) const330 void KeyMaterial::ConvertToCryptoKey(Crypto::Key &aCryptoKey) const
331 {
332 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
333 aCryptoKey.SetAsKeyRef(GetKeyRef());
334 #else
335 aCryptoKey.Set(GetKey().GetBytes(), Key::kSize);
336 #endif
337 }
338
339 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
DestroyKey(void)340 void KeyMaterial::DestroyKey(void)
341 {
342 Crypto::Storage::DestroyKey(GetKeyRef());
343 SetKeyRef(kInvalidKeyRef);
344 }
345 #endif
346
operator ==(const KeyMaterial & aOther) const347 bool KeyMaterial::operator==(const KeyMaterial &aOther) const
348 {
349 return
350 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
351 (GetKeyRef() == aOther.GetKeyRef());
352 #else
353 (GetKey() == aOther.GetKey());
354 #endif
355 }
356
357 } // namespace Mac
358 } // namespace ot
359