• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018, 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 includes definitions for non-volatile storage of settings.
32  */
33 
34 #include "settings.hpp"
35 
36 #include "instance/instance.hpp"
37 
38 namespace ot {
39 
40 RegisterLogModule("Settings");
41 
42 //---------------------------------------------------------------------------------------------------------------------
43 // SettingsBase
44 
45 // LCOV_EXCL_START
46 
47 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
48 
Log(Action aAction) const49 void SettingsBase::NetworkInfo::Log(Action aAction) const
50 {
51     LogInfo("%s NetworkInfo {rloc:0x%04x, extaddr:%s, role:%s, mode:0x%02x, version:%u, keyseq:0x%lx, ...",
52             ActionToString(aAction), GetRloc16(), GetExtAddress().ToString().AsCString(),
53             Mle::RoleToString(static_cast<Mle::DeviceRole>(GetRole())), GetDeviceMode(), GetVersion(),
54             ToUlong(GetKeySequence()));
55 
56     LogInfo("... pid:0x%lx, mlecntr:0x%lx, maccntr:0x%lx, mliid:%s}", ToUlong(GetPreviousPartitionId()),
57             ToUlong(GetMleFrameCounter()), ToUlong(GetMacFrameCounter()), GetMeshLocalIid().ToString().AsCString());
58 }
59 
Log(Action aAction) const60 void SettingsBase::ParentInfo::Log(Action aAction) const
61 {
62     LogInfo("%s ParentInfo {extaddr:%s, version:%u}", ActionToString(aAction), GetExtAddress().ToString().AsCString(),
63             GetVersion());
64 }
65 
66 #if OPENTHREAD_FTD
Log(Action aAction) const67 void SettingsBase::ChildInfo::Log(Action aAction) const
68 {
69     LogInfo("%s ChildInfo {rloc:0x%04x, extaddr:%s, timeout:%lu, mode:0x%02x, version:%u}", ActionToString(aAction),
70             GetRloc16(), GetExtAddress().ToString().AsCString(), ToUlong(GetTimeout()), GetMode(), GetVersion());
71 }
72 #endif
73 
74 #if OPENTHREAD_CONFIG_DUA_ENABLE
Log(Action aAction) const75 void SettingsBase::DadInfo::Log(Action aAction) const
76 {
77     LogInfo("%s DadInfo {DadCounter:%2d}", ActionToString(aAction), GetDadCounter());
78 }
79 #endif
80 
81 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
LogPrefix(Action aAction,Key aKey,const Ip6::Prefix & aPrefix)82 void SettingsBase::LogPrefix(Action aAction, Key aKey, const Ip6::Prefix &aPrefix)
83 {
84     LogInfo("%s %s %s", ActionToString(aAction), KeyToString(aKey), aPrefix.ToString().AsCString());
85 }
86 #endif
87 
88 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
Log(Action aAction) const89 void SettingsBase::SrpClientInfo::Log(Action aAction) const
90 {
91     LogInfo("%s SrpClientInfo {Server:[%s]:%u}", ActionToString(aAction), GetServerAddress().ToString().AsCString(),
92             GetServerPort());
93 }
94 #endif
95 
96 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
Log(Action aAction) const97 void SettingsBase::SrpServerInfo::Log(Action aAction) const
98 {
99     LogInfo("%s SrpServerInfo {port:%u}", ActionToString(aAction), GetPort());
100 }
101 #endif
102 
103 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
Log(Action aAction,const MeshCoP::BorderAgent::Id & aId)104 void SettingsBase::BorderAgentId::Log(Action aAction, const MeshCoP::BorderAgent::Id &aId)
105 {
106     static constexpr uint8_t kStringSize = sizeof(MeshCoP::BorderAgent::Id) * 2 + 1;
107 
108     String<kStringSize> string;
109 
110     string.AppendHexBytes(aId.mId, sizeof(aId));
111     LogInfo("%s BorderAgentId {id:%s}", ActionToString(aAction), string.AsCString());
112 }
113 #endif
114 
115 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
116 
117 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
ActionToString(Action aAction)118 const char *SettingsBase::ActionToString(Action aAction)
119 {
120     static const char *const kActionStrings[] = {
121         "Read",     // (0) kActionRead
122         "Saved",    // (1) kActionSave
123         "Re-saved", // (2) kActionResave
124         "Deleted",  // (3) kActionDelete
125 #if OPENTHREAD_FTD
126         "Added",      // (4) kActionAdd,
127         "Removed",    // (5) kActionRemove,
128         "Deleted all" // (6) kActionDeleteAll
129 #endif
130     };
131 
132     struct EnumCheck
133     {
134         InitEnumValidatorCounter();
135         ValidateNextEnum(kActionRead);
136         ValidateNextEnum(kActionSave);
137         ValidateNextEnum(kActionResave);
138         ValidateNextEnum(kActionDelete);
139 #if OPENTHREAD_FTD
140         ValidateNextEnum(kActionAdd);
141         ValidateNextEnum(kActionRemove);
142         ValidateNextEnum(kActionDeleteAll);
143 #endif
144     };
145 
146     return kActionStrings[aAction];
147 }
148 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
149 
150 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
KeyToString(Key aKey)151 const char *SettingsBase::KeyToString(Key aKey)
152 {
153     static const char *const kKeyStrings[] = {
154         "",                  // (0)  (Unused)
155         "ActiveDataset",     // (1)  kKeyActiveDataset
156         "PendingDataset",    // (2)  kKeyPendingDataset
157         "NetworkInfo",       // (3)  kKeyNetworkInfo
158         "ParentInfo",        // (4)  kKeyParentInfo
159         "ChildInfo",         // (5)  kKeyChildInfo
160         "",                  // (6)  Removed (previously auto-start).
161         "SlaacIidSecretKey", // (7)  kKeySlaacIidSecretKey
162         "DadInfo",           // (8)  kKeyDadInfo
163         "",                  // (9)  Removed (previously OMR prefix).
164         "",                  // (10) Removed (previously on-link prefix).
165         "SrpEcdsaKey",       // (11) kKeySrpEcdsaKey
166         "SrpClientInfo",     // (12) kKeySrpClientInfo
167         "SrpServerInfo",     // (13) kKeySrpServerInfo
168         "",                  // (14) Removed (previously NAT64 prefix)
169         "BrUlaPrefix",       // (15) kKeyBrUlaPrefix
170         "BrOnLinkPrefixes",  // (16) kKeyBrOnLinkPrefixes
171         "BorderAgentId",     // (17) kKeyBorderAgentId
172         "TcatCommrCert"      // (18) kKeyTcatCommrCert
173     };
174 
175     struct EnumCheck
176     {
177         InitEnumValidatorCounter();
178         SkipNextEnum();
179         ValidateNextEnum(kKeyActiveDataset);
180         ValidateNextEnum(kKeyPendingDataset);
181         ValidateNextEnum(kKeyNetworkInfo);
182         ValidateNextEnum(kKeyParentInfo);
183         ValidateNextEnum(kKeyChildInfo);
184         SkipNextEnum();
185         ValidateNextEnum(kKeySlaacIidSecretKey);
186         ValidateNextEnum(kKeyDadInfo);
187         SkipNextEnum();
188         SkipNextEnum();
189         ValidateNextEnum(kKeySrpEcdsaKey);
190         ValidateNextEnum(kKeySrpClientInfo);
191         ValidateNextEnum(kKeySrpServerInfo);
192         SkipNextEnum();
193         ValidateNextEnum(kKeyBrUlaPrefix);
194         ValidateNextEnum(kKeyBrOnLinkPrefixes);
195         ValidateNextEnum(kKeyBorderAgentId);
196         ValidateNextEnum(kKeyTcatCommrCert);
197     };
198 
199     static_assert(kLastKey == kKeyTcatCommrCert, "kLastKey is not valid");
200 
201     OT_ASSERT(aKey <= kLastKey);
202 
203     return kKeyStrings[aKey];
204 }
205 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
206 
207 // LCOV_EXCL_STOP
208 
209 //---------------------------------------------------------------------------------------------------------------------
210 // Settings
211 
212 // This array contains sensitive keys that should be stored in the secure area.
213 const uint16_t Settings::kSensitiveKeys[] = {
214     SettingsBase::kKeyActiveDataset,
215     SettingsBase::kKeyPendingDataset,
216     SettingsBase::kKeySrpEcdsaKey,
217 };
218 
Init(void)219 void Settings::Init(void) { Get<SettingsDriver>().Init(kSensitiveKeys, GetArrayLength(kSensitiveKeys)); }
220 
Deinit(void)221 void Settings::Deinit(void) { Get<SettingsDriver>().Deinit(); }
222 
Wipe(void)223 void Settings::Wipe(void)
224 {
225     Get<SettingsDriver>().Wipe();
226     LogInfo("Wiped all info");
227 }
228 
KeyForDatasetType(MeshCoP::Dataset::Type aType)229 Settings::Key Settings::KeyForDatasetType(MeshCoP::Dataset::Type aType)
230 {
231     return (aType == MeshCoP::Dataset::kActive) ? kKeyActiveDataset : kKeyPendingDataset;
232 }
233 
SaveOperationalDataset(MeshCoP::Dataset::Type aType,const MeshCoP::Dataset & aDataset)234 void Settings::SaveOperationalDataset(MeshCoP::Dataset::Type aType, const MeshCoP::Dataset &aDataset)
235 {
236     Key   key   = KeyForDatasetType(aType);
237     Error error = Get<SettingsDriver>().Set(key, aDataset.GetBytes(), aDataset.GetLength());
238 
239     Log(kActionSave, error, key);
240 
241     SuccessOrAssert(error);
242 }
243 
ReadOperationalDataset(MeshCoP::Dataset::Type aType,MeshCoP::Dataset & aDataset) const244 Error Settings::ReadOperationalDataset(MeshCoP::Dataset::Type aType, MeshCoP::Dataset &aDataset) const
245 {
246     Error    error  = kErrorNone;
247     uint16_t length = MeshCoP::Dataset::kMaxLength;
248 
249     SuccessOrExit(error = Get<SettingsDriver>().Get(KeyForDatasetType(aType), aDataset.GetBytes(), &length));
250     VerifyOrExit(length <= MeshCoP::Dataset::kMaxLength, error = kErrorNotFound);
251 
252     aDataset.SetLength(static_cast<uint8_t>(length));
253 
254 exit:
255     OT_ASSERT(error != kErrorNotImplemented);
256     return error;
257 }
258 
DeleteOperationalDataset(MeshCoP::Dataset::Type aType)259 void Settings::DeleteOperationalDataset(MeshCoP::Dataset::Type aType)
260 {
261     Key   key   = KeyForDatasetType(aType);
262     Error error = Get<SettingsDriver>().Delete(key);
263 
264     Log(kActionDelete, error, key);
265     OT_ASSERT(error != kErrorNotImplemented);
266 }
267 
268 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
SaveTcatCommissionerCertificate(uint8_t * aCert,uint16_t aCertLen)269 void Settings::SaveTcatCommissionerCertificate(uint8_t *aCert, uint16_t aCertLen)
270 {
271     Error error = Get<SettingsDriver>().Set(kKeyTcatCommrCert, aCert, aCertLen);
272 
273     Log(kActionSave, error, kKeyTcatCommrCert);
274 
275     SuccessOrAssert(error);
276 }
277 #endif
278 
279 #if OPENTHREAD_FTD
AddChildInfo(const ChildInfo & aChildInfo)280 Error Settings::AddChildInfo(const ChildInfo &aChildInfo)
281 {
282     Error error = Get<SettingsDriver>().Add(kKeyChildInfo, &aChildInfo, sizeof(aChildInfo));
283 
284     Log(kActionAdd, error, kKeyChildInfo, &aChildInfo);
285 
286     return error;
287 }
288 
DeleteAllChildInfo(void)289 Error Settings::DeleteAllChildInfo(void)
290 {
291     Error error = Get<SettingsDriver>().Delete(kKeyChildInfo);
292 
293     Log(kActionDeleteAll, error, kKeyChildInfo);
294 
295     return error;
296 }
297 
ChildInfoIterator(Instance & aInstance)298 Settings::ChildInfoIterator::ChildInfoIterator(Instance &aInstance)
299     : SettingsBase(aInstance)
300     , mIndex(0)
301     , mIsDone(false)
302 {
303     Read();
304 }
305 
Advance(void)306 void Settings::ChildInfoIterator::Advance(void)
307 {
308     if (!mIsDone)
309     {
310         mIndex++;
311         Read();
312     }
313 }
314 
Delete(void)315 Error Settings::ChildInfoIterator::Delete(void)
316 {
317     Error error = kErrorNone;
318 
319     VerifyOrExit(!mIsDone, error = kErrorInvalidState);
320     SuccessOrExit(error = Get<SettingsDriver>().Delete(kKeyChildInfo, mIndex));
321 
322 exit:
323     Log(kActionRemove, error, kKeyChildInfo, &mChildInfo);
324     return error;
325 }
326 
Read(void)327 void Settings::ChildInfoIterator::Read(void)
328 {
329     uint16_t length = sizeof(ChildInfo);
330     Error    error;
331 
332     mChildInfo.Init();
333     SuccessOrExit(
334         error = Get<SettingsDriver>().Get(kKeyChildInfo, mIndex, reinterpret_cast<uint8_t *>(&mChildInfo), &length));
335 
336 exit:
337     Log(kActionRead, error, kKeyChildInfo, &mChildInfo);
338     mIsDone = (error != kErrorNone);
339 }
340 #endif // OPENTHREAD_FTD
341 
342 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
AddOrUpdateBrOnLinkPrefix(const BrOnLinkPrefix & aBrOnLinkPrefix)343 Error Settings::AddOrUpdateBrOnLinkPrefix(const BrOnLinkPrefix &aBrOnLinkPrefix)
344 {
345     Error          error = kErrorNone;
346     int            index = 0;
347     BrOnLinkPrefix brPrefix;
348     bool           didUpdate = false;
349 
350     while (ReadBrOnLinkPrefix(index, brPrefix) == kErrorNone)
351     {
352         if (brPrefix.GetPrefix() == aBrOnLinkPrefix.GetPrefix())
353         {
354             if (brPrefix.GetLifetime() == aBrOnLinkPrefix.GetLifetime())
355             {
356                 // Existing entry fully matches `aBrOnLinkPrefix`.
357                 // No need to make any changes.
358                 ExitNow();
359             }
360 
361             SuccessOrExit(error = Get<SettingsDriver>().Delete(kKeyBrOnLinkPrefixes, index));
362             didUpdate = true;
363             break;
364         }
365 
366         index++;
367     }
368 
369     SuccessOrExit(error = Get<SettingsDriver>().Add(kKeyBrOnLinkPrefixes, &aBrOnLinkPrefix, sizeof(BrOnLinkPrefix)));
370     brPrefix.Log(didUpdate ? "Updated" : "Added");
371 
372 exit:
373     return error;
374 }
375 
RemoveBrOnLinkPrefix(const Ip6::Prefix & aPrefix)376 Error Settings::RemoveBrOnLinkPrefix(const Ip6::Prefix &aPrefix)
377 {
378     Error          error = kErrorNotFound;
379     BrOnLinkPrefix brPrefix;
380 
381     for (int index = 0; ReadBrOnLinkPrefix(index, brPrefix) == kErrorNone; index++)
382     {
383         if (brPrefix.GetPrefix() == aPrefix)
384         {
385             SuccessOrExit(error = Get<SettingsDriver>().Delete(kKeyBrOnLinkPrefixes, index));
386             brPrefix.Log("Removed");
387             break;
388         }
389     }
390 
391 exit:
392     return error;
393 }
394 
DeleteAllBrOnLinkPrefixes(void)395 Error Settings::DeleteAllBrOnLinkPrefixes(void) { return Get<SettingsDriver>().Delete(kKeyBrOnLinkPrefixes); }
396 
ReadBrOnLinkPrefix(int aIndex,BrOnLinkPrefix & aBrOnLinkPrefix)397 Error Settings::ReadBrOnLinkPrefix(int aIndex, BrOnLinkPrefix &aBrOnLinkPrefix)
398 {
399     uint16_t length = sizeof(BrOnLinkPrefix);
400 
401     aBrOnLinkPrefix.Init();
402 
403     return Get<SettingsDriver>().Get(kKeyBrOnLinkPrefixes, aIndex, &aBrOnLinkPrefix, &length);
404 }
405 
Log(const char * aActionText) const406 void Settings::BrOnLinkPrefix::Log(const char *aActionText) const
407 {
408     OT_UNUSED_VARIABLE(aActionText);
409 
410     LogInfo("%s %s entry {prefix:%s,lifetime:%lu}", aActionText, KeyToString(kKeyBrOnLinkPrefixes),
411             GetPrefix().ToString().AsCString(), ToUlong(GetLifetime()));
412 }
413 
414 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
415 
ReadEntry(Key aKey,void * aValue,uint16_t aMaxLength) const416 Error Settings::ReadEntry(Key aKey, void *aValue, uint16_t aMaxLength) const
417 {
418     Error    error;
419     uint16_t length = aMaxLength;
420 
421     error = Get<SettingsDriver>().Get(aKey, aValue, &length);
422     Log(kActionRead, error, aKey, aValue);
423 
424     return error;
425 }
426 
SaveEntry(Key aKey,const void * aValue,void * aPrev,uint16_t aLength)427 Error Settings::SaveEntry(Key aKey, const void *aValue, void *aPrev, uint16_t aLength)
428 {
429     Error    error      = kErrorNone;
430     uint16_t readLength = aLength;
431     Action   action     = kActionSave;
432 
433     if ((Get<SettingsDriver>().Get(aKey, aPrev, &readLength) == kErrorNone) && (readLength == aLength) &&
434         (memcmp(aValue, aPrev, aLength) == 0))
435     {
436         action = kActionResave;
437     }
438     else
439     {
440         error = Get<SettingsDriver>().Set(aKey, aValue, aLength);
441     }
442 
443     Log(action, error, aKey, aValue);
444 
445     return error;
446 }
447 
DeleteEntry(Key aKey)448 Error Settings::DeleteEntry(Key aKey)
449 {
450     Error error = Get<SettingsDriver>().Delete(aKey);
451 
452     Log(kActionDelete, error, aKey);
453 
454     return error;
455 }
456 
Log(Action aAction,Error aError,Key aKey,const void * aValue)457 void Settings::Log(Action aAction, Error aError, Key aKey, const void *aValue)
458 {
459     OT_UNUSED_VARIABLE(aAction);
460     OT_UNUSED_VARIABLE(aKey);
461     OT_UNUSED_VARIABLE(aError);
462     OT_UNUSED_VARIABLE(aValue);
463 
464     if (aError != kErrorNone)
465     {
466         // Log error if log level is at "warn" or higher.
467 
468 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
469         const char *actionText = "";
470 
471         switch (aAction)
472         {
473         case kActionSave:
474         case kActionResave:
475             actionText = "saving";
476             break;
477 
478         case kActionDelete:
479             VerifyOrExit(aError != kErrorNotFound);
480             actionText = "deleting";
481             break;
482 
483 #if OPENTHREAD_FTD
484         case kActionAdd:
485             actionText = "adding";
486             break;
487 
488         case kActionRemove:
489             VerifyOrExit(aError != kErrorNotFound);
490             actionText = "removing";
491             break;
492 
493         case kActionDeleteAll:
494             VerifyOrExit(aError != kErrorNotFound);
495             actionText = "deleting all";
496             break;
497 #endif
498         case kActionRead:
499             ExitNow();
500         }
501 
502         LogWarn("Error %s %s %s", ErrorToString(aError), actionText, KeyToString(aKey));
503 
504 #endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
505 
506         ExitNow();
507     }
508 
509     // We reach here when `aError` is `kErrorNone`.
510     // Log success if log level is at "info" or higher.
511 
512 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
513     if (aValue != nullptr)
514     {
515         switch (aKey)
516         {
517         case kKeyNetworkInfo:
518             reinterpret_cast<const NetworkInfo *>(aValue)->Log(aAction);
519             break;
520 
521         case kKeyParentInfo:
522             reinterpret_cast<const ParentInfo *>(aValue)->Log(aAction);
523             break;
524 
525 #if OPENTHREAD_FTD
526         case kKeyChildInfo:
527             reinterpret_cast<const ChildInfo *>(aValue)->Log(aAction);
528             break;
529 #endif
530 
531 #if OPENTHREAD_CONFIG_DUA_ENABLE
532         case kKeyDadInfo:
533             reinterpret_cast<const DadInfo *>(aValue)->Log(aAction);
534             break;
535 #endif
536 
537 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
538         case kKeyBrUlaPrefix:
539             LogPrefix(aAction, aKey, *reinterpret_cast<const Ip6::Prefix *>(aValue));
540             break;
541 #endif
542 
543 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_SAVE_SELECTED_SERVER_ENABLE
544         case kKeySrpClientInfo:
545             reinterpret_cast<const SrpClientInfo *>(aValue)->Log(aAction);
546             break;
547 #endif
548 
549 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
550         case kKeySrpServerInfo:
551             reinterpret_cast<const SrpServerInfo *>(aValue)->Log(aAction);
552             break;
553 #endif
554 
555 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
556         case kKeyBorderAgentId:
557             BorderAgentId::Log(aAction, *reinterpret_cast<const MeshCoP::BorderAgent::Id *>(aValue));
558             break;
559 #endif
560 
561         default:
562             // For any other keys, we do not want to include the value
563             // in the log, so even if it is given we set `aValue` to
564             // `nullptr`. This ensures that we just log the action and
565             // the key.
566             aValue = nullptr;
567             break;
568         }
569     }
570 
571     if (aValue == nullptr)
572     {
573         LogInfo("%s %s", ActionToString(aAction), KeyToString(aKey));
574     }
575 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
576 
577 exit:
578     return;
579 }
580 
581 } // namespace ot
582 
583 //---------------------------------------------------------------------------------------------------------------------
584 // Default/weak implementation of settings platform APIs
585 
otPlatSettingsSetCriticalKeys(otInstance * aInstance,const uint16_t * aKeys,uint16_t aKeysLength)586 OT_TOOL_WEAK void otPlatSettingsSetCriticalKeys(otInstance *aInstance, const uint16_t *aKeys, uint16_t aKeysLength)
587 {
588     OT_UNUSED_VARIABLE(aInstance);
589     OT_UNUSED_VARIABLE(aKeys);
590     OT_UNUSED_VARIABLE(aKeysLength);
591 }
592