LCOV - code coverage report
Current view: top level - lib/asn1 - ASN1Writer.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 182 199 91.5 %
Date: 2024-02-15 08:20:41 Functions: 28 29 96.6 %

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

Generated by: LCOV version 1.14