1 /*
2  *    Copyright (c) 2017, 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" AND
17  *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20  *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /**
29  * @file
30  *   This file implements a spinel decoder.
31  */
32 
33 #include "spinel_decoder.hpp"
34 
35 #include "common/code_utils.hpp"
36 #include "common/string.hpp"
37 
38 namespace ot {
39 namespace Spinel {
40 
Decoder(void)41 Decoder::Decoder(void)
42     : mFrame(nullptr)
43     , mLength(0)
44     , mIndex(0)
45     , mEnd(0)
46     , mNumOpenStructs(0)
47     , mSavedNumOpenStructs(0)
48     , mSavedIndex(0)
49     , mSavedEnd(0)
50 {
51 }
52 
Init(const uint8_t * aFrame,uint16_t aLength)53 void Decoder::Init(const uint8_t *aFrame, uint16_t aLength)
54 {
55     mFrame  = aFrame;
56     mLength = (mFrame != nullptr) ? aLength : 0;
57 
58     Reset();
59     ClearSavedPosition();
60 }
61 
Reset(void)62 void Decoder::Reset(void)
63 {
64     mIndex          = 0;
65     mEnd            = mLength;
66     mNumOpenStructs = 0;
67     ClearSavedPosition();
68 }
69 
ReadBool(bool & aBool)70 otError Decoder::ReadBool(bool &aBool)
71 {
72     otError error = OT_ERROR_NONE;
73     uint8_t byte;
74 
75     SuccessOrExit(error = ReadUint8(byte));
76 
77     // Boolean value are encoded in 8-bits as either 0x00 or 0x01. All other values are illegal.
78     if (byte == 0x00)
79     {
80         aBool = false;
81     }
82     else if (byte == 0x01)
83     {
84         aBool = true;
85     }
86     else
87     {
88         error = OT_ERROR_PARSE;
89     }
90 
91 exit:
92     return error;
93 }
94 
ReadUint8(uint8_t & aUint8)95 otError Decoder::ReadUint8(uint8_t &aUint8)
96 {
97     otError error = OT_ERROR_NONE;
98 
99     VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
100     aUint8 = mFrame[mIndex];
101     mIndex += sizeof(uint8_t);
102 
103 exit:
104     return error;
105 }
106 
ReadInt8(int8_t & aInt8)107 otError Decoder::ReadInt8(int8_t &aInt8)
108 {
109     otError error = OT_ERROR_NONE;
110     uint8_t byte;
111 
112     SuccessOrExit(error = ReadUint8(byte));
113     aInt8 = static_cast<int8_t>(byte);
114 
115 exit:
116     return error;
117 }
118 
ReadUint16(uint16_t & aUint16)119 otError Decoder::ReadUint16(uint16_t &aUint16)
120 {
121     otError error = OT_ERROR_NONE;
122 
123     VerifyOrExit(mIndex + sizeof(uint16_t) <= mEnd, error = OT_ERROR_PARSE);
124 
125     aUint16 = static_cast<uint16_t>(mFrame[mIndex] | (mFrame[mIndex + 1] << 8));
126 
127     mIndex += sizeof(uint16_t);
128 
129 exit:
130     return error;
131 }
132 
ReadInt16(int16_t & aInt16)133 otError Decoder::ReadInt16(int16_t &aInt16)
134 {
135     otError  error = OT_ERROR_NONE;
136     uint16_t u16;
137 
138     SuccessOrExit(error = ReadUint16(u16));
139     aInt16 = static_cast<int16_t>(u16);
140 
141 exit:
142     return error;
143 }
144 
ReadUint32(uint32_t & aUint32)145 otError Decoder::ReadUint32(uint32_t &aUint32)
146 {
147     otError error = OT_ERROR_NONE;
148 
149     VerifyOrExit(mIndex + sizeof(uint32_t) <= mEnd, error = OT_ERROR_PARSE);
150 
151     aUint32 = ((static_cast<uint32_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint32_t>(mFrame[mIndex + 1]) << 8) |
152                (static_cast<uint32_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint32_t>(mFrame[mIndex + 3]) << 24));
153 
154     mIndex += sizeof(uint32_t);
155 
156 exit:
157     return error;
158 }
159 
ReadInt32(int32_t & aInt32)160 otError Decoder::ReadInt32(int32_t &aInt32)
161 {
162     otError  error = OT_ERROR_NONE;
163     uint32_t u32;
164 
165     SuccessOrExit(error = ReadUint32(u32));
166     aInt32 = static_cast<int32_t>(u32);
167 
168 exit:
169     return error;
170 }
171 
ReadUint64(uint64_t & aUint64)172 otError Decoder::ReadUint64(uint64_t &aUint64)
173 {
174     otError error = OT_ERROR_NONE;
175 
176     VerifyOrExit(mIndex + sizeof(uint64_t) <= mEnd, error = OT_ERROR_PARSE);
177 
178     aUint64 = ((static_cast<uint64_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint64_t>(mFrame[mIndex + 1]) << 8) |
179                (static_cast<uint64_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint64_t>(mFrame[mIndex + 3]) << 24) |
180                (static_cast<uint64_t>(mFrame[mIndex + 4]) << 32) | (static_cast<uint64_t>(mFrame[mIndex + 5]) << 40) |
181                (static_cast<uint64_t>(mFrame[mIndex + 6]) << 48) | (static_cast<uint64_t>(mFrame[mIndex + 7]) << 56));
182 
183     mIndex += sizeof(uint64_t);
184 
185 exit:
186     return error;
187 }
188 
ReadInt64(int64_t & aInt64)189 otError Decoder::ReadInt64(int64_t &aInt64)
190 {
191     otError  error = OT_ERROR_NONE;
192     uint64_t u64;
193 
194     SuccessOrExit(error = ReadUint64(u64));
195     aInt64 = static_cast<int64_t>(u64);
196 
197 exit:
198     return error;
199 }
200 
ReadUintPacked(unsigned int & aUint)201 otError Decoder::ReadUintPacked(unsigned int &aUint)
202 {
203     otError        error = OT_ERROR_NONE;
204     spinel_ssize_t parsedLen;
205     unsigned int   uint;
206 
207     parsedLen = spinel_packed_uint_decode(&mFrame[mIndex], mEnd - mIndex, &uint);
208     VerifyOrExit(parsedLen > 0, error = OT_ERROR_PARSE);
209 
210     mIndex += parsedLen;
211     aUint = uint;
212 
213 exit:
214     return error;
215 }
216 
217 // Reads an item of given size and updates the pointer `aPtr`.
ReadItem(const uint8_t ** aPtr,uint16_t aSize)218 otError Decoder::ReadItem(const uint8_t **aPtr, uint16_t aSize)
219 {
220     otError error = OT_ERROR_NONE;
221 
222     VerifyOrExit(mIndex + aSize <= mEnd, error = OT_ERROR_PARSE);
223 
224     *aPtr = &mFrame[mIndex];
225 
226     mIndex += aSize;
227 
228 exit:
229     return error;
230 }
231 
ReadIp6Address(spinel_ipv6addr_t & aIp6Addr)232 otError Decoder::ReadIp6Address(spinel_ipv6addr_t &aIp6Addr)
233 {
234     otError                  error = OT_ERROR_NONE;
235     const spinel_ipv6addr_t *ipv6AddrPtr;
236 
237     SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
238     aIp6Addr = *ipv6AddrPtr;
239 
240 exit:
241     return error;
242 }
243 
ReadIp6Address(otIp6Address & aIp6Addr)244 otError Decoder::ReadIp6Address(otIp6Address &aIp6Addr)
245 {
246     otError             error = OT_ERROR_NONE;
247     const otIp6Address *ipv6AddrPtr;
248 
249     SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
250     aIp6Addr = *ipv6AddrPtr;
251 
252 exit:
253     return error;
254 }
255 
ReadEui64(spinel_eui64_t & aEui64)256 otError Decoder::ReadEui64(spinel_eui64_t &aEui64)
257 {
258     otError               error = OT_ERROR_NONE;
259     const spinel_eui64_t *eui64Ptr;
260 
261     SuccessOrExit(error = ReadEui64(eui64Ptr));
262     aEui64 = *eui64Ptr;
263 
264 exit:
265     return error;
266 }
267 
ReadEui64(otExtAddress & aEui64)268 otError Decoder::ReadEui64(otExtAddress &aEui64)
269 {
270     otError             error = OT_ERROR_NONE;
271     const otExtAddress *eui64Ptr;
272 
273     SuccessOrExit(error = ReadEui64(eui64Ptr));
274     aEui64 = *eui64Ptr;
275 
276 exit:
277     return error;
278 }
279 
ReadEui48(spinel_eui48_t & aEui48)280 otError Decoder::ReadEui48(spinel_eui48_t &aEui48)
281 {
282     otError               error = OT_ERROR_NONE;
283     const spinel_eui48_t *eui48Ptr;
284 
285     SuccessOrExit(error = ReadEui48(eui48Ptr));
286     aEui48 = *eui48Ptr;
287 
288 exit:
289     return error;
290 }
291 
ReadUtf8(const char * & aUtf8)292 otError Decoder::ReadUtf8(const char *&aUtf8)
293 {
294     otError error = OT_ERROR_NONE;
295     size_t  len;
296 
297     // Ensure there is at least one byte (for null character).
298     VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
299 
300     len = StringLength(reinterpret_cast<const char *>(&mFrame[mIndex]), mEnd - mIndex);
301     VerifyOrExit(len < static_cast<uint16_t>(mEnd - mIndex), error = OT_ERROR_PARSE);
302 
303     aUtf8 = reinterpret_cast<const char *>(&mFrame[mIndex]);
304 
305     // `sizeof(uint8_t)` is added for the terminating null character.
306     mIndex += static_cast<uint16_t>(len + sizeof(uint8_t));
307 
308 exit:
309     return error;
310 }
311 
ReadData(const uint8_t * & aData,uint16_t & aDataLen)312 otError Decoder::ReadData(const uint8_t *&aData, uint16_t &aDataLen)
313 {
314     aDataLen = mEnd - mIndex;
315 
316     return ReadItem(&aData, aDataLen);
317 }
318 
ReadDataWithLen(const uint8_t * & aData,uint16_t & aDataLen)319 otError Decoder::ReadDataWithLen(const uint8_t *&aData, uint16_t &aDataLen)
320 {
321     otError  error = OT_ERROR_NONE;
322     uint16_t len;
323 
324     SuccessOrExit(error = ReadUint16(len));
325     SuccessOrExit(error = ReadItem(&aData, len));
326     aDataLen = len;
327 
328 exit:
329     return error;
330 }
331 
OpenStruct(void)332 otError Decoder::OpenStruct(void)
333 {
334     otError  error = OT_ERROR_NONE;
335     uint16_t structLen;
336 
337     VerifyOrExit(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);
338 
339     SuccessOrExit(error = ReadUint16(structLen));
340     VerifyOrExit(structLen <= mEnd - mIndex, error = OT_ERROR_PARSE);
341 
342     mPrevEnd[mNumOpenStructs] = mEnd;
343     mEnd                      = (mIndex + structLen);
344     mNumOpenStructs++;
345 
346 exit:
347     return error;
348 }
349 
CloseStruct(void)350 otError Decoder::CloseStruct(void)
351 {
352     otError error = OT_ERROR_NONE;
353 
354     VerifyOrExit(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);
355 
356     // If there is a saved position and it is contained
357     // within the current struct being closed, the saved
358     // position is cleared to ensure user cannot go back
359     // to middle of an already closed struct.
360 
361     if (IsSavedPositionValid() && (mNumOpenStructs == mSavedNumOpenStructs))
362     {
363         ClearSavedPosition();
364     }
365 
366     mNumOpenStructs--;
367     mIndex = mEnd;
368     mEnd   = mPrevEnd[mNumOpenStructs];
369 
370 exit:
371     return error;
372 }
373 
SavePosition(void)374 void Decoder::SavePosition(void)
375 {
376     mSavedIndex          = mIndex;
377     mSavedEnd            = mEnd;
378     mSavedNumOpenStructs = mNumOpenStructs;
379 }
380 
ResetToSaved(void)381 otError Decoder::ResetToSaved(void)
382 {
383     otError error = OT_ERROR_NONE;
384 
385     VerifyOrExit(IsSavedPositionValid(), error = OT_ERROR_INVALID_STATE);
386 
387     mIndex          = mSavedIndex;
388     mEnd            = mSavedEnd;
389     mNumOpenStructs = mSavedNumOpenStructs;
390 
391 exit:
392     return error;
393 }
394 
395 } // namespace Spinel
396 } // namespace ot
397