Matter SDK Coverage Report
Current view: top level - lib/asn1 - ASN1Reader.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 59.9 % 237 142
Test Date: 2025-01-17 19:00:11 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          399 : void ASN1Reader::Init(const uint8_t * buf, size_t len)
      42              : {
      43          399 :     ResetElementState();
      44          399 :     mBuf              = buf;
      45          399 :     mBufEnd           = buf + len;
      46          399 :     mElemStart        = buf;
      47          399 :     mContainerEnd     = mBufEnd;
      48          399 :     mNumSavedContexts = 0;
      49          399 : }
      50              : 
      51        17050 : CHIP_ERROR ASN1Reader::Next()
      52              : {
      53        17050 :     VerifyOrReturnError(!EndOfContents, ASN1_END);
      54        17050 :     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        17050 :     mElemStart = mElemStart + mHeadLen + ValueLen;
      59              : 
      60        17050 :     ResetElementState();
      61              : 
      62        17050 :     VerifyOrReturnError(mElemStart != mContainerEnd, ASN1_END);
      63              : 
      64        10756 :     return DecodeHead();
      65              : }
      66              : 
      67         4918 : CHIP_ERROR ASN1Reader::EnterConstructedType()
      68              : {
      69         4918 :     VerifyOrReturnError(Constructed, ASN1_ERROR_INVALID_STATE);
      70              : 
      71         4918 :     return EnterContainer(0);
      72              : }
      73              : 
      74         4668 : CHIP_ERROR ASN1Reader::ExitConstructedType()
      75              : {
      76         4668 :     return ExitContainer();
      77              : }
      78              : 
      79          461 : CHIP_ERROR ASN1Reader::GetConstructedType(const uint8_t *& val, uint32_t & valLen)
      80              : {
      81          461 :     VerifyOrReturnError(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 :     VerifyOrReturnError(!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         5472 : CHIP_ERROR ASN1Reader::EnterContainer(uint32_t offset)
     105              : {
     106         5472 :     VerifyOrReturnError(mNumSavedContexts != kMaxContextDepth, ASN1_ERROR_MAX_DEPTH_EXCEEDED);
     107              : 
     108         5472 :     mSavedContexts[mNumSavedContexts].ElemStart     = mElemStart;
     109         5472 :     mSavedContexts[mNumSavedContexts].HeadLen       = mHeadLen;
     110         5472 :     mSavedContexts[mNumSavedContexts].ValueLen      = ValueLen;
     111         5472 :     mSavedContexts[mNumSavedContexts].IndefiniteLen = IndefiniteLen;
     112         5472 :     mSavedContexts[mNumSavedContexts].ContainerEnd  = mContainerEnd;
     113         5472 :     mNumSavedContexts++;
     114              : 
     115         5472 :     mElemStart = Value + offset;
     116         5472 :     if (!IndefiniteLen)
     117              :     {
     118         5472 :         VerifyOrReturnError(CanCastTo<uint32_t>(mBufEnd - Value), ASN1_ERROR_VALUE_OVERFLOW);
     119         5472 :         VerifyOrReturnError(static_cast<uint32_t>(mBufEnd - Value) >= ValueLen, ASN1_ERROR_VALUE_OVERFLOW);
     120         5472 :         mContainerEnd = Value + ValueLen;
     121              :     }
     122              : 
     123         5472 :     ResetElementState();
     124              : 
     125         5472 :     return CHIP_NO_ERROR;
     126              : }
     127              : 
     128         5199 : CHIP_ERROR ASN1Reader::ExitContainer()
     129              : {
     130         5199 :     VerifyOrReturnError(mNumSavedContexts != 0, ASN1_ERROR_INVALID_STATE);
     131              : 
     132         5199 :     ASN1ParseContext & prevContext = mSavedContexts[--mNumSavedContexts];
     133              : 
     134         5199 :     VerifyOrReturnError(!prevContext.IndefiniteLen, ASN1_ERROR_UNSUPPORTED_ENCODING);
     135              : 
     136         5199 :     mElemStart = prevContext.ElemStart + prevContext.HeadLen + prevContext.ValueLen;
     137              : 
     138         5199 :     mContainerEnd = prevContext.ContainerEnd;
     139              : 
     140         5199 :     ResetElementState();
     141              : 
     142         5199 :     return CHIP_NO_ERROR;
     143              : }
     144              : 
     145            0 : bool ASN1Reader::IsContained() const
     146              : {
     147            0 :     return mNumSavedContexts > 0;
     148              : }
     149              : 
     150          431 : CHIP_ERROR ASN1Reader::GetInteger(int64_t & val)
     151              : {
     152          431 :     uint8_t encodedVal[sizeof(int64_t)] = { 0 };
     153          431 :     size_t valPaddingLen                = sizeof(int64_t) - ValueLen;
     154              : 
     155          431 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     156          431 :     VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
     157          431 :     VerifyOrReturnError(ValueLen <= sizeof(int64_t), ASN1_ERROR_VALUE_OVERFLOW);
     158          431 :     VerifyOrReturnError(mElemStart + mHeadLen + ValueLen <= mContainerEnd, ASN1_ERROR_UNDERRUN);
     159              : 
     160          431 :     if ((*Value & 0x80) == 0x80)
     161              :     {
     162           19 :         for (size_t i = 0; i < valPaddingLen; i++)
     163              :         {
     164           15 :             encodedVal[i] = 0xFF;
     165              :         }
     166              :     }
     167          431 :     memcpy(&encodedVal[valPaddingLen], Value, ValueLen);
     168              : 
     169          431 :     val = static_cast<int64_t>(BigEndian::Get64(encodedVal));
     170              : 
     171          431 :     return CHIP_NO_ERROR;
     172              : }
     173              : 
     174          323 : CHIP_ERROR ASN1Reader::GetBoolean(bool & val)
     175              : {
     176          323 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     177          323 :     VerifyOrReturnError(ValueLen == 1, ASN1_ERROR_INVALID_ENCODING);
     178          323 :     VerifyOrReturnError(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 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     190          251 :     VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
     191          251 :     VerifyOrReturnError(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 :     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          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 :     VerifyOrReturnError(Value != nullptr, ASN1_ERROR_INVALID_STATE);
     223          106 :     VerifyOrReturnError(ValueLen >= 1, ASN1_ERROR_INVALID_ENCODING);
     224          106 :     VerifyOrReturnError(ValueLen <= 5, ASN1_ERROR_UNSUPPORTED_ENCODING);
     225          106 :     VerifyOrReturnError(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        10756 : CHIP_ERROR ASN1Reader::DecodeHead()
     245              : {
     246        10756 :     const uint8_t * p = mElemStart;
     247        10756 :     VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
     248              : 
     249        10756 :     Class       = *p & 0xC0;
     250        10756 :     Constructed = (*p & 0x20) != 0;
     251        10756 :     Tag         = *p & 0x1F;
     252              : 
     253              :     // Only tags < 31 supported. The implication of this is that encoded tags are exactly 1 byte long.
     254        10756 :     VerifyOrReturnError(Tag < 0x1F, ASN1_ERROR_UNSUPPORTED_ENCODING);
     255              : 
     256        10750 :     p++;
     257        10750 :     VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
     258              : 
     259        10750 :     if ((*p & 0x80) == 0)
     260              :     {
     261         9779 :         ValueLen      = *p & 0x7F;
     262         9779 :         IndefiniteLen = false;
     263         9779 :         p++;
     264              :     }
     265          971 :     else if (*p == 0x80)
     266              :     {
     267            0 :         ValueLen      = 0;
     268            0 :         IndefiniteLen = true;
     269            0 :         p++;
     270              :     }
     271              :     else
     272              :     {
     273          971 :         ValueLen       = 0;
     274          971 :         uint8_t lenLen = *p & 0x7F;
     275          971 :         p++;
     276         2302 :         for (; lenLen > 0; lenLen--, p++)
     277              :         {
     278         1331 :             VerifyOrReturnError(p < mBufEnd, ASN1_ERROR_UNDERRUN);
     279         1331 :             VerifyOrReturnError((ValueLen & 0xFF000000) == 0, ASN1_ERROR_LENGTH_OVERFLOW);
     280         1331 :             ValueLen = (ValueLen << 8) | *p;
     281              :         }
     282          971 :         IndefiniteLen = false;
     283              :     }
     284              : 
     285        10750 :     VerifyOrReturnError(CanCastTo<uint32_t>(mBufEnd - p), ASN1_ERROR_VALUE_OVERFLOW);
     286        10750 :     VerifyOrReturnError(static_cast<uint32_t>(mBufEnd - p) >= ValueLen, ASN1_ERROR_VALUE_OVERFLOW);
     287        10750 :     VerifyOrReturnError(CanCastTo<uint32_t>(p - mElemStart), ASN1_ERROR_VALUE_OVERFLOW);
     288        10750 :     mHeadLen = static_cast<uint32_t>(p - mElemStart);
     289              : 
     290        10750 :     EndOfContents = (Class == kASN1TagClass_Universal && Tag == 0 && !Constructed && ValueLen == 0);
     291              : 
     292        10750 :     Value = p;
     293              : 
     294        10750 :     return CHIP_NO_ERROR;
     295              : }
     296              : 
     297        28120 : void ASN1Reader::ResetElementState()
     298              : {
     299        28120 :     Class         = 0;
     300        28120 :     Tag           = 0;
     301        28120 :     Value         = nullptr;
     302        28120 :     ValueLen      = 0;
     303        28120 :     Constructed   = false;
     304        28120 :     IndefiniteLen = false;
     305        28120 :     EndOfContents = false;
     306        28120 :     mHeadLen      = 0;
     307        28120 : }
     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