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