blob: 5107515dda0425e41f7db9a168eec8d87c0d640f [file] [log] [blame]
/*
*
* Copyright (c) 2020 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 convenience macros for dealing with Abstract
* Syntax Notation One (ASN.1) encoded data.
*
*/
#pragma once
#include <lib/support/CodeUtils.h>
// Local variable names used by utility macros.
#define ASN1_READER reader
#define ASN1_ERR err
// Utility Macros for parsing ASN1
#define ASN1_VERIFY_TAG(CLASS, TAG) \
VerifyOrExit(ASN1_READER.GetClass() == (CLASS) && ASN1_READER.GetTag() == (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 == CHIP_NO_ERROR) \
ASN1_ERR = ASN1_ERROR_INVALID_ENCODING; \
else if (ASN1_ERR == ASN1_END) \
ASN1_ERR = CHIP_NO_ERROR; \
SuccessOrExit(ASN1_ERR); \
\
ASN1_ERR = ASN1_READER.ExitConstructedType(); \
SuccessOrExit(ASN1_ERR); \
} \
while (0)
#define ASN1_SKIP_AND_EXIT_CONSTRUCTED \
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_SKIP_AND_EXIT_SEQUENCE ASN1_SKIP_AND_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_SKIP_AND_EXIT_SET ASN1_SKIP_AND_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 == CHIP_NO_ERROR) \
ASN1_ERR = ASN1_ERROR_INVALID_ENCODING; \
else if (ASN1_ERR == ASN1_END) \
ASN1_ERR = CHIP_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.GetClass() == kASN1TagClass_Universal && ASN1_READER.GetTag() == kASN1UniversalTag_UTCTime) \
ASN1_ERR = ASN1_READER.GetUTCTime(OUT_VAL); \
else if (ASN1_READER.GetClass() == kASN1TagClass_Universal && ASN1_READER.GetTag() == 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)