• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, 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 Thread security material generation.
32  */
33 
34 #include "key_manager.hpp"
35 
36 #include "crypto/hkdf_sha256.hpp"
37 #include "crypto/storage.hpp"
38 #include "instance/instance.hpp"
39 
40 namespace ot {
41 
42 RegisterLogModule("KeyManager");
43 
44 const uint8_t KeyManager::kThreadString[] = {
45     'T', 'h', 'r', 'e', 'a', 'd',
46 };
47 
48 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
49 const uint8_t KeyManager::kHkdfExtractSaltString[] = {'T', 'h', 'r', 'e', 'a', 'd', 'S', 'e', 'q', 'u', 'e', 'n',
50                                                       'c', 'e', 'M', 'a', 's', 't', 'e', 'r', 'K', 'e', 'y'};
51 
52 const uint8_t KeyManager::kTrelInfoString[] = {'T', 'h', 'r', 'e', 'a', 'd', 'O', 'v', 'e',
53                                                'r', 'I', 'n', 'f', 'r', 'a', 'K', 'e', 'y'};
54 #endif
55 
56 //---------------------------------------------------------------------------------------------------------------------
57 // SecurityPolicy
58 
SetToDefault(void)59 void SecurityPolicy::SetToDefault(void)
60 {
61     Clear();
62     mRotationTime = kDefaultKeyRotationTime;
63     SetToDefaultFlags();
64 }
65 
SetToDefaultFlags(void)66 void SecurityPolicy::SetToDefaultFlags(void)
67 {
68     mObtainNetworkKeyEnabled        = true;
69     mNativeCommissioningEnabled     = true;
70     mRoutersEnabled                 = true;
71     mExternalCommissioningEnabled   = true;
72     mCommercialCommissioningEnabled = false;
73     mAutonomousEnrollmentEnabled    = false;
74     mNetworkKeyProvisioningEnabled  = false;
75     mTobleLinkEnabled               = true;
76     mNonCcmRoutersEnabled           = false;
77     mVersionThresholdForRouting     = 0;
78 }
79 
SetFlags(const uint8_t * aFlags,uint8_t aFlagsLength)80 void SecurityPolicy::SetFlags(const uint8_t *aFlags, uint8_t aFlagsLength)
81 {
82     OT_ASSERT(aFlagsLength > 0);
83 
84     SetToDefaultFlags();
85 
86     mObtainNetworkKeyEnabled        = aFlags[0] & kObtainNetworkKeyMask;
87     mNativeCommissioningEnabled     = aFlags[0] & kNativeCommissioningMask;
88     mRoutersEnabled                 = aFlags[0] & kRoutersMask;
89     mExternalCommissioningEnabled   = aFlags[0] & kExternalCommissioningMask;
90     mCommercialCommissioningEnabled = (aFlags[0] & kCommercialCommissioningMask) == 0;
91     mAutonomousEnrollmentEnabled    = (aFlags[0] & kAutonomousEnrollmentMask) == 0;
92     mNetworkKeyProvisioningEnabled  = (aFlags[0] & kNetworkKeyProvisioningMask) == 0;
93 
94     VerifyOrExit(aFlagsLength > sizeof(aFlags[0]));
95     mTobleLinkEnabled           = aFlags[1] & kTobleLinkMask;
96     mNonCcmRoutersEnabled       = (aFlags[1] & kNonCcmRoutersMask) == 0;
97     mVersionThresholdForRouting = aFlags[1] & kVersionThresholdForRoutingMask;
98 
99 exit:
100     return;
101 }
102 
GetFlags(uint8_t * aFlags,uint8_t aFlagsLength) const103 void SecurityPolicy::GetFlags(uint8_t *aFlags, uint8_t aFlagsLength) const
104 {
105     OT_ASSERT(aFlagsLength > 0);
106 
107     memset(aFlags, 0, aFlagsLength);
108 
109     if (mObtainNetworkKeyEnabled)
110     {
111         aFlags[0] |= kObtainNetworkKeyMask;
112     }
113 
114     if (mNativeCommissioningEnabled)
115     {
116         aFlags[0] |= kNativeCommissioningMask;
117     }
118 
119     if (mRoutersEnabled)
120     {
121         aFlags[0] |= kRoutersMask;
122     }
123 
124     if (mExternalCommissioningEnabled)
125     {
126         aFlags[0] |= kExternalCommissioningMask;
127     }
128 
129     if (!mCommercialCommissioningEnabled)
130     {
131         aFlags[0] |= kCommercialCommissioningMask;
132     }
133 
134     if (!mAutonomousEnrollmentEnabled)
135     {
136         aFlags[0] |= kAutonomousEnrollmentMask;
137     }
138 
139     if (!mNetworkKeyProvisioningEnabled)
140     {
141         aFlags[0] |= kNetworkKeyProvisioningMask;
142     }
143 
144     VerifyOrExit(aFlagsLength > sizeof(aFlags[0]));
145 
146     if (mTobleLinkEnabled)
147     {
148         aFlags[1] |= kTobleLinkMask;
149     }
150 
151     if (!mNonCcmRoutersEnabled)
152     {
153         aFlags[1] |= kNonCcmRoutersMask;
154     }
155 
156     aFlags[1] |= kReservedMask;
157     aFlags[1] |= mVersionThresholdForRouting;
158 
159 exit:
160     return;
161 }
162 
163 //---------------------------------------------------------------------------------------------------------------------
164 // KeyManager
165 
KeyManager(Instance & aInstance)166 KeyManager::KeyManager(Instance &aInstance)
167     : InstanceLocator(aInstance)
168     , mKeySequence(0)
169     , mMleFrameCounter(0)
170     , mStoredMacFrameCounter(0)
171     , mStoredMleFrameCounter(0)
172     , mHoursSinceKeyRotation(0)
173     , mKeySwitchGuardTime(kDefaultKeySwitchGuardTime)
174     , mKeySwitchGuardTimer(0)
175     , mKeyRotationTimer(aInstance)
176     , mKekFrameCounter(0)
177     , mIsPskcSet(false)
178 {
179     otPlatCryptoInit();
180 
181 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
182     {
183         NetworkKey networkKey;
184 
185         mNetworkKeyRef = Crypto::Storage::kInvalidKeyRef;
186         mPskcRef       = Crypto::Storage::kInvalidKeyRef;
187 
188         IgnoreError(networkKey.GenerateRandom());
189         StoreNetworkKey(networkKey, /* aOverWriteExisting */ false);
190     }
191 #else
192     IgnoreError(mNetworkKey.GenerateRandom());
193     mPskc.Clear();
194 #endif
195 
196     mMacFrameCounters.Reset();
197 }
198 
Start(void)199 void KeyManager::Start(void)
200 {
201     mKeySwitchGuardTimer = 0;
202     ResetKeyRotationTimer();
203 }
204 
Stop(void)205 void KeyManager::Stop(void) { mKeyRotationTimer.Stop(); }
206 
SetPskc(const Pskc & aPskc)207 void KeyManager::SetPskc(const Pskc &aPskc)
208 {
209 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
210     if (Crypto::Storage::IsKeyRefValid(mPskcRef))
211     {
212         Pskc pskc;
213 
214         GetPskc(pskc);
215         VerifyOrExit(aPskc != pskc, Get<Notifier>().SignalIfFirst(kEventPskcChanged));
216     }
217 
218     StorePskc(aPskc);
219     Get<Notifier>().Signal(kEventPskcChanged);
220 #else
221     SuccessOrExit(Get<Notifier>().Update(mPskc, aPskc, kEventPskcChanged));
222 #endif
223 
224 exit:
225     mIsPskcSet = true;
226 }
227 
ResetFrameCounters(void)228 void KeyManager::ResetFrameCounters(void)
229 {
230     Router *parent;
231 
232     // reset parent frame counters
233     parent = &Get<Mle::MleRouter>().GetParent();
234     parent->SetKeySequence(0);
235     parent->GetLinkFrameCounters().Reset();
236     parent->SetLinkAckFrameCounter(0);
237     parent->SetMleFrameCounter(0);
238 
239 #if OPENTHREAD_FTD
240     // reset router frame counters
241     for (Router &router : Get<RouterTable>())
242     {
243         router.SetKeySequence(0);
244         router.GetLinkFrameCounters().Reset();
245         router.SetLinkAckFrameCounter(0);
246         router.SetMleFrameCounter(0);
247     }
248 
249     // reset child frame counters
250     for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
251     {
252         child.SetKeySequence(0);
253         child.GetLinkFrameCounters().Reset();
254         child.SetLinkAckFrameCounter(0);
255         child.SetMleFrameCounter(0);
256     }
257 #endif
258 }
259 
SetNetworkKey(const NetworkKey & aNetworkKey)260 void KeyManager::SetNetworkKey(const NetworkKey &aNetworkKey)
261 {
262 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
263     if (Crypto::Storage::IsKeyRefValid(mNetworkKeyRef))
264     {
265         NetworkKey networkKey;
266 
267         GetNetworkKey(networkKey);
268         VerifyOrExit(networkKey != aNetworkKey, Get<Notifier>().SignalIfFirst(kEventNetworkKeyChanged));
269     }
270 
271     StoreNetworkKey(aNetworkKey, /* aOverWriteExisting */ true);
272     Get<Notifier>().Signal(kEventNetworkKeyChanged);
273 #else
274     SuccessOrExit(Get<Notifier>().Update(mNetworkKey, aNetworkKey, kEventNetworkKeyChanged));
275 #endif
276 
277     Get<Notifier>().Signal(kEventThreadKeySeqCounterChanged);
278 
279     mKeySequence = 0;
280     UpdateKeyMaterial();
281     ResetFrameCounters();
282 
283 exit:
284     return;
285 }
286 
ComputeKeys(uint32_t aKeySequence,HashKeys & aHashKeys) const287 void KeyManager::ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys) const
288 {
289     Crypto::HmacSha256 hmac;
290     uint8_t            keySequenceBytes[sizeof(uint32_t)];
291     Crypto::Key        cryptoKey;
292 
293 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
294     cryptoKey.SetAsKeyRef(mNetworkKeyRef);
295 #else
296     cryptoKey.Set(mNetworkKey.m8, NetworkKey::kSize);
297 #endif
298 
299     hmac.Start(cryptoKey);
300 
301     BigEndian::WriteUint32(aKeySequence, keySequenceBytes);
302     hmac.Update(keySequenceBytes);
303     hmac.Update(kThreadString);
304 
305     hmac.Finish(aHashKeys.mHash);
306 }
307 
308 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
ComputeTrelKey(uint32_t aKeySequence,Mac::Key & aKey) const309 void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const
310 {
311     Crypto::HkdfSha256 hkdf;
312     uint8_t            salt[sizeof(uint32_t) + sizeof(kHkdfExtractSaltString)];
313     Crypto::Key        cryptoKey;
314 
315 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
316     cryptoKey.SetAsKeyRef(mNetworkKeyRef);
317 #else
318     cryptoKey.Set(mNetworkKey.m8, NetworkKey::kSize);
319 #endif
320 
321     BigEndian::WriteUint32(aKeySequence, salt);
322     memcpy(salt + sizeof(uint32_t), kHkdfExtractSaltString, sizeof(kHkdfExtractSaltString));
323 
324     hkdf.Extract(salt, sizeof(salt), cryptoKey);
325     hkdf.Expand(kTrelInfoString, sizeof(kTrelInfoString), aKey.m8, Mac::Key::kSize);
326 }
327 #endif
328 
UpdateKeyMaterial(void)329 void KeyManager::UpdateKeyMaterial(void)
330 {
331     HashKeys hashKeys;
332 
333     ComputeKeys(mKeySequence, hashKeys);
334 
335     mMleKey.SetFrom(hashKeys.GetMleKey());
336 
337 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
338     {
339         Mac::KeyMaterial curKey;
340         Mac::KeyMaterial prevKey;
341         Mac::KeyMaterial nextKey;
342 
343         curKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
344 
345         ComputeKeys(mKeySequence - 1, hashKeys);
346         prevKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
347 
348         ComputeKeys(mKeySequence + 1, hashKeys);
349         nextKey.SetFrom(hashKeys.GetMacKey(), kExportableMacKeys);
350 
351         Get<Mac::SubMac>().SetMacKey(Mac::Frame::kKeyIdMode1, (mKeySequence & 0x7f) + 1, prevKey, curKey, nextKey);
352     }
353 #endif
354 
355 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
356     {
357         Mac::Key key;
358 
359         ComputeTrelKey(mKeySequence, key);
360         mTrelKey.SetFrom(key);
361     }
362 #endif
363 }
364 
SetCurrentKeySequence(uint32_t aKeySequence,KeySeqUpdateFlags aFlags)365 void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence, KeySeqUpdateFlags aFlags)
366 {
367     VerifyOrExit(aKeySequence != mKeySequence, Get<Notifier>().SignalIfFirst(kEventThreadKeySeqCounterChanged));
368 
369     if (aFlags & kApplySwitchGuard)
370     {
371         VerifyOrExit(mKeySwitchGuardTimer == 0);
372     }
373 
374     // MAC frame counters are reset before updating keys. This order
375     // safeguards against issues that can arise when the radio
376     // platform handles TX security and counter assignment.  The
377     // radio platform might prepare an enhanced ACK to a received
378     // frame from an parallel (e.g., ISR) context, which consumes
379     // a MAC frame counter value.
380     //
381     // Ideally, a call to `otPlatRadioSetMacKey()`, which sets the MAC
382     // keys on the radio, should also reset the frame counter tracked
383     // by the radio. However, if this is not implemented by the radio
384     // platform, resetting the counter first ensures new keys always
385     // start with a zero counter and avoids potential issue below.
386     //
387     // If the MAC key is updated before the frame counter is cleared,
388     // the radio could receive and send an enhanced ACK between these
389     // two actions, possibly using the new MAC key with a larger
390     // (current) frame counter value. This could then prevent the
391     // receiver from accepting subsequent transmissions after the
392     // frame counter reset for a long time.
393     //
394     // While resetting counters first might briefly cause an enhanced
395     // ACK to be sent with the old key and a zero counter (which might
396     // be rejected by the receiver), this is a transient issue that
397     // quickly resolves itself.
398 
399     SetAllMacFrameCounters(0, /* aSetIfLarger */ false);
400     mMleFrameCounter = 0;
401 
402     mKeySequence = aKeySequence;
403     UpdateKeyMaterial();
404 
405     ResetKeyRotationTimer();
406 
407     if (aFlags & kResetGuardTimer)
408     {
409         mKeySwitchGuardTimer = mKeySwitchGuardTime;
410     }
411 
412     Get<Notifier>().Signal(kEventThreadKeySeqCounterChanged);
413 
414 exit:
415     return;
416 }
417 
GetTemporaryMleKey(uint32_t aKeySequence)418 const Mle::KeyMaterial &KeyManager::GetTemporaryMleKey(uint32_t aKeySequence)
419 {
420     HashKeys hashKeys;
421 
422     ComputeKeys(aKeySequence, hashKeys);
423     mTemporaryMleKey.SetFrom(hashKeys.GetMleKey());
424 
425     return mTemporaryMleKey;
426 }
427 
428 #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
GetTemporaryMacKey(uint32_t aKeySequence)429 const Mle::KeyMaterial &KeyManager::GetTemporaryMacKey(uint32_t aKeySequence)
430 {
431     HashKeys hashKeys;
432 
433     ComputeKeys(aKeySequence, hashKeys);
434     mTemporaryMacKey.SetFrom(hashKeys.GetMacKey());
435 
436     return mTemporaryMacKey;
437 }
438 #endif
439 
440 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
GetTemporaryTrelMacKey(uint32_t aKeySequence)441 const Mac::KeyMaterial &KeyManager::GetTemporaryTrelMacKey(uint32_t aKeySequence)
442 {
443     Mac::Key key;
444 
445     ComputeTrelKey(aKeySequence, key);
446     mTemporaryTrelKey.SetFrom(key);
447 
448     return mTemporaryTrelKey;
449 }
450 #endif
451 
SetAllMacFrameCounters(uint32_t aFrameCounter,bool aSetIfLarger)452 void KeyManager::SetAllMacFrameCounters(uint32_t aFrameCounter, bool aSetIfLarger)
453 {
454     mMacFrameCounters.SetAll(aFrameCounter);
455 
456 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
457     Get<Mac::SubMac>().SetFrameCounter(aFrameCounter, aSetIfLarger);
458 #else
459     OT_UNUSED_VARIABLE(aSetIfLarger);
460 #endif
461 }
462 
463 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
MacFrameCounterUsed(uint32_t aMacFrameCounter)464 void KeyManager::MacFrameCounterUsed(uint32_t aMacFrameCounter)
465 {
466     // This is callback from `SubMac` to indicate that a frame
467     // counter value is used for tx. We ensure to handle it
468     // even if it is called out of order.
469 
470     VerifyOrExit(mMacFrameCounters.Get154() <= aMacFrameCounter);
471 
472     mMacFrameCounters.Set154(aMacFrameCounter + 1);
473 
474     if (mMacFrameCounters.Get154() >= mStoredMacFrameCounter)
475     {
476         IgnoreError(Get<Mle::MleRouter>().Store());
477     }
478 
479 exit:
480     return;
481 }
482 #else
MacFrameCounterUsed(uint32_t)483 void KeyManager::MacFrameCounterUsed(uint32_t) {}
484 #endif
485 
486 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
IncrementTrelMacFrameCounter(void)487 void KeyManager::IncrementTrelMacFrameCounter(void)
488 {
489     mMacFrameCounters.IncrementTrel();
490 
491     if (mMacFrameCounters.GetTrel() >= mStoredMacFrameCounter)
492     {
493         IgnoreError(Get<Mle::MleRouter>().Store());
494     }
495 }
496 #endif
497 
IncrementMleFrameCounter(void)498 void KeyManager::IncrementMleFrameCounter(void)
499 {
500     mMleFrameCounter++;
501 
502     if (mMleFrameCounter >= mStoredMleFrameCounter)
503     {
504         IgnoreError(Get<Mle::MleRouter>().Store());
505     }
506 }
507 
SetKek(const Kek & aKek)508 void KeyManager::SetKek(const Kek &aKek)
509 {
510     mKek.SetFrom(aKek, /* aIsExportable */ true);
511     mKekFrameCounter = 0;
512 }
513 
SetSecurityPolicy(const SecurityPolicy & aSecurityPolicy)514 void KeyManager::SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy)
515 {
516     SecurityPolicy newPolicy = aSecurityPolicy;
517 
518     if (newPolicy.mRotationTime < SecurityPolicy::kMinKeyRotationTime)
519     {
520         newPolicy.mRotationTime = SecurityPolicy::kMinKeyRotationTime;
521         LogNote("Key Rotation Time in SecurityPolicy is set to min allowed value of %u", newPolicy.mRotationTime);
522     }
523 
524     if (newPolicy.mRotationTime != mSecurityPolicy.mRotationTime)
525     {
526         uint32_t newGuardTime = newPolicy.mRotationTime;
527 
528         // Calculations are done using a `uint32_t` variable to prevent
529         // potential overflow.
530 
531         newGuardTime *= kKeySwitchGuardTimePercentage;
532         newGuardTime /= 100;
533 
534         mKeySwitchGuardTime = static_cast<uint16_t>(newGuardTime);
535     }
536 
537     IgnoreError(Get<Notifier>().Update(mSecurityPolicy, newPolicy, kEventSecurityPolicyChanged));
538 
539     CheckForKeyRotation();
540 }
541 
ResetKeyRotationTimer(void)542 void KeyManager::ResetKeyRotationTimer(void)
543 {
544     mHoursSinceKeyRotation = 0;
545     mKeyRotationTimer.Start(Time::kOneHourInMsec);
546 }
547 
HandleKeyRotationTimer(void)548 void KeyManager::HandleKeyRotationTimer(void)
549 {
550     mKeyRotationTimer.Start(Time::kOneHourInMsec);
551 
552     mHoursSinceKeyRotation++;
553 
554     if (mKeySwitchGuardTimer > 0)
555     {
556         mKeySwitchGuardTimer--;
557     }
558 
559     CheckForKeyRotation();
560 }
561 
CheckForKeyRotation(void)562 void KeyManager::CheckForKeyRotation(void)
563 {
564     if (mHoursSinceKeyRotation >= mSecurityPolicy.mRotationTime)
565     {
566         SetCurrentKeySequence(mKeySequence + 1, kForceUpdate | kResetGuardTimer);
567     }
568 }
569 
GetNetworkKey(NetworkKey & aNetworkKey) const570 void KeyManager::GetNetworkKey(NetworkKey &aNetworkKey) const
571 {
572 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
573     if (Crypto::Storage::HasKey(mNetworkKeyRef))
574     {
575         size_t keyLen;
576 
577         SuccessOrAssert(Crypto::Storage::ExportKey(mNetworkKeyRef, aNetworkKey.m8, NetworkKey::kSize, keyLen));
578         OT_ASSERT(keyLen == NetworkKey::kSize);
579     }
580     else
581     {
582         aNetworkKey.Clear();
583     }
584 #else
585     aNetworkKey = mNetworkKey;
586 #endif
587 }
588 
GetPskc(Pskc & aPskc) const589 void KeyManager::GetPskc(Pskc &aPskc) const
590 {
591 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
592     if (Crypto::Storage::HasKey(mPskcRef))
593     {
594         size_t keyLen;
595 
596         SuccessOrAssert(Crypto::Storage::ExportKey(mPskcRef, aPskc.m8, Pskc::kSize, keyLen));
597         OT_ASSERT(keyLen == Pskc::kSize);
598     }
599     else
600     {
601         aPskc.Clear();
602     }
603 #else
604     aPskc = mPskc;
605 #endif
606 }
607 
608 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
609 
StoreNetworkKey(const NetworkKey & aNetworkKey,bool aOverWriteExisting)610 void KeyManager::StoreNetworkKey(const NetworkKey &aNetworkKey, bool aOverWriteExisting)
611 {
612     NetworkKeyRef keyRef;
613 
614     keyRef = Get<Crypto::Storage::KeyRefManager>().KeyRefFor(Crypto::Storage::KeyRefManager::kNetworkKey);
615 
616     if (!aOverWriteExisting)
617     {
618         // Check if there is already a network key stored in ITS. If
619         // stored, and we are not overwriting the existing key,
620         // return without doing anything.
621         if (Crypto::Storage::HasKey(keyRef))
622         {
623             ExitNow();
624         }
625     }
626 
627     Crypto::Storage::DestroyKey(keyRef);
628 
629     SuccessOrAssert(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeHmac,
630                                                Crypto::Storage::kKeyAlgorithmHmacSha256,
631                                                Crypto::Storage::kUsageSignHash | Crypto::Storage::kUsageExport,
632                                                Crypto::Storage::kTypePersistent, aNetworkKey.m8, NetworkKey::kSize));
633 
634 exit:
635     if (mNetworkKeyRef != keyRef)
636     {
637         Crypto::Storage::DestroyKey(mNetworkKeyRef);
638     }
639 
640     mNetworkKeyRef = keyRef;
641 }
642 
StorePskc(const Pskc & aPskc)643 void KeyManager::StorePskc(const Pskc &aPskc)
644 {
645     PskcRef keyRef = Get<Crypto::Storage::KeyRefManager>().KeyRefFor(Crypto::Storage::KeyRefManager::kPskc);
646 
647     Crypto::Storage::DestroyKey(keyRef);
648 
649     SuccessOrAssert(Crypto::Storage::ImportKey(keyRef, Crypto::Storage::kKeyTypeRaw,
650                                                Crypto::Storage::kKeyAlgorithmVendor, Crypto::Storage::kUsageExport,
651                                                Crypto::Storage::kTypePersistent, aPskc.m8, Pskc::kSize));
652 
653     if (mPskcRef != keyRef)
654     {
655         Crypto::Storage::DestroyKey(mPskcRef);
656     }
657 
658     mPskcRef = keyRef;
659 }
660 
SetPskcRef(PskcRef aKeyRef)661 void KeyManager::SetPskcRef(PskcRef aKeyRef)
662 {
663     VerifyOrExit(mPskcRef != aKeyRef, Get<Notifier>().SignalIfFirst(kEventPskcChanged));
664 
665     Crypto::Storage::DestroyKey(mPskcRef);
666 
667     mPskcRef = aKeyRef;
668     Get<Notifier>().Signal(kEventPskcChanged);
669 
670 exit:
671     mIsPskcSet = true;
672 }
673 
SetNetworkKeyRef(otNetworkKeyRef aKeyRef)674 void KeyManager::SetNetworkKeyRef(otNetworkKeyRef aKeyRef)
675 {
676     VerifyOrExit(mNetworkKeyRef != aKeyRef, Get<Notifier>().SignalIfFirst(kEventNetworkKeyChanged));
677 
678     Crypto::Storage::DestroyKey(mNetworkKeyRef);
679 
680     mNetworkKeyRef = aKeyRef;
681     Get<Notifier>().Signal(kEventNetworkKeyChanged);
682     Get<Notifier>().Signal(kEventThreadKeySeqCounterChanged);
683     mKeySequence = 0;
684     UpdateKeyMaterial();
685     ResetFrameCounters();
686 
687 exit:
688     return;
689 }
690 
DestroyTemporaryKeys(void)691 void KeyManager::DestroyTemporaryKeys(void)
692 {
693     mMleKey.Clear();
694     mKek.Clear();
695     Get<Mac::SubMac>().ClearMacKeys();
696     Get<Mac::Mac>().ClearMode2Key();
697 }
698 
DestroyPersistentKeys(void)699 void KeyManager::DestroyPersistentKeys(void) { Get<Crypto::Storage::KeyRefManager>().DestroyPersistentKeys(); }
700 
701 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
702 
703 } // namespace ot
704