• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements the OpenThread platform abstraction for non-volatile storage of settings.
32  */
33 
34 #include "openthread-posix-config.h"
35 #include "platform-posix.h"
36 
37 #include <assert.h>
38 #include <fcntl.h>
39 #include <inttypes.h>
40 #include <stddef.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <sys/stat.h>
44 #include <unistd.h>
45 
46 #include <openthread/logging.h>
47 #include <openthread/platform/misc.h>
48 #include <openthread/platform/radio.h>
49 #include <openthread/platform/settings.h>
50 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
51 #include <openthread/platform/secure_settings.h>
52 #endif
53 
54 #include "common/code_utils.hpp"
55 #include "common/encoding.hpp"
56 #include "posix/platform/settings.hpp"
57 #include "posix/platform/settings_file.hpp"
58 
59 #include "system.hpp"
60 
61 static ot::Posix::SettingsFile sSettingsFile;
62 
63 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
64 static const uint16_t *sSensitiveKeys       = nullptr;
65 static uint16_t        sSensitiveKeysLength = 0;
66 
isSensitiveKey(uint16_t aKey)67 static bool isSensitiveKey(uint16_t aKey)
68 {
69     bool ret = false;
70 
71     VerifyOrExit(sSensitiveKeys != nullptr);
72 
73     for (uint16_t i = 0; i < sSensitiveKeysLength; i++)
74     {
75         VerifyOrExit(aKey != sSensitiveKeys[i], ret = true);
76     }
77 
78 exit:
79     return ret;
80 }
81 #endif
82 
settingsFileInit(otInstance * aInstance)83 static otError settingsFileInit(otInstance *aInstance)
84 {
85     static constexpr size_t kMaxFileBaseNameSize = 32;
86     char                    fileBaseName[kMaxFileBaseNameSize];
87     const char             *offset = getenv("PORT_OFFSET");
88     uint64_t                nodeId;
89 
90     otPlatRadioGetIeeeEui64(aInstance, reinterpret_cast<uint8_t *>(&nodeId));
91     nodeId = ot::BigEndian::HostSwap64(nodeId);
92 
93     snprintf(fileBaseName, sizeof(fileBaseName), "%s_%" PRIx64, offset == nullptr ? "0" : offset, nodeId);
94     VerifyOrDie(strlen(fileBaseName) < kMaxFileBaseNameSize, OT_EXIT_FAILURE);
95 
96     return sSettingsFile.Init(fileBaseName);
97 }
98 
otPlatSettingsInit(otInstance * aInstance,const uint16_t * aSensitiveKeys,uint16_t aSensitiveKeysLength)99 void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
100 {
101 #if !OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
102     OT_UNUSED_VARIABLE(aSensitiveKeys);
103     OT_UNUSED_VARIABLE(aSensitiveKeysLength);
104 #endif
105 
106 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
107     sSensitiveKeys       = aSensitiveKeys;
108     sSensitiveKeysLength = aSensitiveKeysLength;
109 #endif
110 
111     // Don't touch the settings file the system runs in dry-run mode.
112     VerifyOrExit(!IsSystemDryRun());
113     SuccessOrExit(settingsFileInit(aInstance));
114 
115 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
116     otPosixSecureSettingsInit(aInstance);
117 #endif
118 
119 exit:
120     return;
121 }
122 
otPlatSettingsDeinit(otInstance * aInstance)123 void otPlatSettingsDeinit(otInstance *aInstance)
124 {
125     OT_UNUSED_VARIABLE(aInstance);
126 
127     VerifyOrExit(!IsSystemDryRun());
128 
129 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
130     otPosixSecureSettingsDeinit(aInstance);
131 #endif
132 
133     sSettingsFile.Deinit();
134 
135 exit:
136     return;
137 }
138 
otPlatSettingsGet(otInstance * aInstance,uint16_t aKey,int aIndex,uint8_t * aValue,uint16_t * aValueLength)139 otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
140 {
141     OT_UNUSED_VARIABLE(aInstance);
142 
143     otError error = OT_ERROR_NOT_FOUND;
144 
145     VerifyOrExit(!IsSystemDryRun());
146 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
147     if (isSensitiveKey(aKey))
148     {
149         error = otPosixSecureSettingsGet(aInstance, aKey, aIndex, aValue, aValueLength);
150     }
151     else
152 #endif
153     {
154         error = sSettingsFile.Get(aKey, aIndex, aValue, aValueLength);
155     }
156 
157 exit:
158     VerifyOrDie(error != OT_ERROR_PARSE, OT_EXIT_FAILURE);
159     return error;
160 }
161 
otPlatSettingsSet(otInstance * aInstance,uint16_t aKey,const uint8_t * aValue,uint16_t aValueLength)162 otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
163 {
164     OT_UNUSED_VARIABLE(aInstance);
165 
166     otError error = OT_ERROR_NONE;
167 
168 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
169     if (isSensitiveKey(aKey))
170     {
171         error = otPosixSecureSettingsSet(aInstance, aKey, aValue, aValueLength);
172     }
173     else
174 #endif
175     {
176         sSettingsFile.Set(aKey, aValue, aValueLength);
177     }
178 
179     return error;
180 }
181 
otPlatSettingsAdd(otInstance * aInstance,uint16_t aKey,const uint8_t * aValue,uint16_t aValueLength)182 otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
183 {
184     OT_UNUSED_VARIABLE(aInstance);
185 
186     otError error = OT_ERROR_NONE;
187 
188 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
189     if (isSensitiveKey(aKey))
190     {
191         error = otPosixSecureSettingsAdd(aInstance, aKey, aValue, aValueLength);
192     }
193     else
194 #endif
195     {
196         sSettingsFile.Add(aKey, aValue, aValueLength);
197     }
198 
199     return error;
200 }
201 
otPlatSettingsDelete(otInstance * aInstance,uint16_t aKey,int aIndex)202 otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
203 {
204     OT_UNUSED_VARIABLE(aInstance);
205 
206     otError error;
207 
208 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
209     if (isSensitiveKey(aKey))
210     {
211         error = otPosixSecureSettingsDelete(aInstance, aKey, aIndex);
212     }
213     else
214 #endif
215     {
216         error = sSettingsFile.Delete(aKey, aIndex);
217     }
218 
219     return error;
220 }
221 
otPlatSettingsWipe(otInstance * aInstance)222 void otPlatSettingsWipe(otInstance *aInstance)
223 {
224     OT_UNUSED_VARIABLE(aInstance);
225 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
226     otPosixSecureSettingsWipe(aInstance);
227 #endif
228 
229     sSettingsFile.Wipe();
230 }
231 
232 namespace ot {
233 namespace Posix {
234 #if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
PlatformSettingsGetSensitiveKeys(otInstance * aInstance,const uint16_t ** aKeys,uint16_t * aKeysLength)235 void PlatformSettingsGetSensitiveKeys(otInstance *aInstance, const uint16_t **aKeys, uint16_t *aKeysLength)
236 {
237     OT_UNUSED_VARIABLE(aInstance);
238 
239     assert(aKeys != nullptr);
240     assert(aKeysLength != nullptr);
241 
242     *aKeys       = sSensitiveKeys;
243     *aKeysLength = sSensitiveKeysLength;
244 }
245 #endif
246 
247 } // namespace Posix
248 } // namespace ot
249 
250 #ifndef SELF_TEST
251 #define SELF_TEST 0
252 #endif
253 
254 #if SELF_TEST
255 
otLogCritPlat(const char * aFormat,...)256 void otLogCritPlat(const char *aFormat, ...) { OT_UNUSED_VARIABLE(aFormat); }
257 
otExitCodeToString(uint8_t aExitCode)258 const char *otExitCodeToString(uint8_t aExitCode)
259 {
260     OT_UNUSED_VARIABLE(aExitCode);
261     return "";
262 }
263 
otPlatRadioGetIeeeEui64(otInstance * aInstance,uint8_t * aIeeeEui64)264 void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
265 {
266     OT_UNUSED_VARIABLE(aInstance);
267 
268     memset(aIeeeEui64, 0, sizeof(uint64_t));
269 }
270 
271 // Stub implementation for testing
IsSystemDryRun(void)272 bool IsSystemDryRun(void) { return false; }
273 
main()274 int main()
275 {
276     otInstance *instance = nullptr;
277     uint8_t     data[60];
278 
279     for (uint8_t i = 0; i < sizeof(data); ++i)
280     {
281         data[i] = i;
282     }
283 
284     otPlatSettingsInit(instance, nullptr, 0);
285 
286     // verify empty situation
287     otPlatSettingsWipe(instance);
288     {
289         uint8_t  value[sizeof(data)];
290         uint16_t length = sizeof(value);
291 
292         assert(otPlatSettingsGet(instance, 0, 0, value, &length) == OT_ERROR_NOT_FOUND);
293         assert(otPlatSettingsDelete(instance, 0, 0) == OT_ERROR_NOT_FOUND);
294         assert(otPlatSettingsDelete(instance, 0, -1) == OT_ERROR_NOT_FOUND);
295     }
296 
297     // verify write one record
298     assert(otPlatSettingsSet(instance, 0, data, sizeof(data) / 2) == OT_ERROR_NONE);
299     {
300         uint8_t  value[sizeof(data)];
301         uint16_t length = sizeof(value);
302 
303         assert(otPlatSettingsGet(instance, 0, 0, nullptr, nullptr) == OT_ERROR_NONE);
304         assert(otPlatSettingsGet(instance, 0, 0, nullptr, &length) == OT_ERROR_NONE);
305         assert(length == sizeof(data) / 2);
306 
307         length = sizeof(value);
308         assert(otPlatSettingsGet(instance, 0, 0, value, &length) == OT_ERROR_NONE);
309         assert(length == sizeof(data) / 2);
310         assert(0 == memcmp(value, data, length));
311 
312         // insufficient buffer
313         length -= 1;
314         value[length] = 0;
315         assert(otPlatSettingsGet(instance, 0, 0, value, &length) == OT_ERROR_NONE);
316         // verify length becomes the actual length of the record
317         assert(length == sizeof(data) / 2);
318         // verify this byte is not changed
319         assert(value[length] == 0);
320 
321         // wrong index
322         assert(otPlatSettingsGet(instance, 0, 1, nullptr, nullptr) == OT_ERROR_NOT_FOUND);
323         // wrong key
324         assert(otPlatSettingsGet(instance, 1, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND);
325     }
326     otPlatSettingsWipe(instance);
327 
328     // verify write two records
329     assert(otPlatSettingsSet(instance, 0, data, sizeof(data)) == OT_ERROR_NONE);
330     assert(otPlatSettingsAdd(instance, 0, data, sizeof(data) / 2) == OT_ERROR_NONE);
331     {
332         uint8_t  value[sizeof(data)];
333         uint16_t length = sizeof(value);
334 
335         assert(otPlatSettingsGet(instance, 0, 1, value, &length) == OT_ERROR_NONE);
336         assert(length == sizeof(data) / 2);
337         assert(0 == memcmp(value, data, length));
338 
339         length = sizeof(value);
340         assert(otPlatSettingsGet(instance, 0, 0, value, &length) == OT_ERROR_NONE);
341         assert(length == sizeof(data));
342         assert(0 == memcmp(value, data, length));
343     }
344     otPlatSettingsWipe(instance);
345 
346     // verify write two records of different keys
347     assert(otPlatSettingsSet(instance, 0, data, sizeof(data)) == OT_ERROR_NONE);
348     assert(otPlatSettingsAdd(instance, 1, data, sizeof(data) / 2) == OT_ERROR_NONE);
349     {
350         uint8_t  value[sizeof(data)];
351         uint16_t length = sizeof(value);
352 
353         assert(otPlatSettingsGet(instance, 1, 0, value, &length) == OT_ERROR_NONE);
354         assert(length == sizeof(data) / 2);
355         assert(0 == memcmp(value, data, length));
356 
357         length = sizeof(value);
358         assert(otPlatSettingsGet(instance, 0, 0, value, &length) == OT_ERROR_NONE);
359         assert(length == sizeof(data));
360         assert(0 == memcmp(value, data, length));
361     }
362     otPlatSettingsWipe(instance);
363 
364     // verify delete record
365     assert(otPlatSettingsAdd(instance, 0, data, sizeof(data)) == OT_ERROR_NONE);
366     assert(otPlatSettingsAdd(instance, 0, data, sizeof(data) / 2) == OT_ERROR_NONE);
367     assert(otPlatSettingsAdd(instance, 0, data, sizeof(data) / 3) == OT_ERROR_NONE);
368     {
369         uint8_t  value[sizeof(data)];
370         uint16_t length = sizeof(value);
371 
372         // wrong key
373         assert(otPlatSettingsDelete(instance, 1, 0) == OT_ERROR_NOT_FOUND);
374         assert(otPlatSettingsDelete(instance, 1, -1) == OT_ERROR_NOT_FOUND);
375 
376         // wrong index
377         assert(otPlatSettingsDelete(instance, 0, 3) == OT_ERROR_NOT_FOUND);
378 
379         // delete one record
380         assert(otPlatSettingsDelete(instance, 0, 1) == OT_ERROR_NONE);
381         assert(otPlatSettingsGet(instance, 0, 1, value, &length) == OT_ERROR_NONE);
382         assert(length == sizeof(data) / 3);
383         assert(0 == memcmp(value, data, length));
384 
385         // delete all records
386         assert(otPlatSettingsDelete(instance, 0, -1) == OT_ERROR_NONE);
387         assert(otPlatSettingsGet(instance, 0, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND);
388     }
389     otPlatSettingsWipe(instance);
390 
391     // verify delete all records of a type
392     assert(otPlatSettingsAdd(instance, 0, data, sizeof(data)) == OT_ERROR_NONE);
393     assert(otPlatSettingsAdd(instance, 1, data, sizeof(data) / 2) == OT_ERROR_NONE);
394     assert(otPlatSettingsAdd(instance, 0, data, sizeof(data) / 3) == OT_ERROR_NONE);
395     {
396         uint8_t  value[sizeof(data)];
397         uint16_t length = sizeof(value);
398 
399         assert(otPlatSettingsDelete(instance, 0, -1) == OT_ERROR_NONE);
400         assert(otPlatSettingsGet(instance, 0, 0, value, &length) == OT_ERROR_NOT_FOUND);
401         assert(otPlatSettingsGet(instance, 1, 0, value, &length) == OT_ERROR_NONE);
402         assert(length == sizeof(data) / 2);
403         assert(0 == memcmp(value, data, length));
404 
405         assert(otPlatSettingsDelete(instance, 0, 0) == OT_ERROR_NOT_FOUND);
406         assert(otPlatSettingsGet(instance, 0, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND);
407     }
408     otPlatSettingsWipe(instance);
409     otPlatSettingsDeinit(instance);
410 
411     return 0;
412 }
413 #endif
414