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