| /* |
| * |
| * 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 convenience macros for dealing with Abstract |
| * Syntax Notation One (ASN.1) encoded data. |
| * |
| */ |
| |
| #ifndef ASN1MACROS_H_ |
| #define ASN1MACROS_H_ |
| |
| // Local variable names used by utility macros. |
| // |
| // Re-define these to use different names. |
| |
| #define ASN1_READER reader |
| #define ASN1_ERR err |
| |
| |
| // Utility Macros for parsing ASN1 |
| |
| #define ASN1_VERIFY_TAG(CLASS, TAG) \ |
| VerifyOrExit(ASN1_READER.Class == (CLASS) && ASN1_READER.Tag == (TAG), ASN1_ERR = ASN1_ERROR_INVALID_ENCODING); |
| |
| #define ASN1_PARSE_ELEMENT(CLASS, TAG) \ |
| do { \ |
| ASN1_ERR = ASN1_READER.Next(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| \ |
| ASN1_VERIFY_TAG(CLASS, TAG); \ |
| } while (0) |
| |
| #define ASN1_PARSE_ANY \ |
| do { \ |
| ASN1_ERR = ASN1_READER.Next(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_ENTER_CONSTRUCTED(CLASS, TAG) \ |
| do { \ |
| ASN1_VERIFY_TAG(CLASS, TAG); \ |
| \ |
| ASN1_ERR = ASN1_READER.EnterConstructedType(); \ |
| SuccessOrExit(ASN1_ERR); |
| |
| #define ASN1_PARSE_ENTER_CONSTRUCTED(CLASS, TAG) \ |
| do { \ |
| ASN1_ERR = ASN1_READER.Next(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| \ |
| ASN1_VERIFY_TAG(CLASS, TAG); \ |
| \ |
| ASN1_ERR = ASN1_READER.EnterConstructedType(); \ |
| SuccessOrExit(ASN1_ERR); |
| |
| #define ASN1_EXIT_CONSTRUCTED \ |
| ASN1_ERR = ASN1_READER.Next(); \ |
| if (ASN1_ERR == ASN1_NO_ERROR) \ |
| ASN1_ERR = ASN1_ERROR_INVALID_ENCODING; \ |
| else if (ASN1_ERR == ASN1_END) \ |
| ASN1_ERR = ASN1_NO_ERROR; \ |
| SuccessOrExit(ASN1_ERR); \ |
| \ |
| ASN1_ERR = ASN1_READER.ExitConstructedType(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_PARSE_ENTER_SEQUENCE \ |
| ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Sequence) |
| |
| #define ASN1_ENTER_SEQUENCE \ |
| ASN1_ENTER_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Sequence) |
| |
| #define ASN1_EXIT_SEQUENCE \ |
| ASN1_EXIT_CONSTRUCTED |
| |
| #define ASN1_PARSE_ENTER_SET \ |
| ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Set) |
| |
| #define ASN1_ENTER_SET \ |
| ASN1_ENTER_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Set) |
| |
| #define ASN1_EXIT_SET \ |
| ASN1_EXIT_CONSTRUCTED |
| |
| #define ASN1_ENTER_ENCAPSULATED(CLASS, TAG) \ |
| do { \ |
| ASN1_VERIFY_TAG(CLASS, TAG); \ |
| \ |
| ASN1_ERR = ASN1_READER.EnterEncapsulatedType(); \ |
| SuccessOrExit(ASN1_ERR); |
| |
| #define ASN1_PARSE_ENTER_ENCAPSULATED(CLASS, TAG) \ |
| do { \ |
| ASN1_ERR = ASN1_READER.Next(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| \ |
| ASN1_VERIFY_TAG(CLASS, TAG); \ |
| \ |
| ASN1_ERR = ASN1_READER.EnterEncapsulatedType(); \ |
| SuccessOrExit(ASN1_ERR); |
| |
| #define ASN1_EXIT_ENCAPSULATED \ |
| ASN1_ERR = ASN1_READER.Next(); \ |
| if (ASN1_ERR == ASN1_NO_ERROR) \ |
| ASN1_ERR = ASN1_ERROR_INVALID_ENCODING; \ |
| else if (ASN1_ERR == ASN1_END) \ |
| ASN1_ERR = ASN1_NO_ERROR; \ |
| SuccessOrExit(ASN1_ERR); \ |
| \ |
| ASN1_ERR = ASN1_READER.ExitEncapsulatedType(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_PARSE_INTEGER(OUT_VAL) \ |
| do { \ |
| ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer); \ |
| \ |
| ASN1_ERR = ASN1_READER.GetInteger(OUT_VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_GET_INTEGER(OUT_VAL) \ |
| do { \ |
| ASN1_ERR = ASN1_READER.GetInteger(OUT_VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_PARSE_BOOLEAN(OUT_VAL) \ |
| do { \ |
| ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Boolean); \ |
| \ |
| ASN1_ERR = ASN1_READER.GetBoolean(OUT_VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_GET_BOOLEAN(OUT_VAL) \ |
| do { \ |
| ASN1_ERR = ASN1_READER.GetBoolean(OUT_VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_PARSE_OBJECT_ID(OUT_VAL) \ |
| do { \ |
| ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId); \ |
| \ |
| ASN1_ERR = ASN1_READER.GetObjectId(OUT_VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_GET_OBJECT_ID(OUT_VAL) \ |
| do { \ |
| ASN1_ERR = ASN1_READER.GetObjectId(OUT_VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_PARSE_NULL \ |
| ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Null) \ |
| |
| #define ASN1_PARSE_TIME(OUT_VAL) \ |
| do { \ |
| ASN1_PARSE_ANY; \ |
| \ |
| if (ASN1_READER.Class == kASN1TagClass_Universal && ASN1_READER.Tag == kASN1UniversalTag_UTCTime) \ |
| ASN1_ERR = ASN1_READER.GetUTCTime(OUT_VAL); \ |
| else if (ASN1_READER.Class == kASN1TagClass_Universal && ASN1_READER.Tag == kASN1UniversalTag_GeneralizedTime) \ |
| ASN1_ERR = ASN1_READER.GetGeneralizedTime(OUT_VAL); \ |
| else \ |
| ASN1_ERR = ASN1_ERROR_INVALID_ENCODING; \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_PARSE_BIT_STRING(OUT_VAL) \ |
| do { \ |
| ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString); \ |
| \ |
| ASN1_ERR = ASN1_READER.GetBitString(OUT_VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_GET_BIT_STRING(OUT_VAL) \ |
| do { \ |
| ASN1_ERR = ASN1_READER.GetBitString(OUT_VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| |
| // Utility Macros for encoding ASN1 |
| |
| #define ASN1_START_CONSTRUCTED(CLASS, TAG) \ |
| do { \ |
| ASN1_ERR = writer.StartConstructedType(CLASS, TAG); \ |
| SuccessOrExit(ASN1_ERR); |
| |
| #define ASN1_END_CONSTRUCTED \ |
| ASN1_ERR = writer.EndConstructedType(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| #define ASN1_START_SEQUENCE \ |
| ASN1_START_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Sequence) |
| |
| #define ASN1_END_SEQUENCE \ |
| ASN1_END_CONSTRUCTED |
| |
| #define ASN1_START_SET \ |
| ASN1_START_CONSTRUCTED(kASN1TagClass_Universal, kASN1UniversalTag_Set) |
| |
| #define ASN1_END_SET \ |
| ASN1_END_CONSTRUCTED |
| |
| #define ASN1_ENCODE_INTEGER(VAL) \ |
| do { \ |
| ASN1_ERR = writer.PutInteger(VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0); |
| |
| #define ASN1_ENCODE_BOOLEAN(VAL) \ |
| do { \ |
| ASN1_ERR = writer.PutBoolean(VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0); |
| |
| #define ASN1_ENCODE_BIT_STRING(VAL) \ |
| do { \ |
| ASN1_ERR = writer.PutBitString(VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0); |
| |
| #define ASN1_ENCODE_OBJECT_ID(OID) \ |
| do { \ |
| ASN1_ERR = writer.PutObjectId(OID); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0); |
| |
| #define ASN1_ENCODE_STRING(TAG, VAL, LEN) \ |
| do { \ |
| ASN1_ERR = writer.PutString(TAG, VAL, LEN); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0); |
| |
| #define ASN1_ENCODE_OCTET_STRING(VAL, LEN) \ |
| do { \ |
| ASN1_ERR = writer.PutOctetString(VAL, LEN); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0); |
| |
| #define ASN1_ENCODE_TIME(VAL) \ |
| do { \ |
| ASN1_ERR = writer.PutTime(VAL); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0); |
| |
| #define ASN1_ENCODE_NULL \ |
| do { \ |
| ASN1_ERR = writer.PutNull(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0); |
| |
| #define ASN1_START_ENCAPSULATED(CLASS, TAG, BIT_STRING_ENCODING) \ |
| do { \ |
| ASN1_ERR = writer.StartEncapsulatedType(CLASS, TAG, BIT_STRING_ENCODING); \ |
| SuccessOrExit(ASN1_ERR); |
| |
| #define ASN1_START_OCTET_STRING_ENCAPSULATED \ |
| ASN1_START_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_OctetString, false) |
| |
| #define ASN1_START_BIT_STRING_ENCAPSULATED \ |
| ASN1_START_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_BitString, true) |
| |
| #define ASN1_END_ENCAPSULATED \ |
| ASN1_ERR = writer.EndEncapsulatedType(); \ |
| SuccessOrExit(ASN1_ERR); \ |
| } while (0) |
| |
| |
| |
| #endif /* ASN1MACROS_H_ */ |