forked from project-chip/connectedhomeip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathASN1.h
272 lines (236 loc) · 8.95 KB
/
ASN1.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
/*
*
* Copyright (c) 2020-2022 Project CHIP Authors
* Copyright (c) 2013-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file defines types and objects for reading and writing
* Abstract Syntax Notation One (ASN.1) encoded data.
*
*/
#pragma once
#ifndef DOXYGEN_SHOULD_SKIP_THIS
#include <asn1/ASN1OID.h>
#endif
#include <lib/asn1/ASN1Error.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/Span.h>
namespace chip {
namespace TLV {
class TLVReader;
}
} // namespace chip
/**
* @namespace chip::ASN1
*
* @brief
* This namespace includes all interfaces within CHIP for
* working with Abstract Syntax Notation One (ASN.1).
*/
namespace chip {
namespace ASN1 {
static constexpr size_t kMaxConstructedAndEncapsulatedTypesDepth = 10;
enum ASN1TagClasses
{
kASN1TagClass_Universal = 0x00,
kASN1TagClass_Application = 0x40,
kASN1TagClass_ContextSpecific = 0x80,
kASN1TagClass_Private = 0xC0
};
enum ASN1UniversalTags : uint8_t
{
kASN1UniversalTag_Boolean = 1,
kASN1UniversalTag_Integer = 2,
kASN1UniversalTag_BitString = 3,
kASN1UniversalTag_OctetString = 4,
kASN1UniversalTag_Null = 5,
kASN1UniversalTag_ObjectId = 6,
kASN1UniversalTag_ObjectDesc = 7,
kASN1UniversalTag_External = 8,
kASN1UniversalTag_Real = 9,
kASN1UniversalTag_Enumerated = 10,
kASN1UniversalTag_UTF8String = 12,
kASN1UniversalTag_Sequence = 16,
kASN1UniversalTag_Set = 17,
kASN1UniversalTag_NumericString = 18,
kASN1UniversalTag_PrintableString = 19,
kASN1UniversalTag_T61String = 20,
kASN1UniversalTag_VideotexString = 21,
kASN1UniversalTag_IA5String = 22,
kASN1UniversalTag_UTCTime = 23,
kASN1UniversalTag_GeneralizedTime = 24,
kASN1UniversalTag_GraphicString = 25,
kASN1UniversalTag_VisibleString = 26,
kASN1UniversalTag_GeneralString = 27,
kASN1UniversalTag_UniversalString = 28
};
/**
* @struct ASN1UniversalTime
*
* @brief
* A data structure representing ASN1 universal time in a calendar format.
*/
struct ASN1UniversalTime
{
uint16_t Year; /**< Year component. Legal interval is 0..9999. */
uint8_t Month; /**< Month component. Legal interval is 1..12. */
uint8_t Day; /**< Day of month component. Legal interval is 1..31. */
uint8_t Hour; /**< Hour component. Legal interval is 0..23. */
uint8_t Minute; /**< Minute component. Legal interval is 0..59. */
uint8_t Second; /**< Second component. Legal interval is 0..59. */
static constexpr size_t kASN1UTCTimeStringLength = 13;
static constexpr size_t kASN1GeneralizedTimeStringLength = 15;
static constexpr size_t kASN1TimeStringMaxLength = 15;
/**
* @brief Set time from ASN1_TIME string.
* Two string formats are supported:
* YYMMDDHHMMSSZ - for years in the range 1950 - 2049
* YYYYMMDDHHMMSSZ - other years
**/
CHIP_ERROR ImportFrom_ASN1_TIME_string(const CharSpan & asn1_time);
/**
* @brief Encode time as an ASN1_TIME string.
* Two string formats are supported:
* YYMMDDHHMMSSZ - for years in the range 1950 - 2049
* YYYYMMDDHHMMSSZ - other years
**/
CHIP_ERROR ExportTo_ASN1_TIME_string(MutableCharSpan & asn1_time) const;
/**
* @brief Encode time as Unix epoch time.
**/
bool ExportTo_UnixTime(uint32_t & unixEpoch);
};
class DLL_EXPORT ASN1Reader
{
public:
void Init(const uint8_t * buf, size_t len);
void Init(const ByteSpan & data) { Init(data.data(), data.size()); }
template <size_t N>
void Init(const uint8_t (&data)[N])
{
Init(data, N);
}
uint8_t GetClass(void) const { return Class; };
uint8_t GetTag(void) const { return Tag; };
const uint8_t * GetValue(void) const { return Value; };
uint32_t GetValueLen(void) const { return ValueLen; };
bool IsConstructed(void) const { return Constructed; };
bool IsIndefiniteLen(void) const { return IndefiniteLen; };
bool IsEndOfContents(void) const { return EndOfContents; };
CHIP_ERROR Next(void);
CHIP_ERROR EnterConstructedType(void);
CHIP_ERROR ExitConstructedType(void);
CHIP_ERROR GetConstructedType(const uint8_t *& val, uint32_t & valLen);
CHIP_ERROR EnterEncapsulatedType(void);
CHIP_ERROR ExitEncapsulatedType(void);
bool IsContained(void) const;
CHIP_ERROR GetInteger(int64_t & val);
CHIP_ERROR GetBoolean(bool & val);
CHIP_ERROR GetObjectId(OID & oid);
CHIP_ERROR GetUTCTime(ASN1UniversalTime & outTime);
CHIP_ERROR GetGeneralizedTime(ASN1UniversalTime & outTime);
CHIP_ERROR GetBitString(uint32_t & outVal);
private:
static constexpr size_t kMaxContextDepth = kMaxConstructedAndEncapsulatedTypesDepth;
struct ASN1ParseContext
{
const uint8_t * ElemStart;
uint32_t HeadLen;
uint32_t ValueLen;
bool IndefiniteLen;
const uint8_t * ContainerEnd;
};
uint8_t Class;
uint8_t Tag;
const uint8_t * Value;
uint32_t ValueLen;
bool Constructed;
bool IndefiniteLen;
bool EndOfContents;
const uint8_t * mBuf;
const uint8_t * mBufEnd;
const uint8_t * mElemStart;
const uint8_t * mContainerEnd;
uint32_t mHeadLen;
ASN1ParseContext mSavedContexts[kMaxContextDepth];
uint32_t mNumSavedContexts;
CHIP_ERROR DecodeHead(void);
void ResetElementState(void);
CHIP_ERROR EnterContainer(uint32_t offset);
CHIP_ERROR ExitContainer(void);
};
class DLL_EXPORT ASN1Writer
{
public:
void Init(uint8_t * buf, size_t maxLen);
void Init(const MutableByteSpan & data) { Init(data.data(), data.size()); }
template <size_t N>
void Init(uint8_t (&data)[N])
{
Init(data, N);
}
void InitNullWriter(void);
size_t GetLengthWritten(void) const;
bool IsNullWriter() const { return mBuf == nullptr; }
CHIP_ERROR PutInteger(int64_t val);
CHIP_ERROR PutBoolean(bool val);
CHIP_ERROR PutObjectId(const uint8_t * val, uint16_t valLen);
CHIP_ERROR PutObjectId(OID oid);
CHIP_ERROR PutString(uint8_t tag, const char * val, uint16_t valLen);
CHIP_ERROR PutOctetString(const uint8_t * val, uint16_t valLen);
CHIP_ERROR PutOctetString(uint8_t cls, uint8_t tag, const uint8_t * val, uint16_t valLen);
CHIP_ERROR PutOctetString(uint8_t cls, uint8_t tag, chip::TLV::TLVReader & tlvReader);
CHIP_ERROR PutBitString(uint32_t val);
CHIP_ERROR PutBitString(uint8_t unusedBits, const uint8_t * val, uint16_t valLen);
CHIP_ERROR PutBitString(uint8_t unusedBits, chip::TLV::TLVReader & tlvReader);
CHIP_ERROR PutTime(const ASN1UniversalTime & val);
CHIP_ERROR PutNull(void);
CHIP_ERROR PutConstructedType(const uint8_t * val, uint16_t valLen);
CHIP_ERROR StartConstructedType(uint8_t cls, uint8_t tag);
CHIP_ERROR EndConstructedType(void);
CHIP_ERROR StartEncapsulatedType(uint8_t cls, uint8_t tag, bool bitStringEncoding);
CHIP_ERROR EndEncapsulatedType(void);
CHIP_ERROR PutValue(uint8_t cls, uint8_t tag, bool isConstructed, const uint8_t * val, uint16_t valLen);
CHIP_ERROR PutValue(uint8_t cls, uint8_t tag, bool isConstructed, chip::TLV::TLVReader & tlvReader);
private:
static constexpr size_t kMaxDeferredLengthDepth = kMaxConstructedAndEncapsulatedTypesDepth;
uint8_t * mBuf;
uint8_t * mBufEnd;
uint8_t * mWritePoint;
uint8_t * mDeferredLengthLocations[kMaxDeferredLengthDepth];
uint8_t mDeferredLengthCount;
CHIP_ERROR EncodeHead(uint8_t cls, uint8_t tag, bool isConstructed, int32_t len);
CHIP_ERROR WriteDeferredLength(void);
static uint8_t BytesForLength(int32_t len);
static void EncodeLength(uint8_t * buf, uint8_t bytesForLen, int32_t lenToEncode);
void WriteData(const uint8_t * p, size_t len);
};
OID ParseObjectID(const uint8_t * encodedOID, uint16_t encodedOIDLen);
bool GetEncodedObjectID(OID oid, const uint8_t *& encodedOID, uint16_t & encodedOIDLen);
OIDCategory GetOIDCategory(OID oid);
const char * GetOIDName(OID oid);
CHIP_ERROR DumpASN1(ASN1Reader & reader, const char * prefix, const char * indent);
inline OID GetOID(OIDCategory category, uint8_t id)
{
return static_cast<OID>(category | id);
}
inline uint8_t GetOIDEnum(OID oid)
{
return static_cast<uint8_t>(oid & kOID_EnumMask);
}
} // namespace ASN1
} // namespace chip