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