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