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 433 : void ASN1Reader::Init(const uint8_t * buf, size_t len)
42 : {
43 433 : ResetElementState();
44 433 : mBuf = buf;
45 433 : mBufEnd = buf + len;
46 433 : mElemStart = buf;
47 433 : mContainerEnd = mBufEnd;
48 433 : mNumSavedContexts = 0;
49 433 : }
50 :
51 20013 : CHIP_ERROR ASN1Reader::Next()
52 : {
53 20013 : VerifyOrReturnError(!EndOfContents, ASN1_END);
54 20013 : 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 20013 : mElemStart = mElemStart + mHeadLen + ValueLen;
59 :
60 20013 : ResetElementState();
61 :
62 20013 : VerifyOrReturnError(mElemStart != mContainerEnd, ASN1_END);
63 :
64 12526 : return DecodeHead();
65 : }
66 :
67 5682 : CHIP_ERROR ASN1Reader::EnterConstructedType()
68 : {
69 5682 : VerifyOrReturnError(Constructed, ASN1_ERROR_INVALID_STATE);
70 :
71 5682 : return EnterContainer(0);
72 : }
73 :
74 5432 : CHIP_ERROR ASN1Reader::ExitConstructedType()
75 : {
76 5432 : return ExitContainer();
77 : }
78 :
79 593 : CHIP_ERROR ASN1Reader::GetConstructedType(const uint8_t *& val, uint32_t & valLen)
80 : {
81 593 : VerifyOrReturnError(Constructed, ASN1_ERROR_INVALID_STATE);
82 :
83 593 : val = mElemStart;
84 593 : valLen = mHeadLen + ValueLen;
85 :
86 593 : return CHIP_NO_ERROR;
87 : }
88 715 : CHIP_ERROR ASN1Reader::EnterEncapsulatedType()
89 : {
90 715 : VerifyOrReturnError(Class == kASN1TagClass_Universal &&
91 : (Tag == kASN1UniversalTag_OctetString || Tag == kASN1UniversalTag_BitString),
92 : ASN1_ERROR_INVALID_STATE);
93 :
94 715 : VerifyOrReturnError(!Constructed, ASN1_ERROR_UNSUPPORTED_ENCODING);
95 :
96 715 : return EnterContainer((Tag == kASN1UniversalTag_BitString) ? 1 : 0);
97 : }
98 :
99 692 : CHIP_ERROR ASN1Reader::ExitEncapsulatedType()
100 : {
101 692 : return ExitContainer();
102 : }
103 :
104 6397 : CHIP_ERROR ASN1Reader::EnterContainer(uint32_t offset)
105 : {
106 6397 : VerifyOrReturnError(mNumSavedContexts != kMaxContextDepth, ASN1_ERROR_MAX_DEPTH_EXCEEDED);
107 :
108 6397 : mSavedContexts[mNumSavedContexts].ElemStart = mElemStart;
109 6397 : mSavedContexts[mNumSavedContexts].HeadLen = mHeadLen;
110 6397 : mSavedContexts[mNumSavedContexts].ValueLen = ValueLen;
111 6397 : mSavedContexts[mNumSavedContexts].IndefiniteLen = IndefiniteLen;
112 6397 : mSavedContexts[mNumSavedContexts].ContainerEnd = mContainerEnd;
113 6397 : mNumSavedContexts++;
114 :
115 6397 : mElemStart = Value + offset;
116 6397 : if (!IndefiniteLen)
117 : {
118 6397 : VerifyOrReturnError(CanCastTo<uint32_t>(mBufEnd - Value), ASN1_ERROR_VALUE_OVERFLOW);
119 6397 : VerifyOrReturnError(static_cast<uint32_t>(mBufEnd - Value) >= ValueLen, ASN1_ERROR_VALUE_OVERFLOW);
120 6397 : mContainerEnd = Value + ValueLen;
121 : }
122 :
123 6397 : ResetElementState();
124 :
125 6397 : return CHIP_NO_ERROR;
126 : }
127 :
128 6124 : CHIP_ERROR ASN1Reader::ExitContainer()
129 : {
130 6124 : VerifyOrReturnError(mNumSavedContexts != 0, ASN1_ERROR_INVALID_STATE);
131 :
132 6124 : ASN1ParseContext & prevContext = mSavedContexts[--mNumSavedContexts];
133 :
134 6124 : VerifyOrReturnError(!prevContext.IndefiniteLen, ASN1_ERROR_UNSUPPORTED_ENCODING);
135 :
136 6124 : mElemStart = prevContext.ElemStart + prevContext.HeadLen + prevContext.ValueLen;
137 :
138 6124 : mContainerEnd = prevContext.ContainerEnd;
139 :
140 6124 : ResetElementState();
141 :
142 6124 : return CHIP_NO_ERROR;
143 : }
144 :
145 0 : bool ASN1Reader::IsContained() const
146 : {
147 0 : return mNumSavedContexts > 0;
148 : }
149 :
150 460 : CHIP_ERROR ASN1Reader::GetInteger(int64_t & val)
151 : {
152 460 : uint8_t encodedVal[sizeof(int64_t)] = { 0 };
153 460 : size_t valPaddingLen = sizeof(int64_t) - ValueLen;
154 :
155 460 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
156 460 : VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
157 460 : VerifyOrReturnError(ValueLen <= sizeof(int64_t), ASN1_ERROR_VALUE_OVERFLOW);
158 460 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
159 :
160 460 : if ((*Value & 0x80) == 0x80)
161 : {
162 19 : for (size_t i = 0; i < valPaddingLen; i++)
163 : {
164 15 : encodedVal[i] = 0xFF;
165 : }
166 : }
167 460 : memcpy(&encodedVal[valPaddingLen], Value, ValueLen);
168 :
169 460 : val = static_cast<int64_t>(BigEndian::Get64(encodedVal));
170 :
171 460 : return CHIP_NO_ERROR;
172 : }
173 :
174 408 : CHIP_ERROR ASN1Reader::GetBoolean(bool & val)
175 : {
176 408 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
177 408 : VerifyOrReturnError(ValueLen == 1, ASN1_ERROR_INVALID_ENCODING);
178 408 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
179 408 : VerifyOrReturnError(Value[0] == 0 || Value[0] == 0xFF, ASN1_ERROR_INVALID_ENCODING);
180 :
181 408 : val = (Value[0] != 0);
182 :
183 408 : return CHIP_NO_ERROR;
184 : }
185 :
186 309 : CHIP_ERROR ASN1Reader::GetUTCTime(ASN1UniversalTime & outTime)
187 : {
188 : // Supported Encoding: YYMMDDHHMMSSZ
189 309 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
190 309 : VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
191 309 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
192 309 : VerifyOrReturnError(ValueLen == 13 && Value[12] == 'Z', ASN1_ERROR_UNSUPPORTED_ENCODING);
193 :
194 309 : return outTime.ImportFrom_ASN1_TIME_string(CharSpan(reinterpret_cast<const char *>(Value), ValueLen));
195 : }
196 :
197 4 : CHIP_ERROR ASN1Reader::GetGeneralizedTime(ASN1UniversalTime & outTime)
198 : {
199 : // Supported Encoding: YYYYMMDDHHMMSSZ
200 4 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
201 4 : VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
202 4 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
203 4 : VerifyOrReturnError(ValueLen == 15 && Value[14] == 'Z', ASN1_ERROR_UNSUPPORTED_ENCODING);
204 :
205 4 : return outTime.ImportFrom_ASN1_TIME_string(CharSpan(reinterpret_cast<const char *>(Value), ValueLen));
206 : }
207 :
208 137 : static uint8_t ReverseBits(uint8_t v)
209 : {
210 : // swap adjacent bits
211 137 : 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 137 : v = static_cast<uint8_t>(static_cast<uint8_t>((v >> 2) & 0x33) | static_cast<uint8_t>((v & 0x33) << 2));
214 : // swap nibbles
215 137 : v = static_cast<uint8_t>(static_cast<uint8_t>(v >> 4) | static_cast<uint8_t>(v << 4));
216 137 : return v;
217 : }
218 :
219 135 : CHIP_ERROR ASN1Reader::GetBitString(uint32_t & outVal)
220 : {
221 : // NOTE: only supports DER encoding.
222 135 : VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
223 135 : VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
224 135 : VerifyOrReturnError(ValueLen <= 5, ASN1_ERROR_UNSUPPORTED_ENCODING);
225 135 : VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
226 :
227 135 : if (ValueLen == 1)
228 : {
229 1 : outVal = 0;
230 : }
231 : else
232 : {
233 134 : outVal = ReverseBits(Value[1]);
234 134 : int shift = 8;
235 137 : 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 135 : return CHIP_NO_ERROR;
242 : }
243 :
244 12526 : CHIP_ERROR ASN1Reader::DecodeHead()
245 : {
246 12526 : const uint8_t * p = mElemStart;
247 12526 : VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
248 :
249 12526 : Class = *p & 0xC0;
250 12526 : Constructed = (*p & 0x20) != 0;
251 12526 : Tag = *p & 0x1F;
252 :
253 : // Only tags < 31 supported. The implication of this is that encoded tags are exactly 1 byte long.
254 12526 : VerifyOrReturnError(Tag < 0x1F, ASN1_ERROR_UNSUPPORTED_ENCODING);
255 :
256 12520 : p++;
257 12520 : VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
258 :
259 12520 : if ((*p & 0x80) == 0)
260 : {
261 11449 : ValueLen = *p & 0x7F;
262 11449 : IndefiniteLen = false;
263 11449 : p++;
264 : }
265 1071 : else if (*p == 0x80)
266 : {
267 0 : ValueLen = 0;
268 0 : IndefiniteLen = true;
269 0 : p++;
270 : }
271 : else
272 : {
273 1071 : ValueLen = 0;
274 1071 : uint8_t lenLen = *p & 0x7F;
275 1071 : p++;
276 2572 : for (; lenLen > 0; lenLen--, p++)
277 : {
278 1501 : VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
279 1501 : VerifyOrReturnError((ValueLen & 0xFF000000) == 0, ASN1_ERROR_LENGTH_OVERFLOW);
280 1501 : ValueLen = (ValueLen << 8) | *p;
281 : }
282 1071 : IndefiniteLen = false;
283 : }
284 :
285 12520 : VerifyOrReturnError(CanCastTo<uint32_t>(mBufEnd - p), ASN1_ERROR_VALUE_OVERFLOW);
286 12520 : VerifyOrReturnError(static_cast<uint32_t>(mBufEnd - p) >= ValueLen, ASN1_ERROR_VALUE_OVERFLOW);
287 12520 : VerifyOrReturnError(CanCastTo<uint32_t>(p - mElemStart), ASN1_ERROR_VALUE_OVERFLOW);
288 12520 : mHeadLen = static_cast<uint32_t>(p - mElemStart);
289 :
290 12520 : EndOfContents = (Class == kASN1TagClass_Universal && Tag == 0 && !Constructed && ValueLen == 0);
291 :
292 12520 : Value = p;
293 :
294 12520 : return CHIP_NO_ERROR;
295 : }
296 :
297 32967 : void ASN1Reader::ResetElementState()
298 : {
299 32967 : Class = 0;
300 32967 : Tag = 0;
301 32967 : Value = nullptr;
302 32967 : ValueLen = 0;
303 32967 : Constructed = false;
304 32967 : IndefiniteLen = false;
305 32967 : EndOfContents = false;
306 32967 : mHeadLen = 0;
307 32967 : }
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
|