Matter SDK Coverage Report
Current view: top level - lib/asn1 - ASN1Reader.cpp (source / functions) Coverage Total Hit
Test: SHA:09f6fdf93a7e847a42518c076e487f336877a722 Lines: 59.9 % 237 142
Test Date: 2025-06-07 07:10:33 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          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
        

Generated by: LCOV version 2.0-1