asn1.h revision f71c6ce3d63d12af823dfc6df1c57ce9928b6a3a
/** @file
* IPRT - Abstract Syntax Notation One (ASN.1).
*/
/*
* Copyright (C) 2006-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
#ifndef ___iprt_asn1_h
#define ___iprt_asn1_h
/** @defgroup grp_rt_asn1 RTAsn1 - Abstract Syntax Notation One
* @ingroup grp_rt
* @{
*/
/** Pointer to ASN.1 allocation information. */
typedef struct RTASN1ALLOCATION *PRTASN1ALLOCATION;
/** Pointer to a ASN.1 byte decoder cursor. */
typedef struct RTASN1CURSOR *PRTASN1CURSOR;
/**
* Sketch of a custom ASN.1 allocator virtual method table.
*
* Any information required by the allocator should be associated with this
* structure, i.e. use this as a kind of parent class. This saves storage in
* RTASN1ALLOCATORINFO and possibly reduces the number of parameters by one.
*/
typedef struct RTASN1ALLOCATORVTABLE
{
/**
* Free a chunk of memory allocated by this allocator.
*
* @returns IPRT status code.
* @param pThis Pointer to the vtable structure.
* @param pAllocation Pointer to the allocation info structure.
* @param pv Pointer to the memory that shall be freed. Not NULL.
*/
DECLCALLBACKMEMBER(void, pfnFree)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
void *pv);
/**
* Allocates a chunk of memory, all initialized to zero.
*
* @returns IPRT status code.
* @param pThis Pointer to the vtable structure.
* @param pAllocation Pointer to the allocation info structure.
* @param ppv Where to store the pointer on success.
* @param cb The minimum number of bytes to allocate. The actual
* number of bytes allocated shall be stored in
* pInfo->cbAllocated on success.
*/
DECLCALLBACKMEMBER(int, pfnAlloc)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
/**
* Reallocates a memory allocation.
*
* New memory does not need to be initialized, the caller takes care of that.
*
* This will not need to deal with free (@a cbNew == 0) or the initial
* allocation (@a pvOld == NULL), those calls will be directed to pfnFree and
* pfnAlloc respectively.
*
* @returns IPRT status code.
* @param pThis Pointer to the vtable structure.
* @param pAllocation Pointer to the allocation info structure.
* @param pvOld Pointer to the current allocation. Shall remain
* valid on failure, but may be invalid on success.
* @param ppvNew Where to store the pointer on success. Shall not be
* touched, except on successful returns.
* @param cbNew The new minimum allocation size. The actual number
* of bytes allocated shall be stored in
* pInfo->cbAllocated on success.
*/
DECLCALLBACKMEMBER(int, pfnRealloc)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
/** Pointer to an ASN.1 allocator vtable. */
typedef RTASN1ALLOCATORVTABLE *PRTASN1ALLOCATORVTABLE;
/** Pointer to a const ASN.1 allocator vtable. */
typedef RTASN1ALLOCATORVTABLE const *PCRTASN1ALLOCATORVTABLE;
/** The default ASN.1 allocator. */
/**
* Allocation information.
*/
typedef struct RTASN1ALLOCATION
{
/** The number of bytes currently allocated. */
/** Number of realloc calls. */
/** Reserved / padding. */
/** Allocator vtable, NULL for the default allocator. */
/**
* Grow an array by zero initialized memory.
*
* @returns IPRT status code.
* @param pAllocation The allocation record (initialized by
* RTAsn1CursorInitAllocation or similar).
* @param ppvArray Pointer to the variable pointing to the array. This is
* both input and output. Remains valid on failure.
* @param cbEntry The size of an array entry.
* @param cCurrent The current entry count. (Relevant for zero
* initialization of the new entries.)
* @param cNew The new entry count.
*/
/**
* Allocate a block of zero initialized memory.
*
* @returns IPRT status code.
* @param pAllocation The allocation record (initialized by
* RTAsn1CursorInitAllocation or similar).
* @param ppvMem Where to return the pointer to the block.
* @param cbMem The minimum number of bytes to allocate.
*/
/**
* Allocates a block of memory initialized to the content of @a pvSrc.
*
* @returns IPRT status code.
* @param pAllocation The allocation record (initialized by
* RTAsn1CursorInitAllocation or similar).
* @param ppvMem Where to return the pointer to the block.
* @param pvSrc The source memory.
* @param cbMem The minimum number of bytes to allocate.
*/
RTDECL(int) RTAsn1MemDup(PRTASN1ALLOCATION pAllocation, void **ppvMem, void const *pvSrc, size_t cbMem);
/**
* Free a memory block.
*
* @param pAllocation The allocation record (initialized by
* RTAsn1CursorInitAllocation or similar).
* @param pv The memory block to free. NULL will be ignored.
*/
/**
* Initalize an allocation.
*
* @param pAllocation The allocation record (initialized by
* RTAsn1CursorInitAllocation or similar).
* @param pAllocator The allocator
*/
RTDECL(PRTASN1ALLOCATION) RTAsn1MemInitAllocation(PRTASN1ALLOCATION pAllocation, PCRTASN1ALLOCATORVTABLE pAllocator);
RTDECL(int) RTAsn1ContentAllocZ(struct RTASN1CORE *pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator);
RTDECL(int) RTAsn1ContentDup(struct RTASN1CORE *pAsn1Core, void const *pvSrc, size_t cbSrc, PCRTASN1ALLOCATORVTABLE pAllocator);
RTDECL(int) RTAsn1ContentReallocZ(struct RTASN1CORE *pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator);
/** Pointer to a core ASN.1 encoding info structure. */
typedef struct RTASN1CORE *PRTASN1CORE;
/** Pointer to a const core ASN.1 encoding info structure. */
typedef struct RTASN1CORE const *PCRTASN1CORE;
/**
* ASN.1 object enumeration callback.
*
* @returns IPRT status code. VINF_SUCCESS continues the enumberation, all
* others quit it and is returned to the caller's caller.
* @param pAsn1Core The ASN.1 object we're called back about.
* @param pszName The member name. Array member names ends with
* '[#]'.
* @param uDepth The current depth.
* @param pvUser Callback user parameter.
*/
typedef DECLCALLBACK(int) FNRTASN1ENUMCALLBACK(struct RTASN1CORE *pAsn1Core, const char *pszName, uint32_t uDepth, void *pvUser);
/** Pointer to an ASN.1 object enumeration callback. */
typedef FNRTASN1ENUMCALLBACK *PFNRTASN1ENUMCALLBACK;
/**
* ASN.1 object encoding writer callback.
*
* @returns IPRT status code.
* @param pbBuf Pointer to the bytes to output.
* @param cbToWrite The number of bytes to write.
* @param pvUser Callback user parameter.
* @param pErrInfo Where to store extended error info. Optional.
*/
typedef DECLCALLBACK(int) FNRTASN1ENCODEWRITER(const void *pvBuf, size_t cbToWrite, void *pvUser, PRTERRINFO pErrInfo);
/** Pointer to an ASN.1 encoding writer callback. */
typedef FNRTASN1ENCODEWRITER *PFNRTASN1ENCODEWRITER;
/** @name ASN.1 Vtable Method Types
* @{ */
/**
* Destructor.
*
* RTAsn1Destroy will first destroy all children by recursive calls to pfnEnum,
* afterwards it will call this method to release any memory or other resources
* associated with this object. The memory backing the object structure shall
* not be freed by this method.
*
* @param pThisCore Pointer to the ASN.1 core to destroy.
*/
/** Pointer to a FNRTASN1COREVTDTOR method. */
typedef FNRTASN1COREVTDTOR *PFNRTASN1COREVTDTOR;
/**
* Enumerate members (not necessary for primitive objects).
*
* @returns IPRT status code, any non VINF_SUCCESS value stems from pfnCallback.
* @param pThisCore Pointer to the ASN.1 core to enumerate members of.
* @param pfnCallback The callback.
* @param uDepth The depth of this object. Children are at +1.
* @param pvUser Callback user argument.
*/
typedef DECLCALLBACK(int) FNRTASN1COREVTENUM(PRTASN1CORE pThisCore, PFNRTASN1ENUMCALLBACK pfnCallback,
/** Pointer to a FNRTASN1COREVTENUM method. */
typedef FNRTASN1COREVTENUM *PFNRTASN1COREVTENUM;
/**
* Clone method.
*
* @param pThisCore Pointer to the ASN.1 core to initialize as a clone
* of pSrcClone. (The caller is responsible for making
* sure there is sufficent space and such.)
* @param pSrcCore The object to clone.
* @param pAllocator The allocator to use.
*/
typedef DECLCALLBACK(int) FNRTASN1COREVTCLONE(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore, PCRTASN1ALLOCATORVTABLE pAllocator);
/** Pointer to a FNRTASN1COREVTCLONE method. */
typedef FNRTASN1COREVTCLONE *PFNRTASN1COREVTCLONE;
/**
* Compare method.
*
* The caller makes sure both cores are present and have the same Vtable.
*
* @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
* @param pLeftCore Pointer to the ASN.1 core of the left side object.
* @param pRightCore Pointer to the ASN.1 core of the right side object.
*/
/** Pointer to a FNRTASN1COREVTCOMPARE method. */
typedef FNRTASN1COREVTCOMPARE *PFNRTASN1COREVTCOMPARE;
/**
* Check sanity method.
*
* @returns IPRT status code.
* @param pThisCore Pointer to the ASN.1 core of the object to check out.
* @param fFlags See RTASN1_CHECK_SANITY_F_XXX.
* @param pszErrInfo Where to return additional error details. Optional.
* @param pszErrorTag Tag for the additional error details.
*/
/** Pointer to a FNRTASN1COREVTCHECKSANITY method. */
/**
* Optional encoding preparations.
*
* On successful return, the pThisCore->cb value shall be valid and up to date.
* Will be called for any present object, including ones with default values and
* similar.
*
* @returns IPRT status code
* @param pThisCore Pointer to the ASN.1 core to enumerate members of.
* @param fFlags Encoding flags, RTASN1ENCODE_F_XXX.
* @param pErrInfo Where to return extra error information. Optional.
*/
typedef DECLCALLBACK(int) FNRTASN1COREVTENCODEPREP(PRTASN1CORE pThisCore, uint32_t fFlags, PRTERRINFO pErrInfo);
/** Pointer to a FNRTASN1COREVTENCODEWRITE method. */
/**
* Optional encoder writer.
*
* This writes the header as well as all the content. Will be called for any
* present object, including ones with default values and similar.
*
* @returns IPRT status code.
* @param pThisCore Pointer to the ASN.1 core to enumerate members of.
* @param fFlags Encoding flags, RTASN1ENCODE_F_XXX.
* @param pfnWriter The output writer function.
* @param pvUser The user context for the writer function.
* @param pErrInfo Where to return extra error information. Optional.
*/
typedef DECLCALLBACK(int) FNRTASN1COREVTENCODEWRITE(PRTASN1CORE pThisCore, uint32_t fFlags, PFNRTASN1ENCODEWRITER pfnWriter,
/** Pointer to a FNRTASN1COREVTENCODEWRITE method. */
/** @} */
/** Mask of common flags. These will be propagated during sanity checking.
* Bits not in this mask are type specfic. */
/**
* ASN.1 core vtable.
*/
typedef struct RTASN1COREVTABLE
{
/** The name. */
const char *pszName;
/** Size of the structure. */
/** The default tag, UINT8_MAX if not applicable. */
/** The default class and flags. */
/** Reserved for later / alignment. */
/** @copydoc FNRTASN1COREVTDTOR */
/** @copydoc FNRTASN1COREVTENUM */
/** @copydoc FNRTASN1COREVTCLONE */
/** @copydoc FNRTASN1COREVTCOMPARE */
/** @copydoc FNRTASN1COREVTCHECKSANITY */
/** @copydoc FNRTASN1COREVTENCODEPREP */
/** @copydoc FNRTASN1COREVTENUM */
/** Pointer to an ASN.1 allocator vtable. */
typedef struct RTASN1COREVTABLE *PRTASN1COREVTABLE;
/** Pointer to a const ASN.1 allocator vtable. */
typedef RTASN1COREVTABLE const *PCRTASN1COREVTABLE;
/** @name Helper macros for prototyping standard functions for an ASN.1 type.
* @{ */
a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Init)(RT_CONCAT(P,a_TypeNm) pThis, PCRTASN1ALLOCATORVTABLE pAllocator); \
a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Clone)(RT_CONCAT(P,a_TypeNm) pThis, RT_CONCAT(PC,a_TypeNm) pSrc, \
a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Enum)(RT_CONCAT(P,a_TypeNm) pThis, PFNRTASN1ENUMCALLBACK pfnCallback, \
a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Compare)(RT_CONCAT(PC,a_TypeNm) pLeft, RT_CONCAT(PC,a_TypeNm) pRight); \
a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, RT_CONCAT(P,a_TypeNm) pThis,\
const char *pszErrorTag); \
a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_CheckSanity)(RT_CONCAT(PC,a_TypeNm) pThis, uint32_t fFlags, \
/** @name Helper macros for prototyping standard functions for an ASN.1 type.
* @{ */
/** Aliases two ASN.1 types. */
typedef a_AliasType a_TypeNm; \
\
\
DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Init)(RT_CONCAT(P,a_TypeNm) pThis, PCRTASN1ALLOCATORVTABLE pAllocator) \
DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, RT_CONCAT(P,a_TypeNm) pThis,\
const char *pszErrorTag) \
\
/** @} */
/**
* Core ASN.1 structure for storing encoding details and data location.
*
* This is used as a 'parent' for all other decoded ASN.1 based structures.
*/
typedef struct RTASN1CORE
{
/** The tag.
* @remarks 32-bit should be enough for everyone... We don't currently
* implement decoding tags larger than 30 anyway. :-) */
/** Tag class and flags (ASN1_TAGCLASS_XXX and ASN1_TAGFLAG_XXX). */
/** The real tag value for IMPLICT tag overrides. */
/** The real class value for IMPLICT tag overrides. */
/** The size of the tag and length ASN.1 header. */
/** Length. */
/** IPRT flags (RTASN1CORE_F_XXX). */
/** Pointer to the data.
* After decoding this generally points to the encoded data content. When
* preparting something for encoding or otherwise constructing things in memory,
* this generally points heap memory or read-only constants.
* @sa RTAsn1ContentAllocZ, RTAsn1ContentReallocZ, RTAsn1ContentDup,
* RTAsn1ContentFree. */
/** Pointer to the virtual method table for this object. Optional. */
} RTASN1CORE;
/** The Vtable for a RTASN1CORE structure when not in some way use used as a
/** @name RTASN1CORE_F_XXX - Flags for RTASN1CORE::fFlags
* @{ */
#define RTASN1CORE_F_PRESENT RT_BIT_32(0)
/** Not present in stream, using default value. */
/** The tag was overriden by an implict context tag or some such thing,
* RTASN1CORE::uImplicitTag hold the universal tag value if one exists. */
/** Primitive tag with the corresponding RTASN1XXX struct. */
/** Dummy node typically used with choices, has children, not encoded, must be
* ignored. */
/** Allocated content (pointed to by uData).
* The content should is still be considered 104% read-only by anyone other
* than then type methods (pOps and associates). */
/** Decoded content (pointed to by uData).
* Mutually exclusive with RTASN1CORE_F_ALLOCATED_CONTENT. If neither is
* set, uData might be NULL or point to some shared static memory for
* frequently used values. */
/** @} */
/** Check s whether an ASN.1 core object present in some way (default data,
* decoded data, ...). */
/** Check s whether an ASN.1 core object is a dummy object (and is present). */
/**
* Calculates pointer to the raw ASN.1 record.
*
* ASSUMES that it's decoded content and that cbHdr and uData are both valid.
*
* @returns Byte pointer to the first tag byte.
* @param a_pAsn1Core The ASN.1 core.
*/
#define RTASN1CORE_GET_RAW_ASN1_PTR(a_pAsn1Core) ( (a_pAsn1Core)->uData.pu8 - (a_pAsn1Core)->cbHdr )
/**
* Calculates the length of the raw ASN.1 record to go with the
* RTASN1CORE_GET_RAW_ASN1_PTR() result.
*
* ASSUMES that it's decoded content and that cbHdr and uData are both valid.
*
* @returns Size in bytes (uint32_t).
* @param a_pAsn1Core The ASN.1 core.
*/
/**
* Retrievs the tag or implicit tag depending on the RTASN1CORE_F_TAG_IMPLICIT
* flag.
*
* @returns The ASN.1 tag of the object.
* @param a_pAsn1Core The ASN.1 core.
*/
#define RTASN1CORE_GET_TAG(a_pAsn1Core) ( !((a_pAsn1Core)->fFlags & RTASN1CORE_F_TAG_IMPLICIT) ? (a_pAsn1Core)->uTag : (a_pAsn1Core)->uRealTag )
{
return (PRTASN1CORE)pThis;
}
{
}
RTDECL(int) RTAsn1Core_InitEx(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass, PCRTASN1COREVTABLE pOps, uint32_t fFlags);
/**
* Initialize the ASN.1 core object representation to a default value.
*
* @returns VINF_SUCCESS
* @param pAsn1Core The ASN.1 core.
* @param uTag The tag number.
* @param fClass The tag class and flags.
*/
RTDECL(int) RTAsn1Core_CloneContent(PRTASN1CORE pThis, PCRTASN1CORE pSrc, PCRTASN1ALLOCATORVTABLE pAllocator);
/**
* Dummy ASN.1 object for use in choices and similar non-sequence structures.
*
* This allows hooking up destructors, enumerators and such, as well as not
* needing custom code for sequence-of / set-of collections.
*/
typedef struct RTASN1DUMMY
{
/** Core ASN.1. */
} RTASN1DUMMY;
/** Pointer to a dummy record. */
typedef RTASN1DUMMY *PRTASN1DUMMY;
/**
* Initalizes a dummy ASN.1 object.
*
* @returns VINF_SUCCESS.
* @param pThis The dummy object.
*/
/**
* Standard compliant initalizer.
*
* @returns VINF_SUCCESS.
* @param pThis The dummy object.
* @param pAllocator Ignored.
*/
{
return RTAsn1Dummy_InitEx(pThis);
}
/**
* ASN.1 sequence core (IPRT representation).
*/
typedef struct RTASN1SEQUENCECORE
{
/** Core ASN.1 encoding details. */
/** Pointer to an ASN.1 sequence core (IPRT representation). */
typedef RTASN1SEQUENCECORE *PRTASN1SEQUENCECORE;
/** Pointer to a const ASN.1 sequence core (IPRT representation). */
typedef RTASN1SEQUENCECORE const *PCRTASN1SEQUENCECORE;
RTDECL(int) RTAsn1SequenceCore_Clone(PRTASN1SEQUENCECORE pSeqCore, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQUENCECORE pSrc);
/**
* ASN.1 sequence-of core (IPRT representation).
*/
#if 0
typedef struct RTASN1SEQOFCORE
{
/** Core ASN.1 encoding details. */
/** Pointer to an ASN.1 sequence-of core (IPRT representation). */
typedef RTASN1SEQUENCECORE *PRTASN1SEQUENCECORE;
/** Pointer to a const ASN.1 sequence-of core (IPRT representation). */
typedef RTASN1SEQUENCECORE const *PCRTASN1SEQUENCECORE;
#else
# define RTASN1SEQOFCORE RTASN1SEQUENCECORE
# define PRTASN1SEQOFCORE PRTASN1SEQUENCECORE
# define PCRTASN1SEQOFCORE PCRTASN1SEQUENCECORE
#endif
RTDECL(int) RTAsn1SeqOfCore_Clone(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQOFCORE pSrc);
/** Defines the typedefs and prototypes for a generic sequence-of type. */
#define RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(a_SeqOfType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
typedef struct a_SeqOfType \
{ \
/** Sequence core. */ \
/** The array allocation tracker. */ \
/** Items in the array. */ \
/** Array. */ \
} a_SeqOfType; \
/**
* ASN.1 set core (IPRT representation).
*/
typedef struct RTASN1SETCORE
{
/** Core ASN.1 encoding details. */
/** Pointer to an ASN.1 set core (IPRT representation). */
typedef RTASN1SETCORE *PRTASN1SETCORE;
/** Pointer to a const ASN.1 set core (IPRT representation). */
typedef RTASN1SETCORE const *PCRTASN1SETCORE;
RTDECL(int) RTAsn1SetCore_Clone(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETCORE pSrc);
/**
* ASN.1 set-of core (IPRT representation).
*/
#if 0
typedef struct RTASN1SETOFCORE
{
/** Core ASN.1 encoding details. */
/** Pointer to an ASN.1 set-of core (IPRT representation). */
typedef RTASN1SETUENCECORE *PRTASN1SETUENCECORE;
/** Pointer to a const ASN.1 set-of core (IPRT representation). */
typedef RTASN1SETUENCECORE const *PCRTASN1SETUENCECORE;
#else
# define RTASN1SETOFCORE RTASN1SETCORE
# define PRTASN1SETOFCORE PRTASN1SETCORE
# define PCRTASN1SETOFCORE PCRTASN1SETCORE
#endif
RTDECL(int) RTAsn1SetOfCore_Clone(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETOFCORE pSrc);
/** Defines the typedefs and prototypes for a generic set-of type. */
#define RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(a_SetOfType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
typedef struct a_SetOfType \
{ \
/** Set core. */ \
/** The array allocation tracker. */ \
/** Items in the array. */ \
/** Array. */ \
} a_SetOfType; \
/*
* Declare sets and sequences of the core structure.
*/
/**
* ASN.1 null (IPRT representation).
*/
typedef struct RTASN1NULL
{
/** Core ASN.1 encoding details. */
} RTASN1NULL;
/** Pointer to an ASN.1 null (IPRT representation). */
typedef RTASN1NULL *PRTASN1NULL;
/** Pointer to a const ASN.1 null (IPRT representation). */
typedef RTASN1NULL const *PCRTASN1NULL;
/** The Vtable for a RTASN1NULL structure. */
/**
* ASN.1 integer (IPRT representation).
*/
typedef struct RTASN1INTEGER
{
/** Core ASN.1 encoding details. */
/** The unsigned C representation of the 64 least significant bits.
* length you like. Thus, the user needs to check the size and
* preferably use the access APIs for signed numbers. */
/** Pointer to an ASN.1 integer (IPRT representation). */
typedef RTASN1INTEGER *PRTASN1INTEGER;
/** Pointer to a const ASN.1 integer (IPRT representation). */
typedef RTASN1INTEGER const *PCRTASN1INTEGER;
/** The Vtable for a RTASN1INTEGER structure. */
/**
* Initializes an interger object to a default value.
* @returns VINF_SUCCESS.
* @param pBoolean The integer object representation.
* @param uValue The default value (unsigned 64-bit).
* @param pAllocator The allocator (pro forma).
*/
RTDECL(int) RTAsn1Integer_InitDefault(PRTASN1INTEGER pInteger, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator);
RTDECL(int) RTAsn1Integer_InitU64(PRTASN1INTEGER pThis, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator);
/**
* Get the most significat bit that's set (1).
*
* @returns 0-base bit number, -1 if all clear.
* @param pInteger The integer to check.
*/
/**
* Compares two ASN.1 unsigned integers.
*
* @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
* @param pLeft The first ASN.1 integer.
* @param pRight The second ASN.1 integer.
*/
/**
* Compares an ASN.1 unsigned integer with a uint64_t.
*
* @returns 0 if equal, -1 if @a pInteger is smaller, 1 if @a pInteger is
* larger.
* @param pInteger The ASN.1 integer to treat as unsigned.
* @param u64Const The uint64_t constant to compare with.
*/
/**
* Compares an ASN.1 unsigned integer with a uint32_t.
*
* @returns 0 if equal, -1 if @a pInteger is smaller, 1 if @a pInteger is
* larger.
* @param pInteger The ASN.1 integer to treat as unsigned.
* @param u32Const The uint32_t constant to compare with.
* @remarks We don't bother with U16 and U8 variants, just use this instead.
*/
/**
* Initializes a big integer number from an ASN.1 integer.
*
* @returns IPRT status code.
* @param pInteger The ASN.1 integer.
* @param pBigNum The big integer number structure to initialize.
* @param fBigNumInit Subset of RTBIGNUMINIT_F_XXX that concerns
* senitivity, signedness and endianness.
*/
RTDECL(int) RTAsn1Integer_ToBigNum(PCRTASN1INTEGER pInteger, PRTBIGNUM pBigNum, uint32_t fBigNumInit);
RTDECL(int) RTAsn1Integer_FromBigNum(PRTASN1INTEGER pThis, PCRTBIGNUM pBigNum, PCRTASN1ALLOCATORVTABLE pAllocator);
RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFINTEGERS, RTASN1INTEGER, RTDECL, RTAsn1SeqOfIntegers);
RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFINTEGERS, RTASN1INTEGER, RTDECL, RTAsn1SetOfIntegers);
/**
* ASN.1 boolean (IPRT representation).
*/
typedef struct RTASN1BOOLEAN
{
/** Core ASN.1 encoding details. */
/** The boolean value. */
bool fValue;
/** Pointer to the IPRT representation of an ASN.1 boolean. */
typedef RTASN1BOOLEAN *PRTASN1BOOLEAN;
/** Pointer to the const IPRT representation of an ASN.1 boolean. */
typedef RTASN1BOOLEAN const *PCRTASN1BOOLEAN;
/** The Vtable for a RTASN1BOOLEAN structure. */
/**
* Initializes a boolean object to a default value.
* @returns VINF_SUCCESS
* @param pBoolean The boolean object representation.
* @param fValue The default value.
* @param pAllocator The allocator (pro forma).
*/
RTDECL(int) RTAsn1Boolean_InitDefault(PRTASN1BOOLEAN pBoolean, bool fValue, PCRTASN1ALLOCATORVTABLE pAllocator);
RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFBOOLEANS, RTASN1BOOLEAN, RTDECL, RTAsn1SeqOfBooleans);
RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFBOOLEANS, RTASN1BOOLEAN, RTDECL, RTAsn1SetOfBooleans);
/**
* ASN.1 UTC and Generalized Time (IPRT representation).
*
* The two time types only differs in the precision the render (UTC time being
* the one for which you go "WTF were they thinking?!!" for in 2014).
*/
typedef struct RTASN1TIME
{
/** The core structure, either ASN1_TAG_UTC_TIME or
* ASN1_TAG_GENERALIZED_TIME. */
/** The exploded time. */
} RTASN1TIME;
/** Pointer to an IPRT representation of ASN.1 UTC/Generalized time. */
typedef RTASN1TIME *PRTASN1TIME;
/** Pointer to a const IPRT representation of ASN.1 UTC/Generalized time. */
typedef RTASN1TIME const *PCRTASN1TIME;
/** The Vtable for a RTASN1TIME structure. */
/**
* Compares two ASN.1 time values.
*
* @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
* @param pLeft The first ASN.1 time object.
* @param pTsRight The second time to compare.
*/
/** @name Predicate macros for determing the exact type of RTASN1TIME.
* @{ */
/** True if UTC time. */
/** True if generalized time. */
#define RTASN1TIME_IS_GENERALIZED_TIME(a_pAsn1Time) ((a_pAsn1Time)->Asn1Core.uTag == ASN1_TAG_GENERALIZED_TIME)
/** @} */
/**
* ASN.1 object identifier (IPRT representation).
*/
typedef struct RTASN1OBJID
{
/** Core ASN.1 encoding details. */
/** Coverning the paComponents memory allocation if there isn't enough room in
* szObjId for both the dottet string and the component values. */
/** Pointer to an array with the component values.
* This may point within szObjId if there is enough space for both there. */
uint32_t const *pauComponents;
/** The number of components in the object identifier.
* This ASSUMES that nobody will be ever needing more than 255 components. */
/** The dotted string representation of the object identifier.
* If there is sufficient space after the string, we will place the array that
*
* An analysis of dumpasn1.cfg, hl7.org and our own _OID defines indicates
* that we need space for at least 10 components and 30-something chars. We've
* allocated 87 bytes, which we ASSUME should be enough for everyone. */
char szObjId[87];
} RTASN1OBJID;
/** Pointer to an ASN.1 object identifier representation. */
typedef RTASN1OBJID *PRTASN1OBJID;
/** Pointer to a const ASN.1 object identifier representation. */
typedef RTASN1OBJID const *PCRTASN1OBJID;
/** The Vtable for a RTASN1OBJID structure. */
RTDECL(int) RTAsn1ObjId_InitFromString(PRTASN1OBJID pThis, const char *pszObjId, PCRTASN1ALLOCATORVTABLE pAllocator);
/**
* Compares an ASN.1 object identifier with a dotted object identifier string.
*
* @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
* @param pThis The ASN.1 object identifier.
* @param pszRight The dotted object identifier string.
*/
/**
* Checks if an ASN.1 object identifier starts with the given dotted object
* identifier string.
*
* The matching is only successful if the given string matches matches the last
* component completely.
*
* @returns true / false.
* @param pThis The ASN.1 object identifier.
* @param pszStartsWith The dotted object identifier string.
*/
RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFOBJIDS, RTASN1OBJID, RTDECL, RTAsn1SeqOfObjIds);
RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOBJIDS, RTASN1OBJID, RTDECL, RTAsn1SetOfObjIds);
/**
* ASN.1 bit string (IPRT representation).
*/
typedef struct RTASN1BITSTRING
{
/** Core ASN.1 encoding details. */
/** The number of bits. */
/** The max number of bits (given at decoding / construction). */
/** Pointer to the bits. */
/** Pointer to user structure encapsulated in this string, if dynamically
* allocated the EncapsulatedAllocation member can be used to track it and
* trigger automatic cleanup on object destruction. If EncapsulatedAllocation
* is zero, any object pointed to will only be deleted. */
/** Allocation tracking structure for pEncapsulated. */
/** Pointer to the IPRT representation of an ASN.1 bit string. */
typedef RTASN1BITSTRING *PRTASN1BITSTRING;
/** Pointer to the const IPRT representation of an ASN.1 bit string. */
typedef RTASN1BITSTRING const *PCRTASN1BITSTRING;
/** The Vtable for a RTASN1BITSTRING structure. */
/**
* Calculates pointer to the first bit.
*
* @returns Byte pointer to the first bit.
* @param a_pBitString The ASN.1 bit string.
*/
/**
* Calculates the size in bytes.
*
* @returns Rounded up size in bytes.
* @param a_pBitString The ASN.1 bit string.
*/
RTDECL(int) RTAsn1BitString_DecodeAsn1Ex(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t cMaxBits, PRTASN1BITSTRING pThis,
const char *pszErrorTag);
RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFBITSTRINGS, RTASN1BITSTRING, RTDECL, RTAsn1SeqOfBitStrings);
RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFBITSTRINGS, RTASN1BITSTRING, RTDECL, RTAsn1SetOfBitStrings);
/**
* ASN.1 octet string (IPRT representation).
*/
typedef struct RTASN1OCTETSTRING
{
/** Core ASN.1 encoding details. */
/** Pointer to user structure encapsulated in this string, if dynamically
* allocated the EncapsulatedAllocation member can be used to track it and
* trigger automatic cleanup on object destruction. If EncapsulatedAllocation
* is zero, any object pointed to will only be deleted. */
/** Allocation tracking structure for pEncapsulated. */
/** Pointer to the IPRT representation of an ASN.1 octet string. */
typedef RTASN1OCTETSTRING *PRTASN1OCTETSTRING;
/** Pointer to the const IPRT representation of an ASN.1 octet string. */
typedef RTASN1OCTETSTRING const *PCRTASN1OCTETSTRING;
/** The Vtable for a RTASN1OCTETSTRING structure. */
RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFOCTETSTRINGS, RTASN1OCTETSTRING, RTDECL, RTAsn1SeqOfOctetStrings);
RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOCTETSTRINGS, RTASN1OCTETSTRING, RTDECL, RTAsn1SetOfOctetStrings);
/**
* ASN.1 string (IPRT representation).
* All char string types except 'character string (29)'.
*/
typedef struct RTASN1STRING
{
/** Core ASN.1 encoding details. */
/** Allocation tracking for pszUtf8. */
/** If conversion to UTF-8 was requested, we cache that here. */
char const *pszUtf8;
/** The length (chars, not code points) of the above UTF-8 string if
* present. */
} RTASN1STRING;
/** Pointer to the IPRT representation of an ASN.1 string. */
typedef RTASN1STRING *PRTASN1STRING;
/** Pointer to the const IPRT representation of an ASN.1 string. */
typedef RTASN1STRING const *PCRTASN1STRING;
/** The Vtable for a RTASN1STRING structure. */
/** @name String type predicate macros.
* @{ */
#define RTASN1STRING_IS_NUMERIC(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_NUMERIC_STRING )
#define RTASN1STRING_IS_PRINTABLE(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_PRINTABLE_STRING )
#define RTASN1STRING_IS_T61(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_T61_STRING )
#define RTASN1STRING_IS_VIDEOTEX(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_VIDEOTEX_STRING )
#define RTASN1STRING_IS_VISIBLE(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_VISIBLE_STRING )
#define RTASN1STRING_IS_IA5(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_IA5_STRING )
#define RTASN1STRING_IS_GRAPHIC(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_GRAPHIC_STRING )
#define RTASN1STRING_IS_GENERAL(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_GENERAL_STRING )
/** UTF-8. */
#define RTASN1STRING_IS_UTF8(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_UTF8_STRING )
/** UCS-2. */
#define RTASN1STRING_IS_BMP(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_BMP_STRING )
/** UCS-4. */
#define RTASN1STRING_IS_UNIVERSAL(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_UNIVERSAL_STRING )
/** @} */
RTDECL(int) RTAsn1String_InitWithValue(PRTASN1STRING pThis, const char *pszUtf8Value, PCRTASN1ALLOCATORVTABLE pAllocator);
RTDECL(int) RTAsn1String_InitEx(PRTASN1STRING pThis, uint32_t uTag, void const *pvValue, size_t cbValue,
/**
* Compares two strings values, extended version.
*
* @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
* @param pLeft The first string.
* @param pRight The second string.
* @param fTypeToo Set if the string types must match, false if
* not.
*/
/**
* Compares a ASN.1 string object with an UTF-8 string.
*
* @returns 0 if equal, -1 if @a pThis is smaller, 1 if @a pThis is larger.
* @param pThis The ASN.1 string object.
* @param pszString The UTF-8 string.
* @param cchString The length of @a pszString, or RTSTR_MAX.
*/
RTDECL(int) RTAsn1String_CompareWithString(PCRTASN1STRING pThis, const char *pszString, size_t cchString);
/**
* Queries the UTF-8 length of an ASN.1 string object.
*
* This differs from RTAsn1String_QueryUtf8 in that it won't need to allocate
* memory for the converted string, but just calculates the length.
*
* @returns IPRT status code.
* @param pThis The ASN.1 string object.
* @param pcch Where to return the string length.
*/
/**
* Queries the UTF-8 string for an ASN.1 string object.
*
* This may fail as it may require memory to be allocated for storing the
* string.
*
* @returns IPRT status code.
* @param pString The ASN.1 string object. This is a const
* parameter for making life easier on the caller,
* however be aware that the object may be modified
* by this call!
* @param ppsz Where to return the pointer to the UTF-8 string.
* Optional.
* @param pcch Where to return the length (in 8-bit chars) to
* of the UTF-8 string. Optional.
*/
RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFSTRINGS, RTASN1STRING, RTDECL, RTAsn1SeqOfStrings);
RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFSTRINGS, RTASN1STRING, RTDECL, RTAsn1SetOfStrings);
/**
* ASN.1 generic context specific tag (IPRT representation).
*
* Normally used to tag something that's optional, version specific or such.
*
* For the purpose of documenting the format with typedefs as well as possibly
* making it a little more type safe, there's a set of typedefs for the most
* commonly used tag values defined. These typedefs have are identical to
* RTASN1CONTEXTTAG, except from the C++ type system of view.
* tag values. These
*/
typedef struct RTASN1CONTEXTTAG
{
/** Core ASN.1 encoding details. */
/** Pointer to an ASN.1 context tag (IPRT thing). */
typedef RTASN1CONTEXTTAG *PRTASN1CONTEXTTAG;
/** Pointer to a const ASN.1 context tag (IPRT thing). */
typedef RTASN1CONTEXTTAG const *PCRTASN1CONTEXTTAG;
RTDECL(int) RTAsn1ContextTagN_Clone(PRTASN1CONTEXTTAG pThis, PCRTASN1CONTEXTTAG pSrc, uint32_t uTag);
/** @internal */
#define RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(a_uTag) \
typedef struct RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) { RTASN1CORE Asn1Core; } RT_CONCAT(RTASN1CONTEXTTAG,a_uTag); \
DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pThis, \
DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pThis, \
/** Helper for comparing optional context tags.
* This will return if both are not present or if their precense differs.
* @internal */
do { \
/* type checks */ \
} while (0)
/** Helpers for comparing optional context tags.
* This will return if both are not present or if their precense differs.
* @{ */
#define RTASN1CONTEXTTAG0_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 0)
#define RTASN1CONTEXTTAG1_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 1)
#define RTASN1CONTEXTTAG2_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 2)
#define RTASN1CONTEXTTAG3_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 3)
#define RTASN1CONTEXTTAG4_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 4)
#define RTASN1CONTEXTTAG5_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 5)
#define RTASN1CONTEXTTAG6_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 6)
#define RTASN1CONTEXTTAG7_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 7)
/** @} */
/**
* Type information for dynamically bits (see RTASN1DYNTYPE).
*/
typedef enum RTASN1TYPE
{
/** Invalid zero value. */
RTASN1TYPE_INVALID = 0,
/** Not present. */
/** ASN.1 NULL. */
/** ASN.1 integer. */
/** ASN.1 boolean. */
/** ASN.1 character string. */
/** ASN.1 octet string. */
/** ASN.1 bite string. */
/** ASN.1 UTC or Generalize time. */
#if 0
/** ASN.1 sequence core. */
/** ASN.1 set core. */
#endif
/** ASN.1 object identifier. */
/** End of valid types. */
/** Type size hack. */
RTASN1TYPE_32BIT_HACK = 0x7fffffff
} RTASN1TYPE;
/**
* ASN.1 dynamic type record.
*/
typedef struct RTASN1DYNTYPE
{
/** Alternative interpretation provided by a user.
* Before destroying this object, the user must explicitly free this and set
* it to NULL, otherwise there will be memory leaks. */
/** The type of data we've got here. */
/** Union with data of the type dictated by enmType. */
union
{
/** RTASN1TYPE_CORE. */
/** RTASN1TYPE_NULL. */
/** RTASN1TYPE_INTEGER. */
/** RTASN1TYPE_BOOLEAN. */
/** RTASN1TYPE_STRING. */
/** RTASN1TYPE_OCTET_STRING. */
/** RTASN1TYPE_BIT_STRING. */
/** RTASN1TYPE_TIME. */
#if 0
/** RTASN1TYPE_SEQUENCE_CORE. */
/** RTASN1TYPE_SET_CORE. */
#endif
/** RTASN1TYPE_OBJID. */
} u;
/** Pointer to an ASN.1 dynamic type record. */
typedef RTASN1DYNTYPE *PRTASN1DYNTYPE;
/** Pointer to a const ASN.1 dynamic type record. */
typedef RTASN1DYNTYPE const *PCRTASN1DYNTYPE;
/** @name Virtual Method Table Based API
* @{ */
/**
* Calls the destructor of the ASN.1 object.
*
* @param pAsn1Core The IPRT representation of an ASN.1 object.
*/
/**
* Deep enumeration of all descendants.
*
* @returns IPRT status code, any non VINF_SUCCESS value stems from pfnCallback.
* @param pThisCore Pointer to the ASN.1 core to enumerate members of.
* @param pfnCallback The callback.
* @param uDepth The depth of this object. Children are at +1.
* @param pvUser Callback user argument.
* @param fDepthFirst When set, recurse into child objects before calling
* pfnCallback on then. When clear, the child object
* is first
*/
/**
* Clones @a pSrcCore onto @a pThisCore.
*
* The caller must be sure that @a pSrcCore and @a pThisCore are of the same
* types.
*
* @returns IPRT status code.
* @param pThisCore Pointer to the ASN.1 core to clone onto. This shall
* be uninitialized.
* @param pSrcCore Pointer to the ASN.1 core to clone.
* @param pAllocator The allocator to use.
*/
RTDECL(int) RTAsn1VtClone(PRTASN1CORE pThisCore, PRTASN1CORE pSrcCore, PCRTASN1ALLOCATORVTABLE pAllocator);
/**
* Compares two objects.
*
* @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
* @param pLeftCore Pointer to the ASN.1 core of the left side object.
* @param pRightCore Pointer to the ASN.1 core of the right side object.
*/
/**
* Check sanity.
*
* A primary criteria is that the object is present and initialized.
*
* @returns IPRT status code.
* @param pThisCore Pointer to the ASN.1 core of the object to check out.
* @param fFlags See RTASN1_CHECK_SANITY_F_XXX.
* @param pszErrInfo Where to return additional error details. Optional.
* @param pszErrorTag Tag for the additional error details.
*/
/** @} */
/** @defgroup rp_asn1_encode RTAsn1Encode - ASN.1 Encoding
* @{ */
/** @name RTASN1ENCODE_F_XXX
* @{ */
/** Use distinguished encoding rules (DER) to encode the object. */
/** Use base encoding rules (BER) to encode the object.
* This is currently the same as DER for practical reasons. */
#define RTASN1ENCODE_F_BER RTASN1ENCODE_F_DER
/** Mask of valid encoding rules. */
/** @} */
/**
* Recalculates cbHdr of and ASN.1 object.
*
* @returns IPRT status code.
* @retval VINF_ASN1_NOT_ENCODED if the header size is zero (default value,
* whatever).
* @param pAsn1Core The object in question.
* @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
* flags. Must include the encoding type.
* @param pErrInfo Extended error info. Optional.
*/
/**
* Prepares the ASN.1 structure for encoding.
*
* The preparations is mainly calculating accurate object size, but may also
* involve operations like recoding internal UTF-8 strings to the actual ASN.1
* format and other things that may require memory to allocated/reallocated.
*
* @returns IPRT status code
* @param pRoot The root of the ASN.1 object tree to encode.
* @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
* flags. Must include the encoding type.
* @param pcbEncoded Where to return the encoded size. Optional.
* @param pErrInfo Where to store extended error information.
* Optional.
*/
RTDECL(int) RTAsn1EncodePrepare(PRTASN1CORE pRoot, uint32_t fFlags, uint32_t *pcbEncoded, PRTERRINFO pErrInfo);
/**
* Encodes and writes the header of an ASN.1 object.
*
* @returns IPRT status code.
* @retval VINF_ASN1_NOT_ENCODED if nothing was written (default value,
* whatever).
* @param pAsn1Core The object in question.
* @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
* flags. Must include the encoding type.
* @param pfnWriter The output writer callback.
* @param pvUser The user argument to pass to @a pfnWriter.
* @param pErrInfo Where to store extended error information.
* Optional.
*/
RTDECL(int) RTAsnEncodeWriteHeader(PCRTASN1CORE pAsn1Core, uint32_t fFlags, FNRTASN1ENCODEWRITER pfnWriter, void *pvUser,
/**
* Prepares the ASN.1 structure for encoding.
*
* The preparations is mainly calculating accurate object size, but may also
* involve operations like recoding internal UTF-8 strings to the actual ASN.1
* format and other things that may require memory to allocated/reallocated.
*
* @returns IPRT status code
* @param pRoot The root of the ASN.1 object tree to encode.
* @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
* flags. Must include the encoding type.
* @param pfnWriter The output writer callback.
* @param pvUser The user argument to pass to @a pfnWriter.
* @param pErrInfo Where to store extended error information.
* Optional.
*/
RTDECL(int) RTAsn1EncodeWrite(PCRTASN1CORE pRoot, uint32_t fFlags, FNRTASN1ENCODEWRITER pfnWriter, void *pvUser,
/** @} */
/** @defgroup rp_asn1_cursor RTAsn1Cursor - BER, DER, and CER cursor
* @{ */
/**
* ASN.1 decoder byte cursor.
*/
typedef struct RTASN1CURSOR
{
/** Pointer to the current (next) byte. */
/** Number of bytes left to decode. */
/** RTASN1CURSOR_FLAGS_XXX. */
/** Pointer to the primary cursor. */
struct RTASN1CURSORPRIMARY *pPrimary;
/** Pointer to the parent cursor. */
struct RTASN1CURSOR *pUp;
/** The error tag for this cursor level. */
const char *pszErrorTag;
} RTASN1CURSOR;
/** @name RTASN1CURSOR_FLAGS_XXX - Cursor flags.
* @{ */
/** Enforce DER rules. */
/** Enforce CER rules. */
/** @} */
typedef struct RTASN1CURSORPRIMARY
{
/** The normal cursor bits. */
/** For error reporting. */
/** The allocator virtual method table. */
typedef RTASN1CURSORPRIMARY *PRTASN1CURSORPRIMARY;
/**
* Initializes a primary cursor.
*
* The primary cursor is special in that it stores information shared with the
* sub-cursors created by methods like RTAsn1CursorGetContextTagNCursor and
* RTAsn1CursorGetSequenceCursor. Even if just sharing a few items at present,
* it still important to save every possible byte since stack space is scarce in
* some of the execution environments.
*
* @returns Pointer to pCursor->Cursor.
* @param pPrimaryCursor The primary cursor structure to initialize.
* @param pvFirst The first byte to decode.
* @param cb The number of bytes to decode.
* @param pErrInfo Where to store error information.
* @param pAllocator The allocator to use.
* @param fFlags RTASN1CURSOR_FLAGS_XXX.
* @param pszErrorTag The primary error tag.
*/
RTDECL(PRTASN1CURSOR) RTAsn1CursorInitPrimary(PRTASN1CURSORPRIMARY pPrimaryCursor, void const *pvFirst, uint32_t cb,
const char *pszErrorTag);
/**
* Initialize a sub-cursor for traversing the content of an ASN.1 object.
*
* @returns @a pChild
* @param pParent The parent cursor.
* @param pAsn1Core The ASN.1 object which content we should
* traverse with the sub-cursor.
* @param pChild The sub-cursor to initialize.
* @param pszErrorTag The error tag of the sub-cursor.
*/
/**
* Initalizes the an allocation structure prior to making an allocation.
*
* To try unify and optimize memory managment for decoding and in-memory
* construction of ASN.1 objects, each allocation has an allocation structure
* associated with it. This stores the allocator and keep statistics for
* optimizing array allocations.
*
* @returns Pointer to the allocator info (for call in alloc parameter).
* @param pCursor The cursor.
* @param pAllocator The allocation structure to initialize.
*/
RTDECL(PRTASN1ALLOCATION) RTAsn1CursorInitAllocation(PRTASN1CURSOR pCursor, PRTASN1ALLOCATION pAllocation);
/**
* Wrapper around RTErrInfoSetV.
*
* @returns @a rc
* @param pCursor The cursor.
* @param rc The return code to return.
* @param pszMsg Message format string.
* @param ... Format arguments.
*/
/**
* Wrapper around RTErrInfoSetV.
*
* @returns @a rc
* @param pCursor The cursor.
* @param rc The return code to return.
* @param pszMsg Message format string.
* @param va Format arguments.
*/
/**
* Checks that we've reached the end of the data for the cursor.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
*/
/**
* Skips a given number of bytes.
*
* @returns @a pCursor
* @param pCursor The cursor.
* @param cb The number of bytes to skip.
* @internal
*/
{
{
}
else
{
}
return pCursor;
}
/**
* Low-level function for reading an ASN.1 header.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param pAsn1Core The output object core.
* @param pszErrorTag Error tag.
* @internal
*/
RTDECL(int) RTAsn1CursorReadHdr(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, const char *pszErrorTag);
/**
* Common helper for simple tag matching.
*
* @returns IPRT status code.
* @param pCursor The cursor (for error reporting).
* @param pAsn1Core The ASN.1 core structure.
* @param uTag The expected tag.
* @param fClass The expected class.
* @param fString Set if it's a string type that shall follow
* special CER and DER rules wrt to constructed and
* primitive encoding.
* @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
* @param pszErrorTag The error tag.
*/
RTDECL(int) RTAsn1CursorMatchTagClassFlagsEx(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
/**
* Common helper for simple tag matching.
*
* @returns IPRT status code.
* @param pCursor The cursor (for error reporting).
* @param pAsn1Core The ASN.1 core structure.
* @param uTag The expected tag.
* @param fClass The expected class.
* @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
* @param pszErrorTag The error tag.
* @internal
*/
DECLINLINE(int) RTAsn1CursorMatchTagClassFlags(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
{
return VINF_SUCCESS;
return RTAsn1CursorMatchTagClassFlagsEx(pCursor, pAsn1Core, uTag, fClass, false /*fString*/, fFlags, pszErrorTag, pszWhat);
}
/**
* Common helper for simple tag matching for strings.
*
* Check string encoding considerations.
*
* @returns IPRT status code.
* @param pCursor The cursor (for error reporting).
* @param pAsn1Core The ASN.1 core structure.
* @param uTag The expected tag.
* @param fClass The expected class.
* @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
* @param pszErrorTag The error tag.
* @internal
*/
DECLINLINE(int) RTAsn1CursorMatchTagClassFlagsString(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
{
return VINF_SUCCESS;
return RTAsn1CursorMatchTagClassFlagsEx(pCursor, pAsn1Core, uTag, fClass, true /*fString*/, fFlags, pszErrorTag, pszWhat);
}
/** @name RTASN1CURSOR_GET_F_XXX - Common flags for all the getters.
* @{ */
/** Used for decoding objects with implicit tags assigned to them. This only
* works when calling getters with a unambigious types. */
#define RTASN1CURSOR_GET_F_IMPLICIT RT_BIT_32(0)
/** @} */
/**
* Read ANY object.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pAsn1Core The output object core.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetCore(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1CORE pAsn1Core, const char *pszErrorTag);
/**
* Read a NULL object.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pNull The output NULL object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetNull(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1NULL pNull, const char *pszErrorTag);
/**
* Read an INTEGER object.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pInteger The output integer object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetInteger(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1INTEGER pInteger, const char *pszErrorTag);
/**
* Read an BOOLEAN object.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pBoolean The output boolean object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetBoolean(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1BOOLEAN pBoolean, const char *pszErrorTag);
/**
* Retrives an object identifier (aka ObjId or OID) item from the ASN.1 stream.
*
* @returns IPRT status code.
* @param pCursor The cursor.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pObjId The output ODI object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetObjId(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pObjId, const char *pszErrorTag);
/**
* Retrives and verifies an object identifier.
*
* @returns IPRT status code.
* @param pCursor The cursor.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pObjId Where to return the parsed object ID, optional.
* @param pszExpectedObjId The expected object identifier (dotted).
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetAndCheckObjId(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pObjId,
const char *pszExpectedObjId, const char *pszErrorTag);
/**
* Read an UTC TIME or GENERALIZED TIME object.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pTime The output time object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetTime(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1TIME pTime, const char *pszErrorTag);
/**
* Read an BIT STRING object (skips past the content).
*
* @returns IPRT status ocde.
* @param pCursor The cursor.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pBitString The output bit string object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetBitString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1BITSTRING pBitString,
const char *pszErrorTag);
/**
* Read an BIT STRING object (skips past the content), extended version with
* cMaxBits.
*
* @returns IPRT status ocde.
* @param pCursor The cursor.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param cMaxBits The max length of the bit string in bits. Pass
* UINT32_MAX if variable size.
* @param pBitString The output bit string object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetBitStringEx(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t cMaxBits, PRTASN1BITSTRING pBitString,
const char *pszErrorTag);
/**
* Read an OCTET STRING object (skips past the content).
*
* @returns IPRT status ocde.
* @param pCursor The cursor.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pOctetString The output octet string object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetOctetString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OCTETSTRING pOctetString,
const char *pszErrorTag);
/**
* Read any kind of string object, except 'character string (29)'.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pString The output boolean object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
/**
* Read a IA5 STRING object.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pString The output boolean object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetIa5String(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
/**
* Read a UTF8 STRING object.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pString The output boolean object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetUtf8String(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
/**
* Read a BMP STRING (UCS-2) object.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pString The output boolean object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetBmpString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
/**
* Read a SEQUENCE object and create a cursor for its content.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pSeqCore The output sequence core object.
* @param pSeqCursor The output cursor for the sequence content.
* @param pszErrorTag Error tag, this will be associated with the
* returned cursor.
*/
/**
* Read a SET object and create a cursor for its content.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pSetCore The output set core object.
* @param pSetCursor The output cursor for the set content.
* @param pszErrorTag Error tag, this will be associated with the
* returned cursor.
*/
/**
* Read a given constructed context tag and create a cursor for its content.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pCtxTagCore The output context tag object.
* @param pCtxTagCursor The output cursor for the context tag content.
* @param pszErrorTag Error tag, this will be associated with the
* returned cursor.
*
* @remarks There are specialized version of this function for each of the
* numbered context tag structures, like for RTASN1CONTEXTTAG0 there is
* RTAsn1CursorGetContextTag0Cursor.
*/
RTDECL(int) RTAsn1CursorGetContextTagNCursor(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t uExpectedTag,
/**
* Read a dynamic ASN.1 type.
*
* @returns IPRT status code.
* @param pCursor The cursor we're decoding from.
* @param fFlags RTASN1CURSOR_GET_F_XXX.
* @param pDynType The output context tag object.
* @param pszErrorTag Error tag.
*/
RTDECL(int) RTAsn1CursorGetDynType(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1DYNTYPE pDynType, const char *pszErrorTag);
/**
* Peeks at the next ASN.1 object.
*
* @returns IPRT status code.
* @param pCursor The cursore we're decoding from.
* @param pAsn1Core Where to store the output of the peek.
*/
/**
*
* @returns @c true on match, @c false on mismatch.
* @param pCursor The cursore we're decoding from.
* @param uTag The tag number to match against.
* @param fClass The tag class and flags to match against.
*/
/** @internal */
#define RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(a_uTag) \
DECLINLINE(int) RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(PRTASN1CURSOR pCursor, uint32_t fFlags, \
{ /* Constructed is automatically implied if you need a cursor to it. */ \
return RTAsn1CursorGetContextTagNCursor(pCursor, fFlags, a_uTag, (PRTASN1CONTEXTTAG)pCtxTag, pCtxTagCursor, pszErrorTag); \
} \
DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,InitDefault)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pCtxTag) \
{ /* Constructed is automatically implied if you need to init it with a default value. */ \
return RTAsn1Core_InitDefault(&pCtxTag->Asn1Core, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED); \
} \
DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsConstructedContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
{ \
} \
{ \
} \
{ \
} \
/**
* Checks if the next object is a boolean.
*
* @returns true / false
* @param pCursor The cursore we're decoding from.
* @remarks May produce error info output on mismatch.
*/
{
return RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_BOOLEAN, ASN1_TAGFLAG_PRIMITIVE | ASN1_TAGCLASS_UNIVERSAL);
}
/**
* Checks if the next object is a set.
*
* @returns true / false
* @param pCursor The cursore we're decoding from.
* @remarks May produce error info output on mismatch.
*/
{
return RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_SET, ASN1_TAGFLAG_CONSTRUCTED | ASN1_TAGCLASS_UNIVERSAL);
}
/** @} */
/** @name ASN.1 Utility APIs
* @{ */
/**
* Dumps an IPRT representation of a ASN.1 object tree.
*
* @returns IPRT status code.
* @param pAsn1Core The ASN.1 object which members should be dumped.
* @param fFlags RTASN1DUMP_F_XXX.
* @param uLevel The indentation level to start at.
* @param pfnPrintfV The output function.
* @param pvUser Argument to the output function.
*/
RTDECL(int) RTAsn1Dump(PCRTASN1CORE pAsn1Core, uint32_t fFlags, uint32_t uLevel, PFNRTDUMPPRINTFV pfnPrintfV, void *pvUser);
/** @} */
/** @} */
#endif