3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2013-2017 Nest Labs, Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * This file implements an object for writing Abstract Syntax
23 * Notation One (ASN.1) encoded data.
27 #ifndef __STDC_LIMIT_MACROS
28 #define __STDC_LIMIT_MACROS
36 #include <asn1/ASN1.h>
37 #include <core/CHIPCore.h>
38 #include <core/CHIPEncoding.h>
39 #include <core/CHIPTLV.h>
40 #include <support/CodeUtils.h>
45 using namespace chip::Encoding;
49 kLengthFieldReserveSize = 5,
50 kMaxElementLength = INT32_MAX,
52 kUnknownLengthMarker = 0xFF
55 void ASN1Writer::Init(uint8_t * buf, uint32_t maxLen)
59 mBufEnd = buf + maxLen;
60 mBufEnd = reinterpret_cast<uint8_t *>(reinterpret_cast<uintptr_t>(mBufEnd) & ~3); // align on 32bit boundary
61 mDeferredLengthList = reinterpret_cast<uint8_t **>(mBufEnd);
64 void ASN1Writer::InitNullWriter(void)
67 mWritePoint = nullptr;
69 mDeferredLengthList = nullptr;
72 ASN1_ERROR ASN1Writer::Finalize()
76 uint8_t * compactPoint = mBuf;
77 uint8_t * spanStart = mBuf;
79 for (uint8_t ** listEntry = reinterpret_cast<uint8_t **>(mBufEnd); listEntry > mDeferredLengthList;)
81 uint8_t * lenField = *--listEntry;
82 uint8_t lenFieldFirstByte = *lenField;
84 if (lenFieldFirstByte == kUnknownLengthMarker)
85 return ASN1_ERROR_INVALID_STATE;
87 uint8_t lenOfLen = (lenFieldFirstByte < 128) ? 1 : (lenFieldFirstByte & 0x7f) + 1;
89 uint8_t * spanEnd = lenField + lenOfLen;
91 if (spanStart == compactPoint)
92 compactPoint = spanEnd;
95 uint32_t spanLen = spanEnd - spanStart;
96 memmove(compactPoint, spanStart, spanLen);
97 compactPoint += spanLen;
100 spanStart = lenField + kLengthFieldReserveSize;
103 if (spanStart > compactPoint)
105 uint32_t spanLen = mWritePoint - spanStart;
106 memmove(compactPoint, spanStart, spanLen);
107 compactPoint += spanLen;
110 mWritePoint = compactPoint;
113 return ASN1_NO_ERROR;
116 uint16_t ASN1Writer::GetLengthWritten() const
118 return (mBuf != nullptr) ? mWritePoint - mBuf : 0;
121 ASN1_ERROR ASN1Writer::PutInteger(int64_t val)
123 uint8_t encodedVal[8];
124 uint8_t valStart, valLen;
126 BigEndian::Put64(encodedVal, static_cast<uint64_t>(val));
128 for (valStart = 0; valStart < 7; valStart++)
130 if (encodedVal[valStart] == 0x00 && (encodedVal[valStart + 1] & 0x80) == 0)
132 if (encodedVal[valStart] == 0xFF && (encodedVal[valStart + 1] & 0x80) == 0x80)
136 valLen = 8 - valStart;
138 return PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, encodedVal + valStart, valLen);
141 ASN1_ERROR ASN1Writer::PutBoolean(bool val)
143 // Do nothing for a null writer.
144 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
146 ReturnErrorOnFailure(EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_Boolean, false, 1));
148 *mWritePoint++ = (val) ? 0xFF : 0;
150 return ASN1_NO_ERROR;
153 ASN1_ERROR ASN1Writer::PutObjectId(const uint8_t * val, uint16_t valLen)
155 return PutValue(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId, false, val, valLen);
158 ASN1_ERROR ASN1Writer::PutString(uint32_t tag, const char * val, uint16_t valLen)
160 return PutValue(kASN1TagClass_Universal, tag, false, (const uint8_t *) val, valLen);
163 ASN1_ERROR ASN1Writer::PutOctetString(const uint8_t * val, uint16_t valLen)
165 return PutValue(kASN1TagClass_Universal, kASN1UniversalTag_OctetString, false, val, valLen);
168 ASN1_ERROR ASN1Writer::PutOctetString(uint8_t cls, uint32_t tag, const uint8_t * val, uint16_t valLen)
170 return PutValue(cls, tag, false, val, valLen);
173 ASN1_ERROR ASN1Writer::PutOctetString(uint8_t cls, uint32_t tag, chip::TLV::TLVReader & val)
175 return PutValue(cls, tag, false, val);
178 static uint8_t ReverseBits(uint8_t v)
180 // swap adjacent bits
181 v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
182 // swap adjacent bit pairs
183 v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
185 v = (v >> 4) | (v << 4);
189 static uint8_t HighestBit(uint32_t v)
191 uint32_t highestBit = 0;
213 highestBit |= (v >> 1);
218 ASN1_ERROR ASN1Writer::PutBitString(uint32_t val)
222 // Do nothing for a null writer.
223 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
229 else if (val < 65536)
231 else if (val < (1 << 24))
236 ReturnErrorOnFailure(EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_BitString, false, len));
242 mWritePoint[1] = ReverseBits(static_cast<uint8_t>(val));
246 mWritePoint[2] = ReverseBits(static_cast<uint8_t>(val));
250 mWritePoint[3] = ReverseBits(static_cast<uint8_t>(val));
254 mWritePoint[4] = ReverseBits(static_cast<uint8_t>(val));
258 mWritePoint[0] = 7 - HighestBit(val);
263 return ASN1_NO_ERROR;
266 ASN1_ERROR ASN1Writer::PutBitString(uint8_t unusedBitCount, const uint8_t * encodedBits, uint16_t encodedBitsLen)
268 // Do nothing for a null writer.
269 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
271 ReturnErrorOnFailure(EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_BitString, false, encodedBitsLen + 1));
273 *mWritePoint++ = unusedBitCount;
275 memcpy(mWritePoint, encodedBits, encodedBitsLen);
276 mWritePoint += encodedBitsLen;
278 return ASN1_NO_ERROR;
281 ASN1_ERROR ASN1Writer::PutBitString(uint8_t unusedBitCount, chip::TLV::TLVReader & encodedBits)
283 uint32_t encodedBitsLen;
285 // Do nothing for a null writer.
286 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
288 encodedBitsLen = encodedBits.GetLength();
290 ReturnErrorOnFailure(EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_BitString, false, encodedBitsLen + 1));
292 *mWritePoint++ = unusedBitCount;
294 encodedBits.GetBytes(mWritePoint, encodedBitsLen);
295 mWritePoint += encodedBitsLen;
297 return ASN1_NO_ERROR;
300 static void itoa2(uint32_t val, uint8_t * buf)
302 buf[1] = '0' + (val % 10);
304 buf[0] = '0' + (val % 10);
307 ASN1_ERROR ASN1Writer::PutTime(const ASN1UniversalTime & val)
311 itoa2(val.Year / 100, buf);
312 itoa2(val.Year, buf + 2);
313 itoa2(val.Month, buf + 4);
314 itoa2(val.Day, buf + 6);
315 itoa2(val.Hour, buf + 8);
316 itoa2(val.Minute, buf + 10);
317 itoa2(val.Second, buf + 12);
320 // X.509/RFC5280 mandates that times before 2050 UTC must be encoded as ASN.1 UTCTime values, while
321 // times equal or greater than 2050 must be encoded as GeneralizedTime values. The only difference
322 // (in the context of X.509 DER) is that GeneralizedTimes are encoded with a 4 digit year, while
323 // UTCTimes are encoded with a two-digit year.
325 if (val.Year >= 2050)
326 return PutValue(kASN1TagClass_Universal, kASN1UniversalTag_GeneralizedTime, false, buf, 15);
328 return PutValue(kASN1TagClass_Universal, kASN1UniversalTag_UTCTime, false, buf + 2, 13);
331 ASN1_ERROR ASN1Writer::PutNull()
333 return EncodeHead(kASN1TagClass_Universal, kASN1UniversalTag_Null, false, 0);
336 ASN1_ERROR ASN1Writer::StartConstructedType(uint8_t cls, uint32_t tag)
338 return EncodeHead(cls, tag, true, kUnkownLength);
341 ASN1_ERROR ASN1Writer::EndConstructedType()
343 return WriteDeferredLength();
346 ASN1_ERROR ASN1Writer::StartEncapsulatedType(uint8_t cls, uint32_t tag, bool bitStringEncoding)
348 // Do nothing for a null writer.
349 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
351 ReturnErrorOnFailure(EncodeHead(cls, tag, false, kUnkownLength));
353 // If the encapsulating type is BIT STRING, encode the unused bit count field. Since the BIT
354 // STRING contains an ASN.1 DER encoding, and ASN.1 DER encodings are always multiples of 8 bits,
355 // the unused bit count is always 0.
356 if (bitStringEncoding)
358 if (mWritePoint == reinterpret_cast<uint8_t *>(mDeferredLengthList))
359 return ASN1_ERROR_OVERFLOW;
363 return ASN1_NO_ERROR;
366 ASN1_ERROR ASN1Writer::EndEncapsulatedType()
368 return WriteDeferredLength();
371 ASN1_ERROR ASN1Writer::PutValue(uint8_t cls, uint32_t tag, bool isConstructed, const uint8_t * val, uint16_t valLen)
373 // Do nothing for a null writer.
374 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
376 ReturnErrorOnFailure(EncodeHead(cls, tag, isConstructed, valLen));
378 memcpy(mWritePoint, val, valLen);
379 mWritePoint += valLen;
381 return ASN1_NO_ERROR;
384 ASN1_ERROR ASN1Writer::PutValue(uint8_t cls, uint32_t tag, bool isConstructed, chip::TLV::TLVReader & val)
388 // Do nothing for a null writer.
389 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
391 valLen = val.GetLength();
393 ReturnErrorOnFailure(EncodeHead(cls, tag, isConstructed, valLen));
395 val.GetBytes(mWritePoint, valLen);
396 mWritePoint += valLen;
398 return ASN1_NO_ERROR;
401 ASN1_ERROR ASN1Writer::EncodeHead(uint8_t cls, uint32_t tag, bool isConstructed, int32_t len)
406 // Do nothing for a null writer.
407 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
409 // Only tags <= 31 supported. The implication of this is that encoded tags are exactly 1 byte long.
410 VerifyOrReturnError(tag <= 0x1F, ASN1_ERROR_UNSUPPORTED_ENCODING);
412 // Only positive and kUnkownLength values are supported for len input.
413 VerifyOrReturnError(len >= 0 || len == kUnkownLength, ASN1_ERROR_UNSUPPORTED_ENCODING);
415 // Compute the number of bytes required to encode the length.
416 bytesForLen = BytesForLength(len);
418 // If the element length is unknown, allocate a new entry in the deferred-length list.
420 // The deferred-length list is a list of "pointers" (represented as offsets into mBuf)
421 // to length fields for which the length of the element was unknown at the time the element
422 // head was written. Examples include constructed types such as SEQUENCE and SET, as well
423 // non-constructed types that encapsulate other ASN.1 types (e.g. OCTET STRINGS that contain
424 // BER/DER encodings). The final lengths are filled in later, at the time the encoding is
425 // complete (e.g. when EndConstructed() is called).
427 if (len == kUnkownLength)
428 mDeferredLengthList--;
430 // Make sure there's enough space to encode the entire value without bumping into the deferred length
431 // list at the end of the buffer.
432 totalLen = 1 + bytesForLen + (len != kUnkownLength ? len : 0);
433 VerifyOrReturnError((mWritePoint + totalLen) <= reinterpret_cast<uint8_t *>(mDeferredLengthList), ASN1_ERROR_OVERFLOW);
435 // Write the tag byte.
436 *mWritePoint++ = cls | (isConstructed ? 0x20 : 0) | tag;
438 // Encode the length if it is known.
439 if (len != kUnkownLength)
440 EncodeLength(mWritePoint, bytesForLen, len);
442 // ... otherwise place a marker in the first byte of the length to indicate that the length is unknown
443 // and save a pointer to the length field in the deferred-length list.
446 *mWritePoint = kUnknownLengthMarker;
447 *mDeferredLengthList = mWritePoint;
450 mWritePoint += bytesForLen;
452 return ASN1_NO_ERROR;
455 ASN1_ERROR ASN1Writer::WriteDeferredLength()
457 uint8_t ** listEntry;
460 // Do nothing for a null writer.
461 VerifyOrReturnError(mBuf != nullptr, ASN1_NO_ERROR);
463 lenAdj = kLengthFieldReserveSize;
465 // Scan the deferred-length list in reverse order looking for the most recent entry where
466 // the length is still unknown. This entry represents the "container" element whose encoding
468 for (listEntry = mDeferredLengthList; listEntry < reinterpret_cast<uint8_t **>(mBufEnd); listEntry++)
470 // Get a pointer to the deferred-length field.
471 uint8_t * lenField = *listEntry;
473 // Get the first byte of the length field.
474 uint8_t lenFieldFirstByte = *lenField;
476 // If the length is marked as unknown...
477 if (lenFieldFirstByte == kUnknownLengthMarker)
479 // Compute the final length of the element's value (3 = bytes reserved for length).
480 uint32_t elemLen = (mWritePoint - lenField) - lenAdj;
482 // Return an error if the length exceeds the maximum value that can be encoded in the
483 // space reserved for the length.
484 VerifyOrReturnError(elemLen <= kMaxElementLength, ASN1_ERROR_LENGTH_OVERFLOW);
486 // Encode the final length of the element, overwriting the unknown length marker
487 // in the process. Note that the number of bytes consumed by the final length field
488 // may be smaller than the space that was reserved for the field. This will be fixed
489 // up when the Finalize() method is called.
490 uint8_t bytesForLen = BytesForLength(static_cast<int32_t>(elemLen));
491 EncodeLength(lenField, bytesForLen, elemLen);
493 return ASN1_NO_ERROR;
497 uint8_t bytesForLen = (lenFieldFirstByte < 128) ? 1 : (lenFieldFirstByte & 0x7f) + 1;
498 lenAdj += (kLengthFieldReserveSize - bytesForLen);
502 return ASN1_ERROR_INVALID_STATE;
506 * Returns the number of bytes required to encode the length value.
508 * @param[in] len Parameter, which encoding length to be calculated.
510 * @return number of bytes required to encode the length value.
512 uint8_t ASN1Writer::BytesForLength(int32_t len)
514 if (len == kUnkownLength)
515 return kLengthFieldReserveSize;
527 void ASN1Writer::EncodeLength(uint8_t * buf, uint8_t bytesForLen, int32_t lenToEncode)
529 if (bytesForLen == 1)
530 buf[0] = static_cast<uint8_t>(lenToEncode);
534 buf[0] = 0x80 | bytesForLen;
537 buf[bytesForLen] = static_cast<uint8_t>(lenToEncode);
539 } while (--bytesForLen);