Matter SDK Coverage Report
Current view: top level - lib/asn1 - ASN1Writer.cpp (source / functions) Coverage Total Hit
Test: SHA:6e8676be6142bb541fa68048c77f2fc56a21c7b1 Lines: 91.5 % 199 182
Test Date: 2025-01-29 08:09:34 Functions: 96.6 % 29 28

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 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 writing 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              : #include <string.h>
      32              : 
      33              : #include <lib/asn1/ASN1.h>
      34              : #include <lib/core/CHIPCore.h>
      35              : #include <lib/core/CHIPEncoding.h>
      36              : #include <lib/core/TLV.h>
      37              : #include <lib/support/CodeUtils.h>
      38              : #include <lib/support/SafeInt.h>
      39              : 
      40              : namespace chip {
      41              : namespace ASN1 {
      42              : 
      43              : using namespace chip::Encoding;
      44              : 
      45              : enum
      46              : {
      47              :     kLengthFieldReserveSize = 1,
      48              :     kUnknownLength          = -1,
      49              :     kUnknownLengthMarker    = 0xFF
      50              : };
      51              : 
      52         1856 : void ASN1Writer::Init(uint8_t * buf, size_t maxLen)
      53              : {
      54         1856 :     mBuf                 = buf;
      55         1856 :     mWritePoint          = buf;
      56         1856 :     mBufEnd              = buf + maxLen;
      57         1856 :     mDeferredLengthCount = 0;
      58         1856 : }
      59              : 
      60         2843 : void ASN1Writer::InitNullWriter()
      61              : {
      62         2843 :     mBuf                 = nullptr;
      63         2843 :     mWritePoint          = nullptr;
      64         2843 :     mBufEnd              = nullptr;
      65         2843 :     mDeferredLengthCount = 0;
      66         2843 : }
      67              : 
      68         1769 : size_t ASN1Writer::GetLengthWritten() const
      69              : {
      70         1769 :     return (mBuf != nullptr) ? static_cast<size_t>(mWritePoint - mBuf) : 0;
      71              : }
      72              : 
      73         3276 : CHIP_ERROR ASN1Writer::PutInteger(int64_t val)
      74              : {
      75         3276 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
      76              : 
      77              :     uint8_t encodedVal[sizeof(int64_t)];
      78              :     uint8_t valStart, valLen;
      79              : 
      80         2019 :     BigEndian::Put64(encodedVal, static_cast<uint64_t>(val));
      81              : 
      82        16088 :     for (valStart = 0; valStart < 7; valStart++)
      83              :     {
      84        14103 :         if (encodedVal[valStart] == 0x00 && (encodedVal[valStart + 1] & 0x80) == 0)
      85        14054 :             continue;
      86           49 :         if (encodedVal[valStart] == 0xFF && (encodedVal[valStart + 1] & 0x80) == 0x80)
      87           15 :             continue;
      88           34 :         break;
      89              :     }
      90         2019 :     valLen = static_cast<uint8_t>(8 - valStart);
      91              : 
      92         2019 :     return PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, encodedVal + valStart, valLen);
      93              : }
      94              : 
      95         8833 : CHIP_ERROR ASN1Writer::PutBoolean(bool val)
      96              : {
      97         8833 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
      98              : 
      99         5300 :     ReturnErrorOnFailure(EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_Boolean, false, 1));
     100              : 
     101         5300 :     *mWritePoint++ = (val) ? 0xFF : 0;
     102              : 
     103         5300 :     return CHIP_NO_ERROR;
     104              : }
     105              : 
     106        36603 : CHIP_ERROR ASN1Writer::PutObjectId(const uint8_t * val, uint16_t valLen)
     107              : {
     108        36603 :     return PutValue(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId, false, val, valLen);
     109              : }
     110              : 
     111         9773 : CHIP_ERROR ASN1Writer::PutString(uint8_t tag, const char * val, uint16_t valLen)
     112              : {
     113         9773 :     return PutValue(kASN1TagClass_Universal, tag, false, (const uint8_t *) val, valLen);
     114              : }
     115              : 
     116         2930 : CHIP_ERROR ASN1Writer::PutOctetString(const uint8_t * val, uint16_t valLen)
     117              : {
     118         2930 :     return PutValue(kASN1TagClass_Universal, kASN1UniversalTag_OctetString, false, val, valLen);
     119              : }
     120              : 
     121         2906 : CHIP_ERROR ASN1Writer::PutOctetString(uint8_t cls, uint8_t tag, const uint8_t * val, uint16_t valLen)
     122              : {
     123         2906 :     return PutValue(cls, tag, false, val, valLen);
     124              : }
     125              : 
     126            2 : CHIP_ERROR ASN1Writer::PutOctetString(uint8_t cls, uint8_t tag, chip::TLV::TLVReader & tlvReader)
     127              : {
     128            2 :     return PutValue(cls, tag, false, tlvReader);
     129              : }
     130              : 
     131         1774 : static uint8_t ReverseBits(uint8_t v)
     132              : {
     133              :     // swap adjacent bits
     134         1774 :     v = static_cast<uint8_t>(static_cast<uint8_t>((v >> 1) & 0x55) | static_cast<uint8_t>((v & 0x55) << 1));
     135              :     // swap adjacent bit pairs
     136         1774 :     v = static_cast<uint8_t>(static_cast<uint8_t>((v >> 2) & 0x33) | static_cast<uint8_t>((v & 0x33) << 2));
     137              :     // swap nibbles
     138         1774 :     v = static_cast<uint8_t>(static_cast<uint8_t>(v >> 4) | static_cast<uint8_t>(v << 4));
     139         1774 :     return v;
     140              : }
     141              : 
     142         1771 : static uint8_t HighestBit(uint32_t v)
     143              : {
     144         1771 :     uint32_t highestBit = 0;
     145              : 
     146         1771 :     if (v > 0xFFFF)
     147              :     {
     148            0 :         highestBit = 16;
     149            0 :         v >>= 16;
     150              :     }
     151         1771 :     if (v > 0xFF)
     152              :     {
     153            0 :         highestBit |= 8;
     154            0 :         v >>= 8;
     155              :     }
     156         1771 :     if (v > 0xF)
     157              :     {
     158          893 :         highestBit |= 4;
     159          893 :         v >>= 4;
     160              :     }
     161         1771 :     if (v > 0x3)
     162              :     {
     163          890 :         highestBit |= 2;
     164          890 :         v >>= 2;
     165              :     }
     166         1771 :     highestBit |= (v >> 1);
     167              : 
     168         1771 :     return static_cast<uint8_t>(highestBit);
     169              : }
     170              : 
     171         2955 : CHIP_ERROR ASN1Writer::PutBitString(uint32_t val)
     172              : {
     173         2955 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     174              : 
     175              :     uint8_t len;
     176         1772 :     if (val == 0)
     177            1 :         len = 1;
     178         1771 :     else if (val < 256)
     179         1768 :         len = 2;
     180            3 :     else if (val < 65536)
     181            3 :         len = 3;
     182            0 :     else if (val < (1 << 24))
     183            0 :         len = 4;
     184              :     else
     185            0 :         len = 5;
     186              : 
     187         1772 :     ReturnErrorOnFailure(EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_BitString, false, len));
     188              : 
     189         1772 :     if (val == 0)
     190              :     {
     191            1 :         mWritePoint[0] = 0;
     192              :     }
     193              :     else
     194              :     {
     195         1771 :         mWritePoint[1] = ReverseBits(static_cast<uint8_t>(val));
     196         1771 :         if (len >= 3)
     197              :         {
     198            3 :             val >>= 8;
     199            3 :             mWritePoint[2] = ReverseBits(static_cast<uint8_t>(val));
     200            3 :             if (len >= 4)
     201              :             {
     202            0 :                 val >>= 8;
     203            0 :                 mWritePoint[3] = ReverseBits(static_cast<uint8_t>(val));
     204            0 :                 if (len == 5)
     205              :                 {
     206            0 :                     val >>= 8;
     207            0 :                     mWritePoint[4] = ReverseBits(static_cast<uint8_t>(val));
     208              :                 }
     209              :             }
     210              :         }
     211         1771 :         mWritePoint[0] = static_cast<uint8_t>(7 - HighestBit(val));
     212              :     }
     213              : 
     214         1772 :     mWritePoint += len;
     215              : 
     216         1772 :     return CHIP_NO_ERROR;
     217              : }
     218              : 
     219         2956 : CHIP_ERROR ASN1Writer::PutBitString(uint8_t unusedBitCount, const uint8_t * encodedBits, uint16_t encodedBitsLen)
     220              : {
     221         2956 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     222              : 
     223         1777 :     ReturnErrorOnFailure(EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_BitString, false, encodedBitsLen + 1));
     224              : 
     225         1777 :     *mWritePoint++ = unusedBitCount;
     226              : 
     227         1777 :     WriteData(encodedBits, encodedBitsLen);
     228              : 
     229         1777 :     return CHIP_NO_ERROR;
     230              : }
     231              : 
     232            2 : CHIP_ERROR ASN1Writer::PutBitString(uint8_t unusedBitCount, chip::TLV::TLVReader & tlvReader)
     233              : {
     234            2 :     ByteSpan encodedBits;
     235            2 :     ReturnErrorOnFailure(tlvReader.Get(encodedBits));
     236              : 
     237            1 :     VerifyOrReturnError(CanCastTo<int32_t>(encodedBits.size() + 1), ASN1_ERROR_LENGTH_OVERFLOW);
     238              : 
     239            1 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     240              : 
     241            1 :     ReturnErrorOnFailure(
     242              :         EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_BitString, false, static_cast<int32_t>(encodedBits.size() + 1)));
     243              : 
     244            1 :     *mWritePoint++ = unusedBitCount;
     245              : 
     246            1 :     WriteData(encodedBits.data(), encodedBits.size());
     247              : 
     248            1 :     return CHIP_NO_ERROR;
     249              : }
     250              : 
     251         6003 : CHIP_ERROR ASN1Writer::PutTime(const ASN1UniversalTime & val)
     252              : {
     253         6003 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     254              : 
     255              :     char buf[ASN1UniversalTime::kASN1TimeStringMaxLength];
     256         3612 :     MutableCharSpan bufSpan(buf);
     257              :     uint8_t tag;
     258              : 
     259         3612 :     ReturnErrorOnFailure(val.ExportTo_ASN1_TIME_string(bufSpan));
     260              : 
     261         3612 :     if (val.Year >= 2050)
     262              :     {
     263           12 :         tag = kASN1UniversalTag_GeneralizedTime;
     264              :     }
     265              :     else
     266              :     {
     267         3600 :         tag = kASN1UniversalTag_UTCTime;
     268              :     }
     269         3612 :     return PutValue(kASN1TagClass_Universal, tag, false, reinterpret_cast<uint8_t *>(buf), static_cast<uint16_t>(bufSpan.size()));
     270              : }
     271              : 
     272            0 : CHIP_ERROR ASN1Writer::PutNull()
     273              : {
     274            0 :     return EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_Null, false, 0);
     275              : }
     276              : 
     277           63 : CHIP_ERROR ASN1Writer::PutConstructedType(const uint8_t * val, uint16_t valLen)
     278              : {
     279           63 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     280              : 
     281              :     // Make sure we have enough space to write
     282           10 :     VerifyOrReturnError((mWritePoint + valLen) <= mBufEnd, ASN1_ERROR_OVERFLOW);
     283              : 
     284           10 :     WriteData(val, valLen);
     285              : 
     286           10 :     return CHIP_NO_ERROR;
     287              : }
     288              : 
     289        75254 : CHIP_ERROR ASN1Writer::StartConstructedType(uint8_t cls, uint8_t tag)
     290              : {
     291        75254 :     return EncodeHead(cls, tag, true, kUnknownLength);
     292              : }
     293              : 
     294        74849 : CHIP_ERROR ASN1Writer::EndConstructedType()
     295              : {
     296        74849 :     return WriteDeferredLength();
     297              : }
     298              : 
     299        12926 : CHIP_ERROR ASN1Writer::StartEncapsulatedType(uint8_t cls, uint8_t tag, bool bitStringEncoding)
     300              : {
     301        12926 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     302              : 
     303         8010 :     ReturnErrorOnFailure(EncodeHead(cls, tag, false, kUnknownLength));
     304              : 
     305              :     // If the encapsulating type is BIT STRING, encode the unused bit count field.  Since the BIT
     306              :     // STRING contains an ASN.1 DER encoding, and ASN.1 DER encodings are always multiples of 8 bits,
     307              :     // the unused bit count is always 0.
     308         8010 :     if (bitStringEncoding)
     309              :     {
     310           93 :         VerifyOrReturnError(mWritePoint < mBufEnd, ASN1_ERROR_OVERFLOW);
     311           93 :         *mWritePoint++ = 0;
     312              :     }
     313              : 
     314         8010 :     return CHIP_NO_ERROR;
     315              : }
     316              : 
     317        12898 : CHIP_ERROR ASN1Writer::EndEncapsulatedType()
     318              : {
     319        12898 :     return WriteDeferredLength();
     320              : }
     321              : 
     322        60924 : CHIP_ERROR ASN1Writer::PutValue(uint8_t cls, uint8_t tag, bool isConstructed, const uint8_t * val, uint16_t valLen)
     323              : {
     324        60924 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     325              : 
     326        37129 :     ReturnErrorOnFailure(EncodeHead(cls, tag, isConstructed, valLen));
     327              : 
     328        37123 :     WriteData(val, valLen);
     329              : 
     330        37123 :     return CHIP_NO_ERROR;
     331              : }
     332              : 
     333            3 : CHIP_ERROR ASN1Writer::PutValue(uint8_t cls, uint8_t tag, bool isConstructed, chip::TLV::TLVReader & tlvReader)
     334              : {
     335            3 :     ByteSpan val;
     336            3 :     ReturnErrorOnFailure(tlvReader.Get(val));
     337              : 
     338            2 :     VerifyOrReturnError(CanCastTo<int32_t>(val.size()), ASN1_ERROR_LENGTH_OVERFLOW);
     339              : 
     340            2 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     341              : 
     342            2 :     ReturnErrorOnFailure(EncodeHead(cls, tag, isConstructed, static_cast<int32_t>(val.size())));
     343              : 
     344            2 :     WriteData(val.data(), val.size());
     345              : 
     346            2 :     return CHIP_NO_ERROR;
     347              : }
     348              : 
     349       129245 : CHIP_ERROR ASN1Writer::EncodeHead(uint8_t cls, uint8_t tag, bool isConstructed, int32_t len)
     350              : {
     351       129245 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     352              : 
     353              :     uint8_t bytesForLen;
     354              :     uint32_t totalLen;
     355              : 
     356              :     // Only tags < 31 supported. The implication of this is that encoded tags are exactly 1 byte long.
     357        95658 :     VerifyOrReturnError(tag < 0x1F, ASN1_ERROR_UNSUPPORTED_ENCODING);
     358              : 
     359              :     // Only positive and kUnknownLength values are supported for len input.
     360        95658 :     VerifyOrReturnError(len >= 0 || len == kUnknownLength, ASN1_ERROR_UNSUPPORTED_ENCODING);
     361              : 
     362              :     // Compute the number of bytes required to encode the length.
     363        95658 :     bytesForLen = BytesForLength(len);
     364              : 
     365              :     // Make sure there's enough space to encode the entire value.
     366              :     // Note that the calculated total length doesn't overflow because `len` is a signed value (int32_t).
     367              :     // Note that if `len` is not kUnknownLength then it is non-negative (`len` >= 0).
     368        95658 :     totalLen = 1 + bytesForLen + static_cast<uint32_t>(len != kUnknownLength ? len : 0);
     369        95658 :     VerifyOrReturnError((mWritePoint + totalLen) <= mBufEnd, ASN1_ERROR_OVERFLOW);
     370              : 
     371              :     // Write the tag byte.
     372        95652 :     *mWritePoint++ = cls | static_cast<uint8_t>(isConstructed ? 0x20 : 0) | tag;
     373              : 
     374              :     // Encode the length if it is known.
     375        95652 :     if (len != kUnknownLength)
     376              :     {
     377        45975 :         EncodeLength(mWritePoint, bytesForLen, len);
     378              :     }
     379              :     // ... otherwise place a marker in the first byte of the length to indicate that the length is unknown
     380              :     // and save a pointer to the length field in the deferred-length array.
     381              :     //
     382              :     // The deferred-length is an array of "pointers" to length fields for which the length of the
     383              :     // element was unknown at the time the element head was written. Examples include constructed
     384              :     // types such as SEQUENCE and SET, as well non-constructed types that encapsulate other ASN.1 types
     385              :     // (e.g. OCTET STRINGS that contain BER/DER encodings). The final lengths are filled in later,
     386              :     // at the time the encoding of the element is complete (e.g. when EndConstructed() is called).
     387              :     else
     388              :     {
     389        49677 :         VerifyOrReturnError(mDeferredLengthCount < kMaxDeferredLengthDepth, ASN1_ERROR_INVALID_STATE);
     390              : 
     391        49677 :         *mWritePoint                                     = kUnknownLengthMarker;
     392        49677 :         mDeferredLengthLocations[mDeferredLengthCount++] = mWritePoint;
     393              :     }
     394              : 
     395        95652 :     mWritePoint += bytesForLen;
     396              : 
     397        95652 :     return CHIP_NO_ERROR;
     398              : }
     399              : 
     400        87747 : CHIP_ERROR ASN1Writer::WriteDeferredLength()
     401              : {
     402        87747 :     VerifyOrReturnError(!IsNullWriter(), CHIP_NO_ERROR);
     403              : 
     404        49422 :     VerifyOrReturnError(mDeferredLengthCount > 0, ASN1_ERROR_INVALID_STATE);
     405              : 
     406        49422 :     uint8_t * lenField = mDeferredLengthLocations[mDeferredLengthCount - 1];
     407              : 
     408        49422 :     VerifyOrReturnError(*lenField == kUnknownLengthMarker, ASN1_ERROR_INVALID_STATE);
     409              : 
     410              :     // Compute the length of the element's value.
     411        49422 :     size_t elemLen = static_cast<size_t>((mWritePoint - lenField) - kLengthFieldReserveSize);
     412              : 
     413        49422 :     VerifyOrReturnError(CanCastTo<int32_t>(elemLen), ASN1_ERROR_LENGTH_OVERFLOW);
     414              : 
     415        49422 :     uint8_t bytesForLen = BytesForLength(static_cast<int32_t>(elemLen));
     416              : 
     417              :     // Move the element data if the number of bytes consumed by the final length field
     418              :     // is different than the space that was reserved for the field.
     419        49422 :     if (bytesForLen != kLengthFieldReserveSize)
     420              :     {
     421         3574 :         mWritePoint += (bytesForLen - kLengthFieldReserveSize);
     422              : 
     423         3574 :         VerifyOrReturnError(mWritePoint <= mBufEnd, ASN1_ERROR_OVERFLOW);
     424              : 
     425         3574 :         memmove(lenField + bytesForLen, lenField + kLengthFieldReserveSize, elemLen);
     426              :     }
     427              : 
     428              :     // Encode the final length of the element, overwriting the unknown length marker
     429              :     // in the process.
     430        49422 :     EncodeLength(lenField, bytesForLen, static_cast<int32_t>(elemLen));
     431              : 
     432        49422 :     mDeferredLengthCount--;
     433              : 
     434        49422 :     return CHIP_NO_ERROR;
     435              : }
     436              : 
     437              : /**
     438              :  * Returns the number of bytes required to encode the length value.
     439              :  *
     440              :  * @param[in]   len     Parameter, which encoding length to be calculated.
     441              :  *
     442              :  * @return number of bytes required to encode the length value.
     443              :  */
     444       145080 : uint8_t ASN1Writer::BytesForLength(int32_t len)
     445              : {
     446       145080 :     if (len == kUnknownLength)
     447        49677 :         return kLengthFieldReserveSize;
     448        95403 :     if (len < 128)
     449        91829 :         return 1;
     450         3574 :     if (len < 256)
     451         1734 :         return 2;
     452         1840 :     if (len < 65536)
     453         1840 :         return 3;
     454            0 :     if (len < (1 << 24))
     455            0 :         return 4;
     456            0 :     return 5;
     457              : }
     458              : 
     459        95397 : void ASN1Writer::EncodeLength(uint8_t * buf, uint8_t bytesForLen, int32_t lenToEncode)
     460              : {
     461        95397 :     if (bytesForLen == 1)
     462              :     {
     463        91823 :         buf[0] = static_cast<uint8_t>(lenToEncode);
     464              :     }
     465              :     else
     466              :     {
     467         3574 :         --bytesForLen;
     468         3574 :         buf[0] = 0x80 | bytesForLen;
     469              :         do
     470              :         {
     471         5414 :             buf[bytesForLen] = static_cast<uint8_t>(lenToEncode);
     472         5414 :             lenToEncode >>= 8;
     473         5414 :         } while (--bytesForLen);
     474              :     }
     475        95397 : }
     476              : 
     477        38913 : void ASN1Writer::WriteData(const uint8_t * p, size_t len)
     478              : {
     479        38913 :     memcpy(mWritePoint, p, len);
     480        38913 :     mWritePoint += len;
     481        38913 : }
     482              : 
     483              : } // namespace ASN1
     484              : } // namespace chip
        

Generated by: LCOV version 2.0-1