Matter SDK Coverage Report
Current view: top level - lib/asn1 - ASN1Reader.cpp (source / functions) Coverage Total Hit
Test: SHA:f1767a8b0a3778fdf31b1d979afbdf544892fd94 Lines: 64.2 % 257 165
Test Date: 2026-06-03 07:35:21 Functions: 89.5 % 19 17

            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          598 : void ASN1Reader::Init(const uint8_t * buf, size_t len)
      42              : {
      43          598 :     ResetElementState();
      44          598 :     mBuf              = buf;
      45          598 :     mBufEnd           = buf + len;
      46          598 :     mElemStart        = buf;
      47          598 :     mContainerEnd     = mBufEnd;
      48          598 :     mNumSavedContexts = 0;
      49          598 : }
      50              : 
      51        28393 : CHIP_ERROR ASN1Reader::Next()
      52              : {
      53        28393 :     VerifyOrReturnError(!EndOfContents, ASN1_END);
      54        28393 :     VerifyOrReturnError(!IndefiniteLen, ASN1_ERROR_UNSUPPORTED_ENCODING);
      55              : 
      56              :     // Defense-in-depth against integer overflow: mHeadLen + ValueLen are both uint32_t and
      57              :     // their sum could in principle wrap around, advancing mElemStart to an unintended
      58              :     // location. DecodeHead already caps ValueLen at the remaining buffer, so this cannot
      59              :     // wrap from any input reaching Next() through the public API; the guard hardens against
      60              :     // a future caller or a regression in those upstream bounds checks.
      61        28392 :     VerifyOrReturnError(mHeadLen <= UINT32_MAX - ValueLen, ASN1_ERROR_LENGTH_OVERFLOW);
      62              :     // Defend against an inconsistent reader state where mElemStart has advanced past
      63              :     // mContainerEnd (e.g. a prior failed unwind left stale pointers). Without this
      64              :     // check the pointer subtraction below would underflow when cast to size_t and the
      65              :     // bounds comparison would silently pass.
      66        28392 :     VerifyOrReturnError(mContainerEnd >= mElemStart, ASN1_ERROR_INVALID_STATE);
      67              :     // Compare in integer space rather than pointer space. On 32-bit targets size_t == uint32_t,
      68              :     // so the size_t cast provides no additional width; the preceding LENGTH_OVERFLOW guard is
      69              :     // what prevents wrap there. The size_t widening eliminates pointer-arithmetic UB on 64-bit
      70              :     // targets where computing `mElemStart + mHeadLen + ValueLen` could otherwise wrap past the
      71              :     // end of the address space before the comparison runs.
      72              :     //
      73              :     // BEHAVIOR CHANGE: a bounds-exceeded result here means a child element claims more bytes
      74              :     // than its parent container holds (malformed encoding). Previously this advanced mElemStart
      75              :     // past mContainerEnd and the subsequent `mElemStart != mContainerEnd` check returned ASN1_END,
      76              :     // which callers (and the ASN1_EXIT_* macros) treat as a clean end of container -- silently
      77              :     // swallowing the malformed input. It now surfaces as ASN1_ERROR_INVALID_ENCODING. A child
      78              :     // ending exactly at mContainerEnd still passes this `<=` check and reports ASN1_END as before,
      79              :     // so well-formed certificates are unaffected.
      80        28392 :     VerifyOrReturnError(static_cast<size_t>(mHeadLen) + ValueLen <= static_cast<size_t>(mContainerEnd - mElemStart),
      81              :                         ASN1_ERROR_INVALID_ENCODING);
      82              : 
      83        28390 :     mElemStart = mElemStart + mHeadLen + ValueLen;
      84              : 
      85        28390 :     ResetElementState();
      86              : 
      87        28390 :     VerifyOrReturnError(mElemStart != mContainerEnd, ASN1_END);
      88              : 
      89        17723 :     return DecodeHead();
      90              : }
      91              : 
      92         7960 : CHIP_ERROR ASN1Reader::EnterConstructedType()
      93              : {
      94         7960 :     VerifyOrReturnError(Constructed, ASN1_ERROR_INVALID_STATE);
      95              : 
      96         7960 :     return EnterContainer(0);
      97              : }
      98              : 
      99         7689 : CHIP_ERROR ASN1Reader::ExitConstructedType()
     100              : {
     101         7689 :     return ExitContainer();
     102              : }
     103              : 
     104          856 : CHIP_ERROR ASN1Reader::GetConstructedType(const uint8_t *& val, uint32_t & valLen)
     105              : {
     106          856 :     VerifyOrReturnError(Constructed, ASN1_ERROR_INVALID_STATE);
     107              : 
     108              :     // Defend against an inconsistent reader state where mElemStart has advanced past
     109              :     // mContainerEnd. Required ahead of any size_t-widened subtraction so the result
     110              :     // cannot underflow.
     111          855 :     VerifyOrReturnError(mContainerEnd >= mElemStart, ASN1_ERROR_INVALID_STATE);
     112              :     // Guard against integer overflow: mHeadLen + ValueLen are both uint32_t and their sum
     113              :     // could wrap around, producing a bogus length for the caller.
     114          855 :     VerifyOrReturnError(mHeadLen <= UINT32_MAX - ValueLen, ASN1_ERROR_LENGTH_OVERFLOW);
     115              : 
     116          855 :     val    = mElemStart;
     117          855 :     valLen = mHeadLen + ValueLen;
     118              : 
     119          855 :     return CHIP_NO_ERROR;
     120              : }
     121         1033 : CHIP_ERROR ASN1Reader::EnterEncapsulatedType()
     122              : {
     123         1033 :     VerifyOrReturnError(Class == kASN1TagClass_Universal &&
     124              :                             (Tag == kASN1UniversalTag_OctetString || Tag == kASN1UniversalTag_BitString),
     125              :                         ASN1_ERROR_INVALID_STATE);
     126              : 
     127         1033 :     VerifyOrReturnError(!Constructed, ASN1_ERROR_UNSUPPORTED_ENCODING);
     128              : 
     129         1033 :     return EnterContainer((Tag == kASN1UniversalTag_BitString) ? 1 : 0);
     130              : }
     131              : 
     132         1010 : CHIP_ERROR ASN1Reader::ExitEncapsulatedType()
     133              : {
     134         1010 :     return ExitContainer();
     135              : }
     136              : 
     137         8993 : CHIP_ERROR ASN1Reader::EnterContainer(uint32_t offset)
     138              : {
     139         8993 :     VerifyOrReturnError(mNumSavedContexts != kMaxContextDepth, ASN1_ERROR_MAX_DEPTH_EXCEEDED);
     140              : 
     141              :     // Peek-then-commit: validate all preconditions BEFORE mutating reader
     142              :     // state. If any guard fires the saved-context stack, mElemStart, and
     143              :     // mContainerEnd are all left untouched so the reader stays in a
     144              :     // consistent state.
     145         8993 :     if (!IndefiniteLen)
     146              :     {
     147         8993 :         VerifyOrReturnError(CanCastTo<uint32_t>(mBufEnd - Value), ASN1_ERROR_VALUE_OVERFLOW);
     148         8993 :         VerifyOrReturnError(static_cast<uint32_t>(mBufEnd - Value) >= ValueLen, ASN1_ERROR_VALUE_OVERFLOW);
     149              :     }
     150              : 
     151              :     // All checks passed - now commit by pushing the saved context and updating reader state.
     152         8993 :     mSavedContexts[mNumSavedContexts].ElemStart     = mElemStart;
     153         8993 :     mSavedContexts[mNumSavedContexts].HeadLen       = mHeadLen;
     154         8993 :     mSavedContexts[mNumSavedContexts].ValueLen      = ValueLen;
     155         8993 :     mSavedContexts[mNumSavedContexts].IndefiniteLen = IndefiniteLen;
     156         8993 :     mSavedContexts[mNumSavedContexts].ContainerEnd  = mContainerEnd;
     157         8993 :     mNumSavedContexts++;
     158              : 
     159         8993 :     mElemStart = Value + offset;
     160         8993 :     if (!IndefiniteLen)
     161              :     {
     162         8993 :         mContainerEnd = Value + ValueLen;
     163              :     }
     164              : 
     165         8993 :     ResetElementState();
     166              : 
     167         8993 :     return CHIP_NO_ERROR;
     168              : }
     169              : 
     170         8699 : CHIP_ERROR ASN1Reader::ExitContainer()
     171              : {
     172         8699 :     VerifyOrReturnError(mNumSavedContexts != 0, ASN1_ERROR_INVALID_STATE);
     173              : 
     174              :     // Peek-then-commit: validate the saved context BEFORE mutating any reader
     175              :     // state. On any error the saved-context stack is left untouched so the
     176              :     // reader stays in a consistent state and a follow-up call sees the same
     177              :     // failure (rather than silently operating on a half-popped stack).
     178         8699 :     const ASN1ParseContext & prevContext = mSavedContexts[mNumSavedContexts - 1];
     179              : 
     180         8699 :     VerifyOrReturnError(!prevContext.IndefiniteLen, ASN1_ERROR_UNSUPPORTED_ENCODING);
     181              : 
     182              :     // Guard against integer overflow: HeadLen + ValueLen are both uint32_t and their sum
     183              :     // could wrap around, potentially advancing mElemStart to an unintended location.
     184         8699 :     VerifyOrReturnError(prevContext.HeadLen <= UINT32_MAX - prevContext.ValueLen, ASN1_ERROR_LENGTH_OVERFLOW);
     185              :     // Defend against a saved context with ContainerEnd < ElemStart so the pointer
     186              :     // subtraction below cannot underflow when widened to size_t.
     187         8699 :     VerifyOrReturnError(prevContext.ContainerEnd >= prevContext.ElemStart, ASN1_ERROR_INVALID_STATE);
     188              :     // Compare in integer space rather than pointer space. On 32-bit targets size_t == uint32_t
     189              :     // and the LENGTH_OVERFLOW guard above is what prevents wrap; the size_t widening eliminates
     190              :     // pointer-arithmetic UB on 64-bit targets where `prevContext.ElemStart + prevContext.HeadLen
     191              :     // + prevContext.ValueLen` could otherwise wrap past the end of the address space. A
     192              :     // bounds-exceeded result here means the saved container declared more bytes than its parent
     193              :     // holds (malformed encoding), NOT a clean end of container, so it must surface as
     194              :     // INVALID_ENCODING rather than ASN1_END.
     195         8699 :     VerifyOrReturnError(static_cast<size_t>(prevContext.HeadLen) + prevContext.ValueLen <=
     196              :                             static_cast<size_t>(prevContext.ContainerEnd - prevContext.ElemStart),
     197              :                         ASN1_ERROR_INVALID_ENCODING);
     198              : 
     199              :     // All checks passed - now commit by popping the saved context and updating reader state.
     200         8699 :     --mNumSavedContexts;
     201         8699 :     mElemStart = prevContext.ElemStart + prevContext.HeadLen + prevContext.ValueLen;
     202              : 
     203         8699 :     mContainerEnd = prevContext.ContainerEnd;
     204              : 
     205         8699 :     ResetElementState();
     206              : 
     207         8699 :     return CHIP_NO_ERROR;
     208              : }
     209              : 
     210            0 : bool ASN1Reader::IsContained() const
     211              : {
     212            0 :     return mNumSavedContexts > 0;
     213              : }
     214              : 
     215          618 : CHIP_ERROR ASN1Reader::GetInteger(int64_t & val)
     216              : {
     217          618 :     uint8_t encodedVal[sizeof(int64_t)] = { 0 };
     218          618 :     size_t valPaddingLen                = sizeof(int64_t) - ValueLen;
     219              : 
     220          618 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     221          618 :     VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
     222          618 :     VerifyOrReturnError(ValueLen <= sizeof(int64_t), ASN1_ERROR_VALUE_OVERFLOW);
     223              :     // Mirrors the guard sequence in Next(): (1) reject inconsistent state where
     224              :     // mContainerEnd < mElemStart (without this the size_t-widened subtraction below would
     225              :     // underflow to a huge value and the bounds compare would trivially pass), (2) reject
     226              :     // mHeadLen + ValueLen wrap on 32-bit targets where size_t == uint32_t, (3) bounds-check
     227              :     // via the size_t-widened comparison.
     228          618 :     VerifyOrReturnError(mContainerEnd >= mElemStart, ASN1_ERROR_INVALID_STATE);
     229          618 :     VerifyOrReturnError(mHeadLen <= UINT32_MAX - ValueLen, ASN1_ERROR_LENGTH_OVERFLOW);
     230          618 :     VerifyOrReturnError(static_cast<size_t>(mHeadLen) + ValueLen <= static_cast<size_t>(mContainerEnd - mElemStart),
     231              :                         ASN1_ERROR_UNDERRUN);
     232              : 
     233          618 :     if ((*Value & 0x80) == 0x80)
     234              :     {
     235           19 :         for (size_t i = 0; i < valPaddingLen; i++)
     236              :         {
     237           15 :             encodedVal[i] = 0xFF;
     238              :         }
     239              :     }
     240          618 :     memcpy(&encodedVal[valPaddingLen], Value, ValueLen);
     241              : 
     242          618 :     val = static_cast<int64_t>(BigEndian::Get64(encodedVal));
     243              : 
     244          618 :     return CHIP_NO_ERROR;
     245              : }
     246              : 
     247          582 : CHIP_ERROR ASN1Reader::GetBoolean(bool & val)
     248              : {
     249          582 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     250          582 :     VerifyOrReturnError(ValueLen == 1, ASN1_ERROR_INVALID_ENCODING);
     251              :     // Mirrors the guard sequence in Next(): (1) reject inconsistent state where
     252              :     // mContainerEnd < mElemStart, (2) reject mHeadLen + ValueLen wrap on 32-bit
     253              :     // (size_t == uint32_t), (3) bounds-check via size_t-widened comparison.
     254          582 :     VerifyOrReturnError(mContainerEnd >= mElemStart, ASN1_ERROR_INVALID_STATE);
     255          582 :     VerifyOrReturnError(mHeadLen <= UINT32_MAX - ValueLen, ASN1_ERROR_LENGTH_OVERFLOW);
     256          582 :     VerifyOrReturnError(static_cast<size_t>(mHeadLen) + ValueLen <= static_cast<size_t>(mContainerEnd - mElemStart),
     257              :                         ASN1_ERROR_UNDERRUN);
     258          582 :     VerifyOrReturnError(Value[0] == 0 || Value[0] == 0xFF, ASN1_ERROR_INVALID_ENCODING);
     259              : 
     260          582 :     val = (Value[0] != 0);
     261              : 
     262          582 :     return CHIP_NO_ERROR;
     263              : }
     264              : 
     265          369 : CHIP_ERROR ASN1Reader::GetUTCTime(ASN1UniversalTime & outTime)
     266              : {
     267              :     // Supported Encoding: YYMMDDHHMMSSZ
     268          369 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     269          369 :     VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
     270              :     // Mirrors the guard sequence in Next(): (1) reject inconsistent state where
     271              :     // mContainerEnd < mElemStart, (2) reject mHeadLen + ValueLen wrap on 32-bit
     272              :     // (size_t == uint32_t), (3) bounds-check via size_t-widened comparison.
     273          369 :     VerifyOrReturnError(mContainerEnd >= mElemStart, ASN1_ERROR_INVALID_STATE);
     274          369 :     VerifyOrReturnError(mHeadLen <= UINT32_MAX - ValueLen, ASN1_ERROR_LENGTH_OVERFLOW);
     275          369 :     VerifyOrReturnError(static_cast<size_t>(mHeadLen) + ValueLen <= static_cast<size_t>(mContainerEnd - mElemStart),
     276              :                         ASN1_ERROR_UNDERRUN);
     277          369 :     VerifyOrReturnError(ValueLen == 13 && Value[12] == 'Z', ASN1_ERROR_UNSUPPORTED_ENCODING);
     278              : 
     279          369 :     return outTime.ImportFrom_ASN1_TIME_string(CharSpan(reinterpret_cast<const char *>(Value), ValueLen));
     280              : }
     281              : 
     282           60 : CHIP_ERROR ASN1Reader::GetGeneralizedTime(ASN1UniversalTime & outTime)
     283              : {
     284              :     // Supported Encoding: YYYYMMDDHHMMSSZ
     285           60 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     286           60 :     VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
     287              :     // Mirrors the guard sequence in Next(): (1) reject inconsistent state where
     288              :     // mContainerEnd < mElemStart, (2) reject mHeadLen + ValueLen wrap on 32-bit
     289              :     // (size_t == uint32_t), (3) bounds-check via size_t-widened comparison.
     290           60 :     VerifyOrReturnError(mContainerEnd >= mElemStart, ASN1_ERROR_INVALID_STATE);
     291           60 :     VerifyOrReturnError(mHeadLen <= UINT32_MAX - ValueLen, ASN1_ERROR_LENGTH_OVERFLOW);
     292           60 :     VerifyOrReturnError(static_cast<size_t>(mHeadLen) + ValueLen <= static_cast<size_t>(mContainerEnd - mElemStart),
     293              :                         ASN1_ERROR_UNDERRUN);
     294           60 :     VerifyOrReturnError(ValueLen == 15 && Value[14] == 'Z', ASN1_ERROR_UNSUPPORTED_ENCODING);
     295              : 
     296           60 :     return outTime.ImportFrom_ASN1_TIME_string(CharSpan(reinterpret_cast<const char *>(Value), ValueLen));
     297              : }
     298              : 
     299          203 : static uint8_t ReverseBits(uint8_t v)
     300              : {
     301              :     // swap adjacent bits
     302          203 :     v = static_cast<uint8_t>(static_cast<uint8_t>((v >> 1) & 0x55) | static_cast<uint8_t>((v & 0x55) << 1));
     303              :     // swap adjacent bit pairs
     304          203 :     v = static_cast<uint8_t>(static_cast<uint8_t>((v >> 2) & 0x33) | static_cast<uint8_t>((v & 0x33) << 2));
     305              :     // swap nibbles
     306          203 :     v = static_cast<uint8_t>(static_cast<uint8_t>(v >> 4) | static_cast<uint8_t>(v << 4));
     307          203 :     return v;
     308              : }
     309              : 
     310          196 : CHIP_ERROR ASN1Reader::GetBitString(uint32_t & outVal)
     311              : {
     312              :     // NOTE: only supports DER encoding.
     313          196 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     314          196 :     VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
     315          196 :     VerifyOrReturnError(ValueLen <= 5, ASN1_ERROR_UNSUPPORTED_ENCODING);
     316              :     // Mirrors the guard sequence in Next(): (1) reject inconsistent state where
     317              :     // mContainerEnd < mElemStart, (2) reject mHeadLen + ValueLen wrap on 32-bit
     318              :     // (size_t == uint32_t), (3) bounds-check via size_t-widened comparison.
     319          196 :     VerifyOrReturnError(mContainerEnd >= mElemStart, ASN1_ERROR_INVALID_STATE);
     320          196 :     VerifyOrReturnError(mHeadLen <= UINT32_MAX - ValueLen, ASN1_ERROR_LENGTH_OVERFLOW);
     321          196 :     VerifyOrReturnError(static_cast<size_t>(mHeadLen) + ValueLen <= static_cast<size_t>(mContainerEnd - mElemStart),
     322              :                         ASN1_ERROR_UNDERRUN);
     323              : 
     324          196 :     if (ValueLen == 1)
     325              :     {
     326            2 :         outVal = 0;
     327              :     }
     328              :     else
     329              :     {
     330          194 :         outVal             = ReverseBits(Value[1]);
     331          194 :         unsigned int shift = 8;
     332          203 :         for (uint32_t i = 2; i < ValueLen; i++, shift += 8)
     333              :         {
     334              :             // Cast to uint32_t before shifting: ReverseBits returns uint8_t which
     335              :             // would be promoted to (signed) int, and shifts of 24+ on a value with
     336              :             // the high bit set are undefined behavior on signed integers.
     337            9 :             outVal |= (static_cast<uint32_t>(ReverseBits(Value[i])) << shift);
     338              :         }
     339              :     }
     340              : 
     341          196 :     return CHIP_NO_ERROR;
     342              : }
     343              : 
     344        17723 : CHIP_ERROR ASN1Reader::DecodeHead()
     345              : {
     346        17723 :     const uint8_t * p = mElemStart;
     347        17723 :     VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
     348              : 
     349        17723 :     Class       = *p & 0xC0;
     350        17723 :     Constructed = (*p & 0x20) != 0;
     351        17723 :     Tag         = *p & 0x1F;
     352              : 
     353              :     // Only tags < 31 supported. The implication of this is that encoded tags are exactly 1 byte long.
     354        17723 :     VerifyOrReturnError(Tag < 0x1F, ASN1_ERROR_UNSUPPORTED_ENCODING);
     355              : 
     356        17717 :     p++;
     357        17717 :     VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
     358              : 
     359        17717 :     if ((*p & 0x80) == 0)
     360              :     {
     361        16192 :         ValueLen      = *p & 0x7F;
     362        16192 :         IndefiniteLen = false;
     363        16192 :         p++;
     364              :     }
     365         1525 :     else if (*p == 0x80)
     366              :     {
     367            1 :         ValueLen      = 0;
     368            1 :         IndefiniteLen = true;
     369            1 :         p++;
     370              :     }
     371              :     else
     372              :     {
     373         1524 :         ValueLen       = 0;
     374         1524 :         uint8_t lenLen = *p & 0x7F;
     375         1524 :         p++;
     376         3619 :         for (; lenLen > 0; lenLen--, p++)
     377              :         {
     378         2095 :             VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
     379         2095 :             VerifyOrReturnError((ValueLen & 0xFF000000) == 0, ASN1_ERROR_LENGTH_OVERFLOW);
     380         2095 :             ValueLen = (ValueLen << 8) | *p;
     381              :         }
     382         1524 :         IndefiniteLen = false;
     383              :     }
     384              : 
     385        17717 :     VerifyOrReturnError(CanCastTo<uint32_t>(mBufEnd - p), ASN1_ERROR_VALUE_OVERFLOW);
     386        17717 :     VerifyOrReturnError(static_cast<uint32_t>(mBufEnd - p) >= ValueLen, ASN1_ERROR_VALUE_OVERFLOW);
     387        17715 :     VerifyOrReturnError(CanCastTo<uint32_t>(p - mElemStart), ASN1_ERROR_VALUE_OVERFLOW);
     388        17715 :     mHeadLen = static_cast<uint32_t>(p - mElemStart);
     389              : 
     390        17715 :     EndOfContents = (Class == kASN1TagClass_Universal && Tag == 0 && !Constructed && ValueLen == 0);
     391              : 
     392        17715 :     Value = p;
     393              : 
     394        17715 :     return CHIP_NO_ERROR;
     395              : }
     396              : 
     397        46680 : void ASN1Reader::ResetElementState()
     398              : {
     399        46680 :     Class         = 0;
     400        46680 :     Tag           = 0;
     401        46680 :     Value         = nullptr;
     402        46680 :     ValueLen      = 0;
     403        46680 :     Constructed   = false;
     404        46680 :     IndefiniteLen = false;
     405        46680 :     EndOfContents = false;
     406        46680 :     mHeadLen      = 0;
     407        46680 : }
     408              : 
     409            0 : CHIP_ERROR DumpASN1(ASN1Reader & asn1Parser, const char * prefix, const char * indent)
     410              : {
     411            0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     412              : 
     413            0 :     if (indent == nullptr)
     414            0 :         indent = "  ";
     415              : 
     416            0 :     int nestLevel = 0;
     417              :     while (true)
     418              :     {
     419            0 :         err = asn1Parser.Next();
     420            0 :         if (err != CHIP_NO_ERROR)
     421              :         {
     422            0 :             if (err == ASN1_END)
     423              :             {
     424            0 :                 if (asn1Parser.IsContained())
     425              :                 {
     426            0 :                     err = asn1Parser.ExitConstructedType();
     427            0 :                     if (err != CHIP_NO_ERROR)
     428              :                     {
     429            0 :                         printf("ASN1Reader::ExitConstructedType() failed: %" CHIP_ERROR_FORMAT "\n", err.Format());
     430            0 :                         return err;
     431              :                     }
     432            0 :                     nestLevel--;
     433            0 :                     continue;
     434              :                 }
     435            0 :                 break;
     436              :             }
     437            0 :             printf("ASN1Reader::Next() failed: %" CHIP_ERROR_FORMAT "\n", err.Format());
     438            0 :             return err;
     439              :         }
     440            0 :         if (prefix != nullptr)
     441            0 :             printf("%s", prefix);
     442            0 :         for (int i = nestLevel; i; i--)
     443            0 :             printf("%s", indent);
     444            0 :         if (asn1Parser.IsEndOfContents())
     445            0 :             printf("END-OF-CONTENTS ");
     446            0 :         else if (asn1Parser.GetClass() == kASN1TagClass_Universal)
     447            0 :             switch (asn1Parser.GetTag())
     448              :             {
     449            0 :             case kASN1UniversalTag_Boolean:
     450            0 :                 printf("BOOLEAN ");
     451            0 :                 break;
     452            0 :             case kASN1UniversalTag_Integer:
     453            0 :                 printf("INTEGER ");
     454            0 :                 break;
     455            0 :             case kASN1UniversalTag_BitString:
     456            0 :                 printf("BIT STRING ");
     457            0 :                 break;
     458            0 :             case kASN1UniversalTag_OctetString:
     459            0 :                 printf("OCTET STRING ");
     460            0 :                 break;
     461            0 :             case kASN1UniversalTag_Null:
     462            0 :                 printf("NULL ");
     463            0 :                 break;
     464            0 :             case kASN1UniversalTag_ObjectId:
     465            0 :                 printf("OBJECT IDENTIFIER ");
     466            0 :                 break;
     467            0 :             case kASN1UniversalTag_ObjectDesc:
     468            0 :                 printf("OBJECT DESCRIPTOR ");
     469            0 :                 break;
     470            0 :             case kASN1UniversalTag_External:
     471            0 :                 printf("EXTERNAL ");
     472            0 :                 break;
     473            0 :             case kASN1UniversalTag_Real:
     474            0 :                 printf("REAL ");
     475            0 :                 break;
     476            0 :             case kASN1UniversalTag_Enumerated:
     477            0 :                 printf("ENUMERATED ");
     478            0 :                 break;
     479            0 :             case kASN1UniversalTag_Sequence:
     480            0 :                 printf("SEQUENCE ");
     481            0 :                 break;
     482            0 :             case kASN1UniversalTag_Set:
     483            0 :                 printf("SET ");
     484            0 :                 break;
     485            0 :             case kASN1UniversalTag_UTF8String:
     486              :             case kASN1UniversalTag_NumericString:
     487              :             case kASN1UniversalTag_PrintableString:
     488              :             case kASN1UniversalTag_T61String:
     489              :             case kASN1UniversalTag_VideotexString:
     490              :             case kASN1UniversalTag_IA5String:
     491              :             case kASN1UniversalTag_GraphicString:
     492              :             case kASN1UniversalTag_VisibleString:
     493              :             case kASN1UniversalTag_GeneralString:
     494              :             case kASN1UniversalTag_UniversalString:
     495            0 :                 printf("STRING ");
     496            0 :                 break;
     497            0 :             case kASN1UniversalTag_UTCTime:
     498              :             case kASN1UniversalTag_GeneralizedTime:
     499            0 :                 printf("TIME ");
     500            0 :                 break;
     501            0 :             default:
     502            0 :                 printf("[UNIVERSAL %lu] ", static_cast<unsigned long>(asn1Parser.GetTag()));
     503            0 :                 break;
     504              :             }
     505            0 :         else if (asn1Parser.GetClass() == kASN1TagClass_Application)
     506            0 :             printf("[APPLICATION %lu] ", static_cast<unsigned long>(asn1Parser.GetTag()));
     507            0 :         else if (asn1Parser.GetClass() == kASN1TagClass_ContextSpecific)
     508            0 :             printf("[%lu] ", static_cast<unsigned long>(asn1Parser.GetTag()));
     509            0 :         else if (asn1Parser.GetClass() == kASN1TagClass_Private)
     510            0 :             printf("[PRIVATE %lu] ", static_cast<unsigned long>(asn1Parser.GetTag()));
     511              : 
     512            0 :         if (asn1Parser.IsConstructed())
     513            0 :             printf("(constructed) ");
     514              : 
     515            0 :         if (asn1Parser.IsIndefiniteLen())
     516            0 :             printf("Length = indefinite\n");
     517              :         else
     518            0 :             printf("Length = %ld\n", static_cast<long>(asn1Parser.GetValueLen()));
     519              : 
     520            0 :         if (asn1Parser.IsConstructed())
     521              :         {
     522            0 :             err = asn1Parser.EnterConstructedType();
     523            0 :             if (err != CHIP_NO_ERROR)
     524              :             {
     525            0 :                 printf("ASN1Reader::EnterConstructedType() failed: %" CHIP_ERROR_FORMAT "\n", err.Format());
     526            0 :                 return err;
     527              :             }
     528            0 :             nestLevel++;
     529              :         }
     530            0 :     }
     531              : 
     532            0 :     return err;
     533              : }
     534              : 
     535              : } // namespace ASN1
     536              : } // namespace chip
        

Generated by: LCOV version 2.0-1