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