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::FillBuffer(m8, sizeof(ExtAddress)));
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
113 #if OPENTHREAD_CONFIG_MULTI_RADIO
114
115 const RadioType RadioTypes::kAllRadioTypes[kNumRadioTypes] = {
116 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
117 kRadioTypeIeee802154,
118 #endif
119 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
120 kRadioTypeTrel,
121 #endif
122 };
123
AddAll(void)124 void RadioTypes::AddAll(void)
125 {
126 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
127 Add(kRadioTypeIeee802154);
128 #endif
129 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
130 Add(kRadioTypeTrel);
131 #endif
132 }
133
ToString(void) const134 RadioTypes::InfoString RadioTypes::ToString(void) const
135 {
136 InfoString string;
137 bool addComma = false;
138
139 string.Append("{");
140 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
141 if (Contains(kRadioTypeIeee802154))
142 {
143 string.Append("%s%s", addComma ? ", " : " ", RadioTypeToString(kRadioTypeIeee802154));
144 addComma = true;
145 }
146 #endif
147
148 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
149 if (Contains(kRadioTypeTrel))
150 {
151 string.Append("%s%s", addComma ? ", " : " ", RadioTypeToString(kRadioTypeTrel));
152 addComma = true;
153 }
154 #endif
155
156 OT_UNUSED_VARIABLE(addComma);
157
158 string.Append(" }");
159
160 return string;
161 }
162
RadioTypeToString(RadioType aRadioType)163 const char *RadioTypeToString(RadioType aRadioType)
164 {
165 const char *str = "unknown";
166
167 switch (aRadioType)
168 {
169 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
170 case kRadioTypeIeee802154:
171 str = "15.4";
172 break;
173 #endif
174
175 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
176 case kRadioTypeTrel:
177 str = "trel";
178 break;
179 #endif
180 }
181
182 return str;
183 }
184
Get(RadioType aRadioType) const185 uint32_t LinkFrameCounters::Get(RadioType aRadioType) const
186 {
187 uint32_t counter = 0;
188
189 switch (aRadioType)
190 {
191 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
192 case kRadioTypeIeee802154:
193 counter = m154Counter;
194 break;
195 #endif
196
197 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
198 case kRadioTypeTrel:
199 counter = mTrelCounter;
200 break;
201 #endif
202 }
203
204 return counter;
205 }
206
Set(RadioType aRadioType,uint32_t aCounter)207 void LinkFrameCounters::Set(RadioType aRadioType, uint32_t aCounter)
208 {
209 switch (aRadioType)
210 {
211 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
212 case kRadioTypeIeee802154:
213 m154Counter = aCounter;
214 break;
215 #endif
216
217 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
218 case kRadioTypeTrel:
219 mTrelCounter = aCounter;
220 break;
221 #endif
222 }
223 }
224
225 #endif // OPENTHREAD_CONFIG_MULTI_RADIO
226
GetMaximum(void) const227 uint32_t LinkFrameCounters::GetMaximum(void) const
228 {
229 uint32_t counter = 0;
230
231 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
232 if (counter < m154Counter)
233 {
234 counter = m154Counter;
235 }
236 #endif
237
238 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
239 if (counter < mTrelCounter)
240 {
241 counter = mTrelCounter;
242 }
243 #endif
244
245 return counter;
246 }
247
SetAll(uint32_t aCounter)248 void LinkFrameCounters::SetAll(uint32_t aCounter)
249 {
250 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
251 m154Counter = aCounter;
252 #endif
253 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
254 mTrelCounter = aCounter;
255 #endif
256 }
257
258 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
operator =(const KeyMaterial & aOther)259 KeyMaterial &KeyMaterial::operator=(const KeyMaterial &aOther)
260 {
261 VerifyOrExit(GetKeyRef() != aOther.GetKeyRef());
262 DestroyKey();
263 SetKeyRef(aOther.GetKeyRef());
264
265 exit:
266 return *this;
267 }
268 #endif
269
Clear(void)270 void KeyMaterial::Clear(void)
271 {
272 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
273 DestroyKey();
274 SetKeyRef(kInvalidKeyRef);
275 #else
276 GetKey().Clear();
277 #endif
278 }
279
SetFrom(const Key & aKey,bool aIsExportable)280 void KeyMaterial::SetFrom(const Key &aKey, bool aIsExportable)
281 {
282 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
283 {
284 KeyRef keyRef = 0;
285
286 DestroyKey();
287
288 SuccessOrAssert(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeAes,
289 Crypto::Storage::kKeyAlgorithmAesEcb,
290 (aIsExportable ? Crypto::Storage::kUsageExport : 0) |
291 Crypto::Storage::kUsageEncrypt | Crypto::Storage::kUsageDecrypt,
292 Crypto::Storage::kTypeVolatile, aKey.GetBytes(), Key::kSize));
293
294 SetKeyRef(keyRef);
295 }
296 #else
297 SetKey(aKey);
298 OT_UNUSED_VARIABLE(aIsExportable);
299 #endif
300 }
301
ExtractKey(Key & aKey) const302 void KeyMaterial::ExtractKey(Key &aKey) const
303 {
304 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
305 aKey.Clear();
306
307 if (Crypto::Storage::IsKeyRefValid(GetKeyRef()))
308 {
309 size_t keySize;
310
311 SuccessOrAssert(Crypto::Storage::ExportKey(GetKeyRef(), aKey.m8, Key::kSize, keySize));
312 }
313 #else
314 aKey = GetKey();
315 #endif
316 }
317
ConvertToCryptoKey(Crypto::Key & aCryptoKey) const318 void KeyMaterial::ConvertToCryptoKey(Crypto::Key &aCryptoKey) const
319 {
320 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
321 aCryptoKey.SetAsKeyRef(GetKeyRef());
322 #else
323 aCryptoKey.Set(GetKey().GetBytes(), Key::kSize);
324 #endif
325 }
326
327 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
DestroyKey(void)328 void KeyMaterial::DestroyKey(void)
329 {
330 Crypto::Storage::DestroyKey(GetKeyRef());
331 SetKeyRef(kInvalidKeyRef);
332 }
333 #endif
334
operator ==(const KeyMaterial & aOther) const335 bool KeyMaterial::operator==(const KeyMaterial &aOther) const
336 {
337 return
338 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
339 (GetKeyRef() == aOther.GetKeyRef());
340 #else
341 (GetKey() == aOther.GetKey());
342 #endif
343 }
344
345 } // namespace Mac
346 } // namespace ot
347