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