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 MeshCoP Datasets manager to process commands.
32  */
33 
34 #include "dataset_manager.hpp"
35 
36 #include "instance/instance.hpp"
37 
38 namespace ot {
39 namespace MeshCoP {
40 
41 RegisterLogModule("DatasetManager");
42 
43 //---------------------------------------------------------------------------------------------------------------------
44 // DatasetManager
45 
DatasetManager(Instance & aInstance,Type aType,Timer::Handler aTimerHandler)46 DatasetManager::DatasetManager(Instance &aInstance, Type aType, Timer::Handler aTimerHandler)
47     : InstanceLocator(aInstance)
48     , mType(aType)
49     , mLocalSaved(false)
50     , mMgmtPending(false)
51     , mLocalUpdateTime(0)
52     , mTimer(aInstance, aTimerHandler)
53 {
54     mLocalTimestamp.SetToInvalid();
55     mNetworkTimestamp.SetToInvalid();
56 }
57 
Restore(void)58 Error DatasetManager::Restore(void)
59 {
60     Error   error;
61     Dataset dataset;
62 
63     // If `Read()` fails, `dataset` will remain empty. We still call
64     // `Restore(dataset)` to stop timer and clear the timestamp
65     // flags.
66 
67     error = Read(dataset);
68     Restore(dataset);
69 
70     return error;
71 }
72 
Restore(const Dataset & aDataset)73 void DatasetManager::Restore(const Dataset &aDataset)
74 {
75     mTimer.Stop();
76 
77     mNetworkTimestamp.SetToInvalid();
78     mLocalTimestamp.SetToInvalid();
79 
80     VerifyOrExit(aDataset.GetLength() != 0);
81 
82     mLocalSaved = true;
83 
84     if (aDataset.ReadTimestamp(mType, mLocalTimestamp) == kErrorNone)
85     {
86         mNetworkTimestamp = mLocalTimestamp;
87     }
88 
89     if (IsActiveDataset())
90     {
91         IgnoreError(ApplyConfiguration(aDataset));
92     }
93 
94     SignalDatasetChange();
95 
96 exit:
97     return;
98 }
99 
Read(Dataset & aDataset) const100 Error DatasetManager::Read(Dataset &aDataset) const
101 {
102     Error error;
103 
104     aDataset.Clear();
105 
106     SuccessOrExit(error = Get<Settings>().ReadOperationalDataset(mType, aDataset));
107 
108 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
109     EmplaceSecurelyStoredKeys(aDataset);
110 #endif
111 
112     if (mType == Dataset::kActive)
113     {
114         aDataset.RemoveTlv(Tlv::kPendingTimestamp);
115         aDataset.RemoveTlv(Tlv::kDelayTimer);
116     }
117     else
118     {
119         Tlv *tlv = aDataset.FindTlv(Tlv::kDelayTimer);
120 
121         VerifyOrExit(tlv != nullptr);
122         tlv->WriteValueAs<DelayTimerTlv>(DelayTimerTlv::CalculateRemainingDelay(*tlv, mLocalUpdateTime));
123     }
124 
125     aDataset.mUpdateTime = TimerMilli::GetNow();
126 
127 exit:
128     return error;
129 }
130 
Read(Dataset::Info & aDatasetInfo) const131 Error DatasetManager::Read(Dataset::Info &aDatasetInfo) const
132 {
133     Dataset dataset;
134     Error   error;
135 
136     aDatasetInfo.Clear();
137 
138     SuccessOrExit(error = Read(dataset));
139     dataset.ConvertTo(aDatasetInfo);
140 
141 exit:
142     return error;
143 }
144 
Read(Dataset::Tlvs & aDatasetTlvs) const145 Error DatasetManager::Read(Dataset::Tlvs &aDatasetTlvs) const
146 {
147     Dataset dataset;
148     Error   error;
149 
150     ClearAllBytes(aDatasetTlvs);
151 
152     SuccessOrExit(error = Read(dataset));
153     dataset.ConvertTo(aDatasetTlvs);
154 
155 exit:
156     return error;
157 }
158 
ApplyConfiguration(void) const159 Error DatasetManager::ApplyConfiguration(void) const
160 {
161     Error   error;
162     Dataset dataset;
163 
164     SuccessOrExit(error = Read(dataset));
165     error = ApplyConfiguration(dataset);
166 
167 exit:
168     return error;
169 }
170 
ApplyConfiguration(const Dataset & aDataset) const171 Error DatasetManager::ApplyConfiguration(const Dataset &aDataset) const
172 {
173     Error error = kErrorNone;
174 
175     SuccessOrExit(error = aDataset.ValidateTlvs());
176 
177     for (const Tlv *cur = aDataset.GetTlvsStart(); cur < aDataset.GetTlvsEnd(); cur = cur->GetNext())
178     {
179         switch (cur->GetType())
180         {
181         case Tlv::kChannel:
182         {
183             uint8_t channel = static_cast<uint8_t>(cur->ReadValueAs<ChannelTlv>().GetChannel());
184 
185             error = Get<Mac::Mac>().SetPanChannel(channel);
186 
187             if (error != kErrorNone)
188             {
189                 LogCrit("Failed to set PAN channel to %u when applying dataset: %s", channel, ErrorToString(error));
190             }
191 
192             break;
193         }
194 
195         case Tlv::kWakeupChannel:
196         {
197 #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
198             uint8_t channel = static_cast<uint8_t>(cur->ReadValueAs<WakeupChannelTlv>().GetChannel());
199             error           = Get<Mac::Mac>().SetWakeupChannel(channel);
200 
201             if (error != kErrorNone)
202             {
203                 LogCrit("Failed to set wake-up channel to %u when applying dataset: %s", channel, ErrorToString(error));
204             }
205 #endif
206             break;
207         }
208 
209         case Tlv::kPanId:
210             Get<Mac::Mac>().SetPanId(cur->ReadValueAs<PanIdTlv>());
211             break;
212 
213         case Tlv::kExtendedPanId:
214             Get<ExtendedPanIdManager>().SetExtPanId(cur->ReadValueAs<ExtendedPanIdTlv>());
215             break;
216 
217         case Tlv::kNetworkName:
218             IgnoreError(Get<NetworkNameManager>().SetNetworkName(As<NetworkNameTlv>(cur)->GetNetworkName()));
219             break;
220 
221         case Tlv::kNetworkKey:
222             Get<KeyManager>().SetNetworkKey(cur->ReadValueAs<NetworkKeyTlv>());
223             break;
224 
225 #if OPENTHREAD_FTD
226         case Tlv::kPskc:
227             Get<KeyManager>().SetPskc(cur->ReadValueAs<PskcTlv>());
228             break;
229 #endif
230 
231         case Tlv::kMeshLocalPrefix:
232             Get<Mle::MleRouter>().SetMeshLocalPrefix(cur->ReadValueAs<MeshLocalPrefixTlv>());
233             break;
234 
235         case Tlv::kSecurityPolicy:
236             Get<KeyManager>().SetSecurityPolicy(As<SecurityPolicyTlv>(cur)->GetSecurityPolicy());
237             break;
238 
239         default:
240             break;
241         }
242     }
243 
244 exit:
245     return error;
246 }
247 
Clear(void)248 void DatasetManager::Clear(void)
249 {
250     mNetworkTimestamp.SetToInvalid();
251     mLocalTimestamp.SetToInvalid();
252 
253     mLocalSaved = false;
254 
255 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
256     DestroySecurelyStoredKeys();
257 #endif
258     Get<Settings>().DeleteOperationalDataset(mType);
259 
260     mTimer.Stop();
261 
262     if (IsPendingDataset())
263     {
264         Get<PendingDatasetManager>().mDelayTimer.Stop();
265     }
266 
267     SignalDatasetChange();
268 }
269 
Save(const Dataset & aDataset,bool aAllowOlderTimestamp)270 Error DatasetManager::Save(const Dataset &aDataset, bool aAllowOlderTimestamp)
271 {
272     Error error = kErrorNone;
273     int   compare;
274 
275     if ((aDataset.ReadTimestamp(mType, mNetworkTimestamp) == kErrorNone) && IsActiveDataset())
276     {
277         SuccessOrExit(error = ApplyConfiguration(aDataset));
278     }
279 
280     compare = Timestamp::Compare(mNetworkTimestamp, mLocalTimestamp);
281 
282     if ((compare > 0) || aAllowOlderTimestamp)
283     {
284         LocalSave(aDataset);
285 
286 #if OPENTHREAD_FTD
287         Get<NetworkData::Leader>().IncrementVersionAndStableVersion();
288 #endif
289     }
290     else if (compare < 0)
291     {
292         mTimer.Start(kSendSetDelay);
293     }
294 
295     SignalDatasetChange();
296 
297 exit:
298     return error;
299 }
300 
SaveLocal(const Dataset::Info & aDatasetInfo)301 void DatasetManager::SaveLocal(const Dataset::Info &aDatasetInfo)
302 {
303     Dataset dataset;
304 
305     dataset.SetFrom(aDatasetInfo);
306     SaveLocal(dataset);
307 }
308 
SaveLocal(const Dataset::Tlvs & aDatasetTlvs)309 Error DatasetManager::SaveLocal(const Dataset::Tlvs &aDatasetTlvs)
310 {
311     Error   error = kErrorInvalidArgs;
312     Dataset dataset;
313 
314     SuccessOrExit(dataset.SetFrom(aDatasetTlvs));
315     SuccessOrExit(dataset.ValidateTlvs());
316     SaveLocal(dataset);
317     error = kErrorNone;
318 
319 exit:
320     return error;
321 }
322 
SaveLocal(const Dataset & aDataset)323 void DatasetManager::SaveLocal(const Dataset &aDataset)
324 {
325     LocalSave(aDataset);
326 
327     switch (Get<Mle::MleRouter>().GetRole())
328     {
329     case Mle::kRoleDisabled:
330         Restore(aDataset);
331         break;
332 
333     case Mle::kRoleChild:
334         SyncLocalWithLeader(aDataset);
335         break;
336 #if OPENTHREAD_FTD
337     case Mle::kRoleRouter:
338         SyncLocalWithLeader(aDataset);
339         break;
340 
341     case Mle::kRoleLeader:
342         Restore(aDataset);
343         Get<NetworkData::Leader>().IncrementVersionAndStableVersion();
344         break;
345 #endif
346 
347     default:
348         break;
349     }
350 
351     SignalDatasetChange();
352 }
353 
LocalSave(const Dataset & aDataset)354 void DatasetManager::LocalSave(const Dataset &aDataset)
355 {
356 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
357     DestroySecurelyStoredKeys();
358 #endif
359 
360     if (aDataset.GetLength() == 0)
361     {
362         Get<Settings>().DeleteOperationalDataset(mType);
363         mLocalSaved = false;
364         LogInfo("%s dataset deleted", Dataset::TypeToString(mType));
365     }
366     else
367     {
368 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
369         // Store the network key and PSKC in the secure storage instead of settings.
370         Dataset dataset;
371 
372         dataset.SetFrom(aDataset);
373         MoveKeysToSecureStorage(dataset);
374         Get<Settings>().SaveOperationalDataset(mType, dataset);
375 #else
376         Get<Settings>().SaveOperationalDataset(mType, aDataset);
377 #endif
378 
379         mLocalSaved = true;
380         LogInfo("%s dataset set", Dataset::TypeToString(mType));
381     }
382 
383     if (aDataset.ReadTimestamp(mType, mLocalTimestamp) != kErrorNone)
384     {
385         mLocalTimestamp.SetToInvalid();
386     }
387 
388     mLocalUpdateTime = TimerMilli::GetNow();
389 
390     if (IsPendingDataset())
391     {
392         Get<PendingDatasetManager>().StartDelayTimer(aDataset);
393     }
394 }
395 
SignalDatasetChange(void) const396 void DatasetManager::SignalDatasetChange(void) const
397 {
398     Get<Notifier>().Signal(IsActiveDataset() ? kEventActiveDatasetChanged : kEventPendingDatasetChanged);
399 }
400 
GetChannelMask(Mac::ChannelMask & aChannelMask) const401 Error DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const
402 {
403     Error                 error;
404     const ChannelMaskTlv *channelMaskTlv;
405     uint32_t              mask;
406     Dataset               dataset;
407 
408     SuccessOrExit(error = Read(dataset));
409 
410     channelMaskTlv = As<ChannelMaskTlv>(dataset.FindTlv(Tlv::kChannelMask));
411     VerifyOrExit(channelMaskTlv != nullptr, error = kErrorNotFound);
412     SuccessOrExit(channelMaskTlv->ReadChannelMask(mask));
413 
414     aChannelMask.SetMask(mask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
415 
416     VerifyOrExit(!aChannelMask.IsEmpty(), error = kErrorNotFound);
417 
418 exit:
419     return error;
420 }
421 
HandleTimer(void)422 void DatasetManager::HandleTimer(void)
423 {
424     Dataset dataset;
425 
426     SuccessOrExit(Read(dataset));
427     SyncLocalWithLeader(dataset);
428 
429 exit:
430     return;
431 }
432 
SyncLocalWithLeader(const Dataset & aDataset)433 void DatasetManager::SyncLocalWithLeader(const Dataset &aDataset)
434 {
435     // Attempts to synchronize the local Dataset with the leader by
436     // sending `MGMT_SET` command if the local Dataset's timestamp is
437     // newer.
438 
439     Error error = kErrorNone;
440 
441     VerifyOrExit(!mMgmtPending, error = kErrorBusy);
442     VerifyOrExit(Get<Mle::MleRouter>().IsChild() || Get<Mle::MleRouter>().IsRouter(), error = kErrorInvalidState);
443 
444     VerifyOrExit(mNetworkTimestamp < mLocalTimestamp, error = kErrorAlready);
445 
446     if (IsActiveDataset())
447     {
448         Dataset   pendingDataset;
449         Timestamp timestamp;
450 
451         IgnoreError(Get<PendingDatasetManager>().Read(pendingDataset));
452 
453         if ((pendingDataset.Read<ActiveTimestampTlv>(timestamp) == kErrorNone) && (timestamp == mLocalTimestamp))
454         {
455             // Stop registration attempts during dataset transition
456             ExitNow(error = kErrorInvalidState);
457         }
458     }
459 
460     error = SendSetRequest(aDataset);
461 
462 exit:
463     if (error == kErrorNoBufs)
464     {
465         mTimer.Start(kSendSetDelay);
466     }
467 
468     if (error != kErrorAlready)
469     {
470         LogWarnOnError(error, "send Dataset set to leader");
471     }
472 }
473 
SendSetRequest(const Dataset & aDataset)474 Error DatasetManager::SendSetRequest(const Dataset &aDataset)
475 {
476     Error            error   = kErrorNone;
477     Coap::Message   *message = nullptr;
478     Tmf::MessageInfo messageInfo(GetInstance());
479 
480     VerifyOrExit(!mMgmtPending, error = kErrorAlready);
481 
482     message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(IsActiveDataset() ? kUriActiveSet : kUriPendingSet);
483     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
484 
485     SuccessOrExit(error = message->AppendBytes(aDataset.GetBytes(), aDataset.GetLength()));
486     messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc();
487 
488     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleMgmtSetResponse, this));
489     mMgmtPending = true;
490 
491     LogInfo("Sent dataset set request to leader");
492 
493 exit:
494     FreeMessageOnError(message, error);
495     return error;
496 }
497 
HandleMgmtSetResponse(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo,otError aError)498 void DatasetManager::HandleMgmtSetResponse(void                *aContext,
499                                            otMessage           *aMessage,
500                                            const otMessageInfo *aMessageInfo,
501                                            otError              aError)
502 {
503     static_cast<DatasetManager *>(aContext)->HandleMgmtSetResponse(AsCoapMessagePtr(aMessage),
504                                                                    AsCoreTypePtr(aMessageInfo), aError);
505 }
506 
HandleMgmtSetResponse(Coap::Message * aMessage,const Ip6::MessageInfo * aMessageInfo,Error aError)507 void DatasetManager::HandleMgmtSetResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aError)
508 {
509     OT_UNUSED_VARIABLE(aMessageInfo);
510 
511     Error   error;
512     uint8_t state = StateTlv::kPending;
513 
514     SuccessOrExit(error = aError);
515     VerifyOrExit(Tlv::Find<StateTlv>(*aMessage, state) == kErrorNone && state != StateTlv::kPending,
516                  error = kErrorParse);
517 
518     if (state == StateTlv::kReject)
519     {
520         error = kErrorRejected;
521     }
522 
523 exit:
524     LogInfo("MGMT_SET finished: %s", error == kErrorNone ? "Accepted" : ErrorToString(error));
525 
526     mMgmtPending = false;
527 
528     mMgmtSetCallback.InvokeAndClearIfSet(error);
529 
530     mTimer.Start(kSendSetDelay);
531 }
532 
HandleGet(const Coap::Message & aMessage,const Ip6::MessageInfo & aMessageInfo) const533 void DatasetManager::HandleGet(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
534 {
535     Error          error    = kErrorNone;
536     Coap::Message *response = ProcessGetRequest(aMessage, kCheckSecurityPolicyFlags);
537 
538     VerifyOrExit(response != nullptr);
539     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*response, aMessageInfo));
540 
541     LogInfo("sent %s dataset get response to %s", IsActiveDataset() ? "active" : "pending",
542             aMessageInfo.GetPeerAddr().ToString().AsCString());
543 
544 exit:
545     FreeMessageOnError(response, error);
546 }
547 
ProcessGetRequest(const Coap::Message & aRequest,SecurityPolicyCheckMode aCheckMode) const548 Coap::Message *DatasetManager::ProcessGetRequest(const Coap::Message    &aRequest,
549                                                  SecurityPolicyCheckMode aCheckMode) const
550 {
551     // Processes a MGMT_ACTIVE_GET or MGMT_PENDING_GET request
552     // and prepares the response.
553 
554     Error          error    = kErrorNone;
555     Coap::Message *response = nullptr;
556     Dataset        dataset;
557     TlvList        tlvList;
558     OffsetRange    offsetRange;
559 
560     if (Tlv::FindTlvValueOffsetRange(aRequest, Tlv::kGet, offsetRange) == kErrorNone)
561     {
562         while (!offsetRange.IsEmpty())
563         {
564             uint8_t tlvType;
565 
566             IgnoreError(aRequest.Read(offsetRange, tlvType));
567             tlvList.Add(tlvType);
568             offsetRange.AdvanceOffset(sizeof(uint8_t));
569         }
570 
571         // MGMT_PENDING_GET.rsp must include Delay Timer TLV (Thread 1.1.1
572         // Section 8.7.5.4).
573 
574         if (!tlvList.IsEmpty() && IsPendingDataset())
575         {
576             tlvList.Add(Tlv::kDelayTimer);
577         }
578     }
579 
580     // Ignore `Read()` error, since even if no Dataset is saved, we should
581     // respond with an empty one.
582 
583     IgnoreError(Read(dataset));
584 
585     response = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
586     VerifyOrExit(response != nullptr, error = kErrorNoBufs);
587 
588     for (const Tlv *tlv = dataset.GetTlvsStart(); tlv < dataset.GetTlvsEnd(); tlv = tlv->GetNext())
589     {
590         bool shouldAppend = true;
591 
592         if (!tlvList.IsEmpty())
593         {
594             shouldAppend = tlvList.Contains(tlv->GetType());
595         }
596 
597         if ((aCheckMode == kCheckSecurityPolicyFlags) && (tlv->GetType() == Tlv::kNetworkKey) &&
598             !Get<KeyManager>().GetSecurityPolicy().mObtainNetworkKeyEnabled)
599         {
600             shouldAppend = false;
601         }
602 
603         if (shouldAppend)
604         {
605             SuccessOrExit(error = tlv->AppendTo(*response));
606         }
607     }
608 
609 exit:
610     FreeAndNullMessageOnError(response, error);
611     return response;
612 }
613 
SendSetRequest(const Dataset::Info & aDatasetInfo,const uint8_t * aTlvs,uint8_t aLength,MgmtSetCallback aCallback,void * aContext)614 Error DatasetManager::SendSetRequest(const Dataset::Info &aDatasetInfo,
615                                      const uint8_t       *aTlvs,
616                                      uint8_t              aLength,
617                                      MgmtSetCallback      aCallback,
618                                      void                *aContext)
619 {
620     Error   error = kErrorNone;
621     Dataset dataset;
622 
623     dataset.SetFrom(aDatasetInfo);
624     SuccessOrExit(error = dataset.AppendTlvsFrom(aTlvs, aLength));
625 
626 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
627     if (Get<Commissioner>().IsActive() && !dataset.ContainsTlv(Tlv::kCommissionerSessionId))
628     {
629         SuccessOrExit(error = dataset.Write<CommissionerSessionIdTlv>(Get<Commissioner>().GetSessionId()));
630     }
631 #endif
632 
633     SuccessOrExit(error = SendSetRequest(dataset));
634     mMgmtSetCallback.Set(aCallback, aContext);
635 
636 exit:
637     return error;
638 }
639 
SendGetRequest(const Dataset::Components & aDatasetComponents,const uint8_t * aTlvTypes,uint8_t aLength,const otIp6Address * aAddress) const640 Error DatasetManager::SendGetRequest(const Dataset::Components &aDatasetComponents,
641                                      const uint8_t             *aTlvTypes,
642                                      uint8_t                    aLength,
643                                      const otIp6Address        *aAddress) const
644 {
645     Error            error = kErrorNone;
646     Coap::Message   *message;
647     Tmf::MessageInfo messageInfo(GetInstance());
648     TlvList          tlvList;
649 
650     if (aDatasetComponents.IsPresent<Dataset::kActiveTimestamp>())
651     {
652         tlvList.Add(Tlv::kActiveTimestamp);
653     }
654 
655     if (aDatasetComponents.IsPresent<Dataset::kPendingTimestamp>())
656     {
657         tlvList.Add(Tlv::kPendingTimestamp);
658     }
659 
660     if (aDatasetComponents.IsPresent<Dataset::kNetworkKey>())
661     {
662         tlvList.Add(Tlv::kNetworkKey);
663     }
664 
665     if (aDatasetComponents.IsPresent<Dataset::kNetworkName>())
666     {
667         tlvList.Add(Tlv::kNetworkName);
668     }
669 
670     if (aDatasetComponents.IsPresent<Dataset::kExtendedPanId>())
671     {
672         tlvList.Add(Tlv::kExtendedPanId);
673     }
674 
675     if (aDatasetComponents.IsPresent<Dataset::kMeshLocalPrefix>())
676     {
677         tlvList.Add(Tlv::kMeshLocalPrefix);
678     }
679 
680     if (aDatasetComponents.IsPresent<Dataset::kDelay>())
681     {
682         tlvList.Add(Tlv::kDelayTimer);
683     }
684 
685     if (aDatasetComponents.IsPresent<Dataset::kPanId>())
686     {
687         tlvList.Add(Tlv::kPanId);
688     }
689 
690     if (aDatasetComponents.IsPresent<Dataset::kChannel>())
691     {
692         tlvList.Add(Tlv::kChannel);
693     }
694 
695     if (aDatasetComponents.IsPresent<Dataset::kWakeupChannel>())
696     {
697         tlvList.Add(Tlv::kWakeupChannel);
698     }
699 
700     if (aDatasetComponents.IsPresent<Dataset::kPskc>())
701     {
702         tlvList.Add(Tlv::kPskc);
703     }
704 
705     if (aDatasetComponents.IsPresent<Dataset::kSecurityPolicy>())
706     {
707         tlvList.Add(Tlv::kSecurityPolicy);
708     }
709 
710     if (aDatasetComponents.IsPresent<Dataset::kChannelMask>())
711     {
712         tlvList.Add(Tlv::kChannelMask);
713     }
714 
715     for (uint8_t index = 0; index < aLength; index++)
716     {
717         tlvList.Add(aTlvTypes[index]);
718     }
719 
720     message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(IsActiveDataset() ? kUriActiveGet : kUriPendingGet);
721     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
722 
723     if (!tlvList.IsEmpty())
724     {
725         SuccessOrExit(error = Tlv::AppendTlv(*message, Tlv::kGet, tlvList.GetArrayBuffer(), tlvList.GetLength()));
726     }
727 
728     messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc();
729 
730     if (aAddress != nullptr)
731     {
732         // Use leader ALOC if `aAddress` is `nullptr`.
733         messageInfo.SetPeerAddr(AsCoreType(aAddress));
734     }
735 
736     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
737 
738     LogInfo("sent dataset get request");
739 
740 exit:
741     FreeMessageOnError(message, error);
742     return error;
743 }
744 
Add(uint8_t aTlvType)745 void DatasetManager::TlvList::Add(uint8_t aTlvType)
746 {
747     if (!Contains(aTlvType))
748     {
749         IgnoreError(PushBack(aTlvType));
750     }
751 }
752 
753 #if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
754 
755 const DatasetManager::SecurelyStoredTlv DatasetManager::kSecurelyStoredTlvs[] = {
756     {
757         Tlv::kNetworkKey,
758         KeyRefManager::kActiveDatasetNetworkKey,
759         KeyRefManager::kPendingDatasetNetworkKey,
760     },
761     {
762         Tlv::kPskc,
763         KeyRefManager::kActiveDatasetPskc,
764         KeyRefManager::kPendingDatasetPskc,
765     },
766 };
767 
DestroySecurelyStoredKeys(void) const768 void DatasetManager::DestroySecurelyStoredKeys(void) const
769 {
770     for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
771     {
772         Crypto::Storage::DestroyKey(Get<KeyRefManager>().KeyRefFor(entry.GetKeyRefType(mType)));
773     }
774 }
775 
MoveKeysToSecureStorage(Dataset & aDataset) const776 void DatasetManager::MoveKeysToSecureStorage(Dataset &aDataset) const
777 {
778     for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
779     {
780         KeyRef keyRef = Get<KeyRefManager>().KeyRefFor(entry.GetKeyRefType(mType));
781 
782         SaveTlvInSecureStorageAndClearValue(aDataset, entry.mTlvType, keyRef);
783     }
784 }
785 
EmplaceSecurelyStoredKeys(Dataset & aDataset) const786 void DatasetManager::EmplaceSecurelyStoredKeys(Dataset &aDataset) const
787 {
788     bool moveKeys = false;
789 
790     // If reading any of the TLVs fails, it indicates they are not yet
791     // stored in secure storage and are still contained in the `Dataset`
792     // read from `Settings`. In this case, we move the keys to secure
793     // storage and then clear them from 'Settings'.
794 
795     for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
796     {
797         KeyRef keyRef = Get<KeyRefManager>().KeyRefFor(entry.GetKeyRefType(mType));
798 
799         if (ReadTlvFromSecureStorage(aDataset, entry.mTlvType, keyRef) != kErrorNone)
800         {
801             moveKeys = true;
802         }
803     }
804 
805     if (moveKeys)
806     {
807         Dataset dataset;
808 
809         dataset.SetFrom(aDataset);
810         MoveKeysToSecureStorage(dataset);
811         Get<Settings>().SaveOperationalDataset(mType, dataset);
812     }
813 }
814 
SaveTlvInSecureStorageAndClearValue(Dataset & aDataset,Tlv::Type aTlvType,KeyRef aKeyRef) const815 void DatasetManager::SaveTlvInSecureStorageAndClearValue(Dataset &aDataset, Tlv::Type aTlvType, KeyRef aKeyRef) const
816 {
817     using namespace ot::Crypto::Storage;
818 
819     Tlv *tlv = aDataset.FindTlv(aTlvType);
820 
821     VerifyOrExit(tlv != nullptr);
822     VerifyOrExit(tlv->GetLength() > 0);
823 
824     SuccessOrAssert(ImportKey(aKeyRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent, tlv->GetValue(),
825                               tlv->GetLength()));
826 
827     memset(tlv->GetValue(), 0, tlv->GetLength());
828 
829 exit:
830     return;
831 }
832 
ReadTlvFromSecureStorage(Dataset & aDataset,Tlv::Type aTlvType,KeyRef aKeyRef) const833 Error DatasetManager::ReadTlvFromSecureStorage(Dataset &aDataset, Tlv::Type aTlvType, KeyRef aKeyRef) const
834 {
835     using namespace ot::Crypto::Storage;
836 
837     Error  error = kErrorNone;
838     Tlv   *tlv   = aDataset.FindTlv(aTlvType);
839     size_t readLength;
840 
841     VerifyOrExit(tlv != nullptr);
842     VerifyOrExit(tlv->GetLength() > 0);
843 
844     SuccessOrExit(error = ExportKey(aKeyRef, tlv->GetValue(), tlv->GetLength(), readLength));
845     VerifyOrExit(readLength == tlv->GetLength(), error = OT_ERROR_FAILED);
846 
847 exit:
848     return error;
849 }
850 
851 #endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
852 
853 //---------------------------------------------------------------------------------------------------------------------
854 // ActiveDatasetManager
855 
ActiveDatasetManager(Instance & aInstance)856 ActiveDatasetManager::ActiveDatasetManager(Instance &aInstance)
857     : DatasetManager(aInstance, Dataset::kActive, ActiveDatasetManager::HandleTimer)
858 {
859 }
860 
IsPartiallyComplete(void) const861 bool ActiveDatasetManager::IsPartiallyComplete(void) const { return mLocalSaved && !mNetworkTimestamp.IsValid(); }
862 
IsComplete(void) const863 bool ActiveDatasetManager::IsComplete(void) const { return mLocalSaved && mNetworkTimestamp.IsValid(); }
864 
IsCommissioned(void) const865 bool ActiveDatasetManager::IsCommissioned(void) const
866 {
867     static const Tlv::Type kRequiredTlvs[] = {
868         Tlv::kNetworkKey, Tlv::kNetworkName, Tlv::kExtendedPanId, Tlv::kPanId, Tlv::kChannel,
869     };
870 
871     Dataset dataset;
872     bool    isValid = false;
873 
874     SuccessOrExit(Read(dataset));
875     isValid = dataset.ContainsAllTlvs(kRequiredTlvs, sizeof(kRequiredTlvs));
876 
877 exit:
878     return isValid;
879 }
880 
881 template <>
HandleTmf(Coap::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)882 void ActiveDatasetManager::HandleTmf<kUriActiveGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
883 {
884     DatasetManager::HandleGet(aMessage, aMessageInfo);
885 }
886 
HandleTimer(Timer & aTimer)887 void ActiveDatasetManager::HandleTimer(Timer &aTimer) { aTimer.Get<ActiveDatasetManager>().HandleTimer(); }
888 
889 //---------------------------------------------------------------------------------------------------------------------
890 // PendingDatasetManager
891 
PendingDatasetManager(Instance & aInstance)892 PendingDatasetManager::PendingDatasetManager(Instance &aInstance)
893     : DatasetManager(aInstance, Dataset::kPending, PendingDatasetManager::HandleTimer)
894     , mDelayTimer(aInstance)
895 {
896 }
897 
ReadActiveTimestamp(Timestamp & aTimestamp) const898 Error PendingDatasetManager::ReadActiveTimestamp(Timestamp &aTimestamp) const
899 {
900     Error   error = kErrorNotFound;
901     Dataset dataset;
902 
903     SuccessOrExit(Read(dataset));
904 
905     SuccessOrExit(dataset.Read<ActiveTimestampTlv>(aTimestamp));
906     error = kErrorNone;
907 
908 exit:
909     return error;
910 }
911 
ReadRemainingDelay(uint32_t & aRemainingDelay) const912 Error PendingDatasetManager::ReadRemainingDelay(uint32_t &aRemainingDelay) const
913 {
914     Error     error = kErrorNone;
915     TimeMilli now   = TimerMilli::GetNow();
916 
917     aRemainingDelay = 0;
918 
919     VerifyOrExit(mDelayTimer.IsRunning(), error = kErrorNotFound);
920     VerifyOrExit(mDelayTimer.GetFireTime() > now);
921     aRemainingDelay = mDelayTimer.GetFireTime() - now;
922 
923 exit:
924     return error;
925 }
926 
StartDelayTimer(void)927 void PendingDatasetManager::StartDelayTimer(void)
928 {
929     Dataset dataset;
930 
931     mDelayTimer.Stop();
932 
933     SuccessOrExit(Read(dataset));
934     StartDelayTimer(dataset);
935 
936 exit:
937     return;
938 }
939 
StartDelayTimer(const Dataset & aDataset)940 void PendingDatasetManager::StartDelayTimer(const Dataset &aDataset)
941 {
942     uint32_t delay;
943 
944     mDelayTimer.Stop();
945 
946     SuccessOrExit(aDataset.Read<DelayTimerTlv>(delay));
947 
948     delay = Min(delay, DelayTimerTlv::kMaxDelay);
949 
950     mDelayTimer.StartAt(aDataset.GetUpdateTime(), delay);
951     LogInfo("delay timer started %lu", ToUlong(delay));
952 
953 exit:
954     return;
955 }
956 
HandleDelayTimer(void)957 void PendingDatasetManager::HandleDelayTimer(void)
958 {
959     Dataset   dataset;
960     Timestamp activeTimestamp;
961     bool      shouldReplaceActive = false;
962 
963     SuccessOrExit(Read(dataset));
964 
965     LogInfo("Pending delay timer expired");
966 
967     // Determine whether the Pending Dataset should replace the
968     // current Active Dataset. This is allowed if the Pending
969     // Dataset's Active Timestamp is newer, or the Pending Dataset
970     // contains a different key.
971 
972     SuccessOrExit(dataset.Read<ActiveTimestampTlv>(activeTimestamp));
973 
974     if (activeTimestamp > Get<ActiveDatasetManager>().GetTimestamp())
975     {
976         shouldReplaceActive = true;
977     }
978     else
979     {
980         NetworkKey newKey;
981         NetworkKey currentKey;
982 
983         SuccessOrExit(dataset.Read<NetworkKeyTlv>(newKey));
984         Get<KeyManager>().GetNetworkKey(currentKey);
985         shouldReplaceActive = (currentKey != newKey);
986     }
987 
988     VerifyOrExit(shouldReplaceActive);
989 
990     // Convert Pending Dataset to Active by removing the Pending
991     // Timestamp and the Delay Timer TLVs.
992 
993     dataset.RemoveTlv(Tlv::kPendingTimestamp);
994     dataset.RemoveTlv(Tlv::kDelayTimer);
995 
996     IgnoreError(Get<ActiveDatasetManager>().Save(dataset, /* aAllowOlderTimestamp */ true));
997 
998 exit:
999     Clear();
1000 }
1001 
1002 template <>
HandleTmf(Coap::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)1003 void PendingDatasetManager::HandleTmf<kUriPendingGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
1004 {
1005     DatasetManager::HandleGet(aMessage, aMessageInfo);
1006 }
1007 
HandleTimer(Timer & aTimer)1008 void PendingDatasetManager::HandleTimer(Timer &aTimer) { aTimer.Get<PendingDatasetManager>().HandleTimer(); }
1009 
1010 } // namespace MeshCoP
1011 } // namespace ot
1012