Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2022 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : * All rights reserved.
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : /**
21 : * @file
22 : * This file implements an object for reading Abstract Syntax
23 : * Notation One (ASN.1) encoded data.
24 : *
25 : */
26 :
27 : #include <ctype.h>
28 : #include <stdint.h>
29 : #include <stdio.h>
30 : #include <stdlib.h>
31 :
32 : #include <lib/asn1/ASN1.h>
33 : #include <lib/core/CHIPEncoding.h>
34 : #include <lib/support/SafeInt.h>
35 :
36 : namespace chip {
37 : namespace ASN1 {
38 :
39 : using namespace chip::Encoding;
40 :
41 546 : void ASN1Reader::Init(const uint8_t * buf, size_t len)
42 : {
43 546 : ResetElementState();
44 546 : mBuf = buf;
45 546 : mBufEnd = buf + len;
46 546 : mElemStart = buf;
47 546 : mContainerEnd = mBufEnd;
48 546 : mNumSavedContexts = 0;
49 546 : }
50 :
51 24240 : CHIP_ERROR ASN1Reader::Next()
52 : {
53 24240 : VerifyOrReturnError(!EndOfContents, ASN1_END);
54 24240 : VerifyOrReturnError(!IndefiniteLen, ASN1_ERROR_UNSUPPORTED_ENCODING);
55 :
56 : // Note: avoid using addition assignment operator (+=), which may result in integer overflow
57 : // in the right hand side of an assignment (mHeadLen + ValueLen).
58 24240 : mElemStart = mElemStart + mHeadLen + ValueLen;
59 :
60 24240 : ResetElementState();
61 :
62 24240 : VerifyOrReturnError(mElemStart != mContainerEnd, ASN1_END);
63 :
64 15257 : return DecodeHead();
65 : }
66 :
67 6881 : CHIP_ERROR ASN1Reader::EnterConstructedType()
68 : {
69 6881 : VerifyOrReturnError(Constructed, ASN1_ERROR_INVALID_STATE);
70 :
71 6881 : return EnterContainer(0);
72 : }
73 :
74 6614 : CHIP_ERROR ASN1Reader::ExitConstructedType()
75 : {
76 6614 : return ExitContainer();
77 : }
78 :
79 682 : CHIP_ERROR ASN1Reader::GetConstructedType(const uint8_t *& val, uint32_t & valLen)
80 : {
81 682 : VerifyOrReturnError(Constructed, ASN1_ERROR_INVALID_STATE);
82 :
83 682 : val = mElemStart;
84 682 : valLen = mHeadLen + ValueLen;
85 :
86 682 : return CHIP_NO_ERROR;
87 : }
88 824 : CHIP_ERROR ASN1Reader::EnterEncapsulatedType()
89 : {
90 824 : VerifyOrReturnError(Class == kASN1TagClass_Universal &&
91 : (Tag == kASN1UniversalTag_OctetString || Tag == kASN1UniversalTag_BitString),
92 : ASN1_ERROR_INVALID_STATE);
93 :
94 824 : VerifyOrReturnError(!Constructed, ASN1_ERROR_UNSUPPORTED_ENCODING);
95 :
96 824 : return EnterContainer((Tag == kASN1UniversalTag_BitString) ? 1 : 0);
97 : }
98 :
99 801 : CHIP_ERROR ASN1Reader::ExitEncapsulatedType()
100 : {
101 801 : return ExitContainer();
102 : }
103 :
104 7705 : CHIP_ERROR ASN1Reader::EnterContainer(uint32_t offset)
105 : {
106 7705 : VerifyOrReturnError(mNumSavedContexts != kMaxContextDepth, ASN1_ERROR_MAX_DEPTH_EXCEEDED);
107 :
108 7705 : mSavedContexts[mNumSavedContexts].ElemStart = mElemStart;
109 7705 : mSavedContexts[mNumSavedContexts].HeadLen = mHeadLen;
110 7705 : mSavedContexts[mNumSavedContexts].ValueLen = ValueLen;
111 7705 : mSavedContexts[mNumSavedContexts].IndefiniteLen = IndefiniteLen;
112 7705 : mSavedContexts[mNumSavedContexts].ContainerEnd = mContainerEnd;
113 7705 : mNumSavedContexts++;
114 :
115 7705 : mElemStart = Value + offset;
116 7705 : if (!IndefiniteLen)
117 : {
118 7705 : VerifyOrReturnError(CanCastTo<uint32_t>(mBufEnd - Value), ASN1_ERROR_VALUE_OVERFLOW);
119 7705 : VerifyOrReturnError(static_cast<uint32_t>(mBufEnd - Value) >= ValueLen, ASN1_ERROR_VALUE_OVERFLOW);
120 7705 : mContainerEnd = Value + ValueLen;
121 : }
122 :
123 7705 : ResetElementState();
124 :
125 7705 : return CHIP_NO_ERROR;
126 : }
127 :
128 7415 : CHIP_ERROR ASN1Reader::ExitContainer()
129 : {
130 7415 : VerifyOrReturnError(mNumSavedContexts != 0, ASN1_ERROR_INVALID_STATE);
131 :
132 7415 : ASN1ParseContext & prevContext = mSavedContexts[--mNumSavedContexts];
133 :
134 7415 : VerifyOrReturnError(!prevContext.IndefiniteLen, ASN1_ERROR_UNSUPPORTED_ENCODING);
135 :
136 7415 : mElemStart = prevContext.ElemStart + prevContext.HeadLen + prevContext.ValueLen;
137 :
138 7415 : mContainerEnd = prevContext.ContainerEnd;
139 :
140 7415 : ResetElementState();
141 :
142 7415 : return CHIP_NO_ERROR;
143 : }
144 :
145 0 : bool ASN1Reader::IsContained() const
146 : {
147 0 : return mNumSavedContexts > 0;
148 : }
149 :
150 574 : CHIP_ERROR ASN1Reader::GetInteger(int64_t & val)
151 : {
152 574 : uint8_t encodedVal[sizeof(int64_t)] = { 0 };
153 574 : size_t valPaddingLen = sizeof(int64_t) - ValueLen;
154 :
155 574 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
156 574 : VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
157 574 : VerifyOrReturnError(ValueLen <= sizeof(int64_t), ASN1_ERROR_VALUE_OVERFLOW);
158 574 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
159 :
160 574 : if ((*Value & 0x80) == 0x80)
161 : {
162 19 : for (size_t i = 0; i < valPaddingLen; i++)
163 : {
164 15 : encodedVal[i] = 0xFF;
165 : }
166 : }
167 574 : memcpy(&encodedVal[valPaddingLen], Value, ValueLen);
168 :
169 574 : val = static_cast<int64_t>(BigEndian::Get64(encodedVal));
170 :
171 574 : return CHIP_NO_ERROR;
172 : }
173 :
174 468 : CHIP_ERROR ASN1Reader::GetBoolean(bool & val)
175 : {
176 468 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
177 468 : VerifyOrReturnError(ValueLen == 1, ASN1_ERROR_INVALID_ENCODING);
178 468 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
179 468 : VerifyOrReturnError(Value[0] == 0 || Value[0] == 0xFF, ASN1_ERROR_INVALID_ENCODING);
180 :
181 468 : val = (Value[0] != 0);
182 :
183 468 : return CHIP_NO_ERROR;
184 : }
185 :
186 331 : CHIP_ERROR ASN1Reader::GetUTCTime(ASN1UniversalTime & outTime)
187 : {
188 : // Supported Encoding: YYMMDDHHMMSSZ
189 331 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
190 331 : VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
191 331 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
192 331 : VerifyOrReturnError(ValueLen == 13 && Value[12] == 'Z', ASN1_ERROR_UNSUPPORTED_ENCODING);
193 :
194 331 : return outTime.ImportFrom_ASN1_TIME_string(CharSpan(reinterpret_cast<const char *>(Value), ValueLen));
195 : }
196 :
197 22 : CHIP_ERROR ASN1Reader::GetGeneralizedTime(ASN1UniversalTime & outTime)
198 : {
199 : // Supported Encoding: YYYYMMDDHHMMSSZ
200 22 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
201 22 : VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
202 22 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
203 22 : VerifyOrReturnError(ValueLen == 15 && Value[14] == 'Z', ASN1_ERROR_UNSUPPORTED_ENCODING);
204 :
205 22 : return outTime.ImportFrom_ASN1_TIME_string(CharSpan(reinterpret_cast<const char *>(Value), ValueLen));
206 : }
207 :
208 157 : static uint8_t ReverseBits(uint8_t v)
209 : {
210 : // swap adjacent bits
211 157 : v = static_cast<uint8_t>(static_cast<uint8_t>((v >> 1) & 0x55) | static_cast<uint8_t>((v & 0x55) << 1));
212 : // swap adjacent bit pairs
213 157 : v = static_cast<uint8_t>(static_cast<uint8_t>((v >> 2) & 0x33) | static_cast<uint8_t>((v & 0x33) << 2));
214 : // swap nibbles
215 157 : v = static_cast<uint8_t>(static_cast<uint8_t>(v >> 4) | static_cast<uint8_t>(v << 4));
216 157 : return v;
217 : }
218 :
219 155 : CHIP_ERROR ASN1Reader::GetBitString(uint32_t & outVal)
220 : {
221 : // NOTE: only supports DER encoding.
222 155 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
223 155 : VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
224 155 : VerifyOrReturnError(ValueLen <= 5, ASN1_ERROR_UNSUPPORTED_ENCODING);
225 155 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
226 :
227 155 : if (ValueLen == 1)
228 : {
229 1 : outVal = 0;
230 : }
231 : else
232 : {
233 154 : outVal = ReverseBits(Value[1]);
234 154 : int shift = 8;
235 157 : for (uint32_t i = 2; i < ValueLen; i++, shift += 8)
236 : {
237 3 : outVal |= static_cast<uint32_t>(ReverseBits(Value[i]) << shift);
238 : }
239 : }
240 :
241 155 : return CHIP_NO_ERROR;
242 : }
243 :
244 15257 : CHIP_ERROR ASN1Reader::DecodeHead()
245 : {
246 15257 : const uint8_t * p = mElemStart;
247 15257 : VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
248 :
249 15257 : Class = *p & 0xC0;
250 15257 : Constructed = (*p & 0x20) != 0;
251 15257 : Tag = *p & 0x1F;
252 :
253 : // Only tags < 31 supported. The implication of this is that encoded tags are exactly 1 byte long.
254 15257 : VerifyOrReturnError(Tag < 0x1F, ASN1_ERROR_UNSUPPORTED_ENCODING);
255 :
256 15251 : p++;
257 15251 : VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
258 :
259 15251 : if ((*p & 0x80) == 0)
260 : {
261 13841 : ValueLen = *p & 0x7F;
262 13841 : IndefiniteLen = false;
263 13841 : p++;
264 : }
265 1410 : else if (*p == 0x80)
266 : {
267 0 : ValueLen = 0;
268 0 : IndefiniteLen = true;
269 0 : p++;
270 : }
271 : else
272 : {
273 1410 : ValueLen = 0;
274 1410 : uint8_t lenLen = *p & 0x7F;
275 1410 : p++;
276 3315 : for (; lenLen > 0; lenLen--, p++)
277 : {
278 1905 : VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
279 1905 : VerifyOrReturnError((ValueLen & 0xFF000000) == 0, ASN1_ERROR_LENGTH_OVERFLOW);
280 1905 : ValueLen = (ValueLen << 8) | *p;
281 : }
282 1410 : IndefiniteLen = false;
283 : }
284 :
285 15251 : VerifyOrReturnError(CanCastTo<uint32_t>(mBufEnd - p), ASN1_ERROR_VALUE_OVERFLOW);
286 15251 : VerifyOrReturnError(static_cast<uint32_t>(mBufEnd - p) >= ValueLen, ASN1_ERROR_VALUE_OVERFLOW);
287 15250 : VerifyOrReturnError(CanCastTo<uint32_t>(p - mElemStart), ASN1_ERROR_VALUE_OVERFLOW);
288 15250 : mHeadLen = static_cast<uint32_t>(p - mElemStart);
289 :
290 15250 : EndOfContents = (Class == kASN1TagClass_Universal && Tag == 0 && !Constructed && ValueLen == 0);
291 :
292 15250 : Value = p;
293 :
294 15250 : return CHIP_NO_ERROR;
295 : }
296 :
297 39906 : void ASN1Reader::ResetElementState()
298 : {
299 39906 : Class = 0;
300 39906 : Tag = 0;
301 39906 : Value = nullptr;
302 39906 : ValueLen = 0;
303 39906 : Constructed = false;
304 39906 : IndefiniteLen = false;
305 39906 : EndOfContents = false;
306 39906 : mHeadLen = 0;
307 39906 : }
308 :
309 0 : CHIP_ERROR DumpASN1(ASN1Reader & asn1Parser, const char * prefix, const char * indent)
310 : {
311 0 : CHIP_ERROR err = CHIP_NO_ERROR;
312 :
313 0 : if (indent == nullptr)
314 0 : indent = " ";
315 :
316 0 : int nestLevel = 0;
317 : while (true)
318 : {
319 0 : err = asn1Parser.Next();
320 0 : if (err != CHIP_NO_ERROR)
321 : {
322 0 : if (err == ASN1_END)
323 : {
324 0 : if (asn1Parser.IsContained())
325 : {
326 0 : err = asn1Parser.ExitConstructedType();
327 0 : if (err != CHIP_NO_ERROR)
328 : {
329 0 : printf("ASN1Reader::ExitConstructedType() failed: %" CHIP_ERROR_FORMAT "\n", err.Format());
330 0 : return err;
331 : }
332 0 : nestLevel--;
333 0 : continue;
334 : }
335 0 : break;
336 : }
337 0 : printf("ASN1Reader::Next() failed: %" CHIP_ERROR_FORMAT "\n", err.Format());
338 0 : return err;
339 : }
340 0 : if (prefix != nullptr)
341 0 : printf("%s", prefix);
342 0 : for (int i = nestLevel; i; i--)
343 0 : printf("%s", indent);
344 0 : if (asn1Parser.IsEndOfContents())
345 0 : printf("END-OF-CONTENTS ");
346 0 : else if (asn1Parser.GetClass() == kASN1TagClass_Universal)
347 0 : switch (asn1Parser.GetTag())
348 : {
349 0 : case kASN1UniversalTag_Boolean:
350 0 : printf("BOOLEAN ");
351 0 : break;
352 0 : case kASN1UniversalTag_Integer:
353 0 : printf("INTEGER ");
354 0 : break;
355 0 : case kASN1UniversalTag_BitString:
356 0 : printf("BIT STRING ");
357 0 : break;
358 0 : case kASN1UniversalTag_OctetString:
359 0 : printf("OCTET STRING ");
360 0 : break;
361 0 : case kASN1UniversalTag_Null:
362 0 : printf("NULL ");
363 0 : break;
364 0 : case kASN1UniversalTag_ObjectId:
365 0 : printf("OBJECT IDENTIFIER ");
366 0 : break;
367 0 : case kASN1UniversalTag_ObjectDesc:
368 0 : printf("OBJECT DESCRIPTOR ");
369 0 : break;
370 0 : case kASN1UniversalTag_External:
371 0 : printf("EXTERNAL ");
372 0 : break;
373 0 : case kASN1UniversalTag_Real:
374 0 : printf("REAL ");
375 0 : break;
376 0 : case kASN1UniversalTag_Enumerated:
377 0 : printf("ENUMERATED ");
378 0 : break;
379 0 : case kASN1UniversalTag_Sequence:
380 0 : printf("SEQUENCE ");
381 0 : break;
382 0 : case kASN1UniversalTag_Set:
383 0 : printf("SET ");
384 0 : break;
385 0 : case kASN1UniversalTag_UTF8String:
386 : case kASN1UniversalTag_NumericString:
387 : case kASN1UniversalTag_PrintableString:
388 : case kASN1UniversalTag_T61String:
389 : case kASN1UniversalTag_VideotexString:
390 : case kASN1UniversalTag_IA5String:
391 : case kASN1UniversalTag_GraphicString:
392 : case kASN1UniversalTag_VisibleString:
393 : case kASN1UniversalTag_GeneralString:
394 : case kASN1UniversalTag_UniversalString:
395 0 : printf("STRING ");
396 0 : break;
397 0 : case kASN1UniversalTag_UTCTime:
398 : case kASN1UniversalTag_GeneralizedTime:
399 0 : printf("TIME ");
400 0 : break;
401 0 : default:
402 0 : printf("[UNIVERSAL %lu] ", static_cast<unsigned long>(asn1Parser.GetTag()));
403 0 : break;
404 : }
405 0 : else if (asn1Parser.GetClass() == kASN1TagClass_Application)
406 0 : printf("[APPLICATION %lu] ", static_cast<unsigned long>(asn1Parser.GetTag()));
407 0 : else if (asn1Parser.GetClass() == kASN1TagClass_ContextSpecific)
408 0 : printf("[%lu] ", static_cast<unsigned long>(asn1Parser.GetTag()));
409 0 : else if (asn1Parser.GetClass() == kASN1TagClass_Private)
410 0 : printf("[PRIVATE %lu] ", static_cast<unsigned long>(asn1Parser.GetTag()));
411 :
412 0 : if (asn1Parser.IsConstructed())
413 0 : printf("(constructed) ");
414 :
415 0 : if (asn1Parser.IsIndefiniteLen())
416 0 : printf("Length = indefinite\n");
417 : else
418 0 : printf("Length = %ld\n", static_cast<long>(asn1Parser.GetValueLen()));
419 :
420 0 : if (asn1Parser.IsConstructed())
421 : {
422 0 : err = asn1Parser.EnterConstructedType();
423 0 : if (err != CHIP_NO_ERROR)
424 : {
425 0 : printf("ASN1Reader::EnterConstructedType() failed: %" CHIP_ERROR_FORMAT "\n", err.Format());
426 0 : return err;
427 : }
428 0 : nestLevel++;
429 : }
430 0 : }
431 :
432 0 : return err;
433 : }
434 :
435 : } // namespace ASN1
436 : } // namespace chip
|