3 * Copyright (c) 2020 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 defines convenience macros for dealing with Abstract
23 * Syntax Notation One (ASN.1) encoded data.
29 #include <support/CodeUtils.h>
31 // Local variable names used by utility macros.
33 #define ASN1_READER reader
36 // Utility Macros for parsing ASN1
38 #define ASN1_VERIFY_TAG(CLASS, TAG) \
39 VerifyOrExit(ASN1_READER.GetClass() == (CLASS) && ASN1_READER.GetTag() == (TAG), ASN1_ERR = ASN1_ERROR_INVALID_ENCODING);
41 #define ASN1_PARSE_ELEMENT(CLASS, TAG) \
44 ASN1_ERR = ASN1_READER.Next(); \
45 SuccessOrExit(ASN1_ERR); \
47 ASN1_VERIFY_TAG(CLASS, TAG); \
50 #define ASN1_PARSE_ANY \
53 ASN1_ERR = ASN1_READER.Next(); \
54 SuccessOrExit(ASN1_ERR); \
57 #define ASN1_ENTER_CONSTRUCTED(CLASS, TAG) \
60 ASN1_VERIFY_TAG(CLASS, TAG); \
62 ASN1_ERR = ASN1_READER.EnterConstructedType(); \
63 SuccessOrExit(ASN1_ERR);
65 #define ASN1_PARSE_ENTER_CONSTRUCTED(CLASS, TAG) \
68 ASN1_ERR = ASN1_READER.Next(); \
69 SuccessOrExit(ASN1_ERR); \
71 ASN1_VERIFY_TAG(CLASS, TAG); \
73 ASN1_ERR = ASN1_READER.EnterConstructedType(); \
74 SuccessOrExit(ASN1_ERR);
76 #define ASN1_EXIT_CONSTRUCTED \
77 ASN1_ERR = ASN1_READER.Next(); \
78 if (ASN1_ERR == ASN1_NO_ERROR) \
79 ASN1_ERR = ASN1_ERROR_INVALID_ENCODING; \
80 else if (ASN1_ERR == ASN1_END) \
81 ASN1_ERR = ASN1_NO_ERROR; \
82 SuccessOrExit(ASN1_ERR); \
84 ASN1_ERR = ASN1_READER.ExitConstructedType(); \
85 SuccessOrExit(ASN1_ERR); \
89 #define ASN1_PARSE_ENTER_SEQUENCE ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Sequence)
91 #define ASN1_ENTER_SEQUENCE ASN1_ENTER_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Sequence)
93 #define ASN1_EXIT_SEQUENCE ASN1_EXIT_CONSTRUCTED
95 #define ASN1_PARSE_ENTER_SET ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Set)
97 #define ASN1_ENTER_SET ASN1_ENTER_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Set)
99 #define ASN1_EXIT_SET ASN1_EXIT_CONSTRUCTED
101 #define ASN1_ENTER_ENCAPSULATED(CLASS, TAG) \
104 ASN1_VERIFY_TAG(CLASS, TAG); \
106 ASN1_ERR = ASN1_READER.EnterEncapsulatedType(); \
107 SuccessOrExit(ASN1_ERR);
109 #define ASN1_PARSE_ENTER_ENCAPSULATED(CLASS, TAG) \
112 ASN1_ERR = ASN1_READER.Next(); \
113 SuccessOrExit(ASN1_ERR); \
115 ASN1_VERIFY_TAG(CLASS, TAG); \
117 ASN1_ERR = ASN1_READER.EnterEncapsulatedType(); \
118 SuccessOrExit(ASN1_ERR);
120 #define ASN1_EXIT_ENCAPSULATED \
121 ASN1_ERR = ASN1_READER.Next(); \
122 if (ASN1_ERR == ASN1_NO_ERROR) \
123 ASN1_ERR = ASN1_ERROR_INVALID_ENCODING; \
124 else if (ASN1_ERR == ASN1_END) \
125 ASN1_ERR = ASN1_NO_ERROR; \
126 SuccessOrExit(ASN1_ERR); \
128 ASN1_ERR = ASN1_READER.ExitEncapsulatedType(); \
129 SuccessOrExit(ASN1_ERR); \
133 #define ASN1_PARSE_INTEGER(OUT_VAL) \
136 ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer); \
138 ASN1_ERR = ASN1_READER.GetInteger(OUT_VAL); \
139 SuccessOrExit(ASN1_ERR); \
142 #define ASN1_GET_INTEGER(OUT_VAL) \
145 ASN1_ERR = ASN1_READER.GetInteger(OUT_VAL); \
146 SuccessOrExit(ASN1_ERR); \
149 #define ASN1_PARSE_BOOLEAN(OUT_VAL) \
152 ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Boolean); \
154 ASN1_ERR = ASN1_READER.GetBoolean(OUT_VAL); \
155 SuccessOrExit(ASN1_ERR); \
158 #define ASN1_GET_BOOLEAN(OUT_VAL) \
161 ASN1_ERR = ASN1_READER.GetBoolean(OUT_VAL); \
162 SuccessOrExit(ASN1_ERR); \
165 #define ASN1_PARSE_OBJECT_ID(OUT_VAL) \
168 ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId); \
170 ASN1_ERR = ASN1_READER.GetObjectId(OUT_VAL); \
171 SuccessOrExit(ASN1_ERR); \
174 #define ASN1_GET_OBJECT_ID(OUT_VAL) \
177 ASN1_ERR = ASN1_READER.GetObjectId(OUT_VAL); \
178 SuccessOrExit(ASN1_ERR); \
181 #define ASN1_PARSE_NULL ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Null)
183 #define ASN1_PARSE_TIME(OUT_VAL) \
188 if (ASN1_READER.GetClass() == kASN1TagClass_Universal && ASN1_READER.GetTag() == kASN1UniversalTag_UTCTime) \
189 ASN1_ERR = ASN1_READER.GetUTCTime(OUT_VAL); \
190 else if (ASN1_READER.GetClass() == kASN1TagClass_Universal && ASN1_READER.GetTag() == kASN1UniversalTag_GeneralizedTime) \
191 ASN1_ERR = ASN1_READER.GetGeneralizedTime(OUT_VAL); \
193 ASN1_ERR = ASN1_ERROR_INVALID_ENCODING; \
194 SuccessOrExit(ASN1_ERR); \
197 #define ASN1_PARSE_BIT_STRING(OUT_VAL) \
200 ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString); \
202 ASN1_ERR = ASN1_READER.GetBitString(OUT_VAL); \
203 SuccessOrExit(ASN1_ERR); \
206 #define ASN1_GET_BIT_STRING(OUT_VAL) \
209 ASN1_ERR = ASN1_READER.GetBitString(OUT_VAL); \
210 SuccessOrExit(ASN1_ERR); \
213 // Utility Macros for encoding ASN1
215 #define ASN1_START_CONSTRUCTED(CLASS, TAG) \
218 ASN1_ERR = writer.StartConstructedType(CLASS, TAG); \
219 SuccessOrExit(ASN1_ERR);
221 #define ASN1_END_CONSTRUCTED \
222 ASN1_ERR = writer.EndConstructedType(); \
223 SuccessOrExit(ASN1_ERR); \
227 #define ASN1_START_SEQUENCE ASN1_START_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Sequence)
229 #define ASN1_END_SEQUENCE ASN1_END_CONSTRUCTED
231 #define ASN1_START_SET ASN1_START_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Set)
233 #define ASN1_END_SET ASN1_END_CONSTRUCTED
235 #define ASN1_ENCODE_INTEGER(VAL) \
238 ASN1_ERR = writer.PutInteger(VAL); \
239 SuccessOrExit(ASN1_ERR); \
242 #define ASN1_ENCODE_BOOLEAN(VAL) \
245 ASN1_ERR = writer.PutBoolean(VAL); \
246 SuccessOrExit(ASN1_ERR); \
249 #define ASN1_ENCODE_BIT_STRING(VAL) \
252 ASN1_ERR = writer.PutBitString(VAL); \
253 SuccessOrExit(ASN1_ERR); \
256 #define ASN1_ENCODE_OBJECT_ID(OID) \
259 ASN1_ERR = writer.PutObjectId(OID); \
260 SuccessOrExit(ASN1_ERR); \
263 #define ASN1_ENCODE_STRING(TAG, VAL, LEN) \
266 ASN1_ERR = writer.PutString(TAG, VAL, LEN); \
267 SuccessOrExit(ASN1_ERR); \
270 #define ASN1_ENCODE_OCTET_STRING(VAL, LEN) \
273 ASN1_ERR = writer.PutOctetString(VAL, LEN); \
274 SuccessOrExit(ASN1_ERR); \
277 #define ASN1_ENCODE_TIME(VAL) \
280 ASN1_ERR = writer.PutTime(VAL); \
281 SuccessOrExit(ASN1_ERR); \
284 #define ASN1_ENCODE_NULL \
287 ASN1_ERR = writer.PutNull(); \
288 SuccessOrExit(ASN1_ERR); \
291 #define ASN1_START_ENCAPSULATED(CLASS, TAG, BIT_STRING_ENCODING) \
294 ASN1_ERR = writer.StartEncapsulatedType(CLASS, TAG, BIT_STRING_ENCODING); \
295 SuccessOrExit(ASN1_ERR);
297 #define ASN1_START_OCTET_STRING_ENCAPSULATED ASN1_START_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_OctetString, false)
299 #define ASN1_START_BIT_STRING_ENCAPSULATED ASN1_START_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_BitString, true)
301 #define ASN1_END_ENCAPSULATED \
302 ASN1_ERR = writer.EndEncapsulatedType(); \
303 SuccessOrExit(ASN1_ERR); \