VirtualBox

source: vbox/trunk/include/iprt/asn1.h@ 64887

Last change on this file since 64887 was 64887, checked in by vboxsync, 8 years ago

IPRT/ASN.1: Refactored array handling (SET OF, SEQUENCE OF) to use a pointer array instead of an object instance array. The old approach would move objects around in memory after they'd be initialized/decoded, making certain core optimziations involving pointers to object members impossible, as well as causing potentially causing trouble when modifying structures that takes down pointers after decoding. Fixed validation bug in rtCrX509Name_CheckSanityExtra where it didn't check that the RDNs had subitems but instead checked the parent twice (slight risk).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 91.8 KB
Line 
1/** @file
2 * IPRT - Abstract Syntax Notation One (ASN.1).
3 */
4
5/*
6 * Copyright (C) 2006-2016 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef ___iprt_asn1_h
27#define ___iprt_asn1_h
28
29#include <iprt/time.h>
30#include <iprt/stdarg.h>
31#include <iprt/err.h>
32#include <iprt/formats/asn1.h>
33
34
35RT_C_DECLS_BEGIN
36
37/** @defgroup grp_rt_asn1 RTAsn1 - Abstract Syntax Notation One
38 * @ingroup grp_rt
39 * @{
40 */
41
42
43/** Pointer to ASN.1 allocation information. */
44typedef struct RTASN1ALLOCATION *PRTASN1ALLOCATION;
45/** Pointer to ASN.1 array allocation information. */
46typedef struct RTASN1ARRAYALLOCATION *PRTASN1ARRAYALLOCATION;
47/** Pointer to a ASN.1 byte decoder cursor. */
48typedef struct RTASN1CURSOR *PRTASN1CURSOR;
49
50
51/**
52 * Sketch of a custom ASN.1 allocator virtual method table.
53 *
54 * Any information required by the allocator should be associated with this
55 * structure, i.e. use this as a kind of parent class. This saves storage in
56 * RTASN1ALLOCATORINFO and possibly reduces the number of parameters by one.
57 */
58typedef struct RTASN1ALLOCATORVTABLE
59{
60 /**
61 * Free a chunk of memory allocated by this allocator.
62 *
63 * @returns IPRT status code.
64 * @param pThis Pointer to the vtable structure.
65 * @param pAllocation Pointer to the allocation info structure.
66 * @param pv Pointer to the memory that shall be freed. Not NULL.
67 */
68 DECLCALLBACKMEMBER(void, pfnFree)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
69 void *pv);
70 /**
71 * Allocates a chunk of memory, all initialized to zero.
72 *
73 * @returns IPRT status code.
74 * @param pThis Pointer to the vtable structure.
75 * @param pAllocation Pointer to the allocation info structure.
76 * @param ppv Where to store the pointer on success.
77 * @param cb The minimum number of bytes to allocate. The actual
78 * number of bytes allocated shall be stored in
79 * pInfo->cbAllocated on success.
80 */
81 DECLCALLBACKMEMBER(int, pfnAlloc)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
82 void **ppv, size_t cb);
83 /**
84 * Reallocates a memory allocation.
85 *
86 * New memory does not need to be initialized, the caller takes care of that.
87 *
88 * This will not need to deal with free (@a cbNew == 0) or the initial
89 * allocation (@a pvOld == NULL), those calls will be directed to pfnFree and
90 * pfnAlloc respectively.
91 *
92 * @returns IPRT status code.
93 * @param pThis Pointer to the vtable structure.
94 * @param pAllocation Pointer to the allocation info structure.
95 * @param pvOld Pointer to the current allocation. Shall remain
96 * valid on failure, but may be invalid on success.
97 * @param ppvNew Where to store the pointer on success. Shall not be
98 * touched, except on successful returns.
99 * @param cbNew The new minimum allocation size. The actual number
100 * of bytes allocated shall be stored in
101 * pInfo->cbAllocated on success.
102 */
103 DECLCALLBACKMEMBER(int, pfnRealloc)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
104 void *pvOld, void **ppvNew, size_t cbNew);
105
106 /**
107 * Frees an array allocation (the array an all instances in it).
108 *
109 * @returns IPRT status code.
110 * @param pThis Pointer to the vtable structure.
111 * @param pAllocation Pointer to the allocation info structure.
112 * @param papvArray Pointer to the pointer array to be freed. Not NULL.
113 */
114 DECLCALLBACKMEMBER(void, pfnFreeArray)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ARRAYALLOCATION pAllocation,
115 void **papvArray);
116 /**
117 * Grows the array to at least @a cMinEntries.
118 *
119 * The entries are initalized with ZEROs.
120 *
121 * @returns IPRT status code.
122 * @param pThis Pointer to the vtable structure.
123 * @param pAllocation Pointer to the allocation info structure.
124 * @param ppapvArray Pointer to the pointer to the array to be grown (or
125 * allocated).
126 * @param cMinEntries The minimum number of entries (array size and
127 * instantiated entries) that must be available
128 * on successful return.
129 */
130 DECLCALLBACKMEMBER(int, pfnGrowArray)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ARRAYALLOCATION pAllocation,
131 void ***ppapvArray, uint32_t cMinEntries);
132 /**
133 * Shrinks the array (depends on allocator policy).
134 *
135 * If memory isn't freed, the implementation must fill the entries being
136 * shredded with ZEROs so the growth optimizations in RTAsn1MemResizeArray
137 * returns ZEROed entries.
138 *
139 * @returns IPRT status code.
140 * @param pThis Pointer to the vtable structure.
141 * @param pAllocation Pointer to the allocation info structure.
142 * @param ppapvArray Pointer to the pointer to the array to shrunk.
143 * @param cNew The new entry count.
144 * @param cCurrent The new entry count.
145 */
146 DECLCALLBACKMEMBER(void, pfnShrinkArray)(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ARRAYALLOCATION pAllocation,
147 void ***ppapvArray, uint32_t cNew, uint32_t cCurrent);
148} RTASN1ALLOCATORVTABLE;
149/** Pointer to an ASN.1 allocator vtable. */
150typedef RTASN1ALLOCATORVTABLE *PRTASN1ALLOCATORVTABLE;
151/** Pointer to a const ASN.1 allocator vtable. */
152typedef RTASN1ALLOCATORVTABLE const *PCRTASN1ALLOCATORVTABLE;
153
154/** The default ASN.1 allocator. */
155extern RTDATADECL(RTASN1ALLOCATORVTABLE const) g_RTAsn1DefaultAllocator;
156
157/** The Electric Fence ASN.1 allocator. */
158extern RTDATADECL(RTASN1ALLOCATORVTABLE const) g_RTAsn1EFenceAllocator;
159
160
161/**
162 * Allocation information.
163 */
164typedef struct RTASN1ALLOCATION
165{
166 /** The number of bytes currently allocated. */
167 uint32_t cbAllocated;
168 /** Number of realloc calls. */
169 uint16_t cReallocs;
170 /** Reserved / padding. */
171 uint16_t uReserved0;
172 /** Allocator vtable, NULL for the default allocator. */
173 PCRTASN1ALLOCATORVTABLE pAllocator;
174} RTASN1ALLOCATION;
175
176
177/**
178 * Pointer array allocation information.
179 *
180 * Used by SET OF and SEQUENCE OF structures (typically automatically
181 * generated).
182 */
183typedef struct RTASN1ARRAYALLOCATION
184{
185 /** The size of the array entry. */
186 uint32_t cbEntry;
187 /** The size of the pointer array allocation. */
188 uint32_t cPointersAllocated;
189 /** Number of entry instances allocated. This can be greater than the
190 * official array size. */
191 uint32_t cEntriesAllocated;
192 /** Number of array resizing calls (for increasing growth rate).
193 * Maintained by RTAsn1MemResizeArray(). */
194 uint16_t cResizeCalls;
195 /** Reserved / padding. */
196 uint16_t uReserved0;
197 /** Allocator vtable, NULL for the default allocator. */
198 PCRTASN1ALLOCATORVTABLE pAllocator;
199} RTASN1ARRAYALLOCATION;
200
201
202/**
203 * Allocate a block of zero initialized memory.
204 *
205 * @returns IPRT status code.
206 * @param pAllocation The allocation record (initialized by
207 * RTAsn1CursorInitAllocation or similar).
208 * @param ppvMem Where to return the pointer to the block.
209 * @param cbMem The minimum number of bytes to allocate.
210 */
211RTDECL(int) RTAsn1MemAllocZ(PRTASN1ALLOCATION pAllocation, void **ppvMem, size_t cbMem);
212
213/**
214 * Allocates a block of memory initialized to the content of @a pvSrc.
215 *
216 * @returns IPRT status code.
217 * @param pAllocation The allocation record (initialized by
218 * RTAsn1CursorInitAllocation or similar).
219 * @param ppvMem Where to return the pointer to the block.
220 * @param pvSrc The source memory.
221 * @param cbMem The minimum number of bytes to allocate.
222 */
223RTDECL(int) RTAsn1MemDup(PRTASN1ALLOCATION pAllocation, void **ppvMem, void const *pvSrc, size_t cbMem);
224
225/**
226 * Free a memory block.
227 *
228 * @param pAllocation The allocation record (initialized by
229 * RTAsn1CursorInitAllocation or similar).
230 * @param pv The memory block to free. NULL will be ignored.
231 */
232RTDECL(void) RTAsn1MemFree(PRTASN1ALLOCATION pAllocation, void *pv);
233
234/**
235 * Initalize an allocation.
236 *
237 * @returns pAllocation
238 * @param pAllocation The allocation record (initialized by
239 * RTAsn1CursorInitAllocation or similar).
240 * @param pAllocator The allocator
241 */
242RTDECL(PRTASN1ALLOCATION) RTAsn1MemInitAllocation(PRTASN1ALLOCATION pAllocation, PCRTASN1ALLOCATORVTABLE pAllocator);
243
244/**
245 * Initalize an array allocation.
246 *
247 * @returns pAllocation
248 * @param pAllocation The allocation record (initialized by
249 * RTAsn1CursorInitAllocation or similar).
250 * @param pAllocator The allocator
251 * @param cbEntry The entry size.
252 */
253RTDECL(PRTASN1ARRAYALLOCATION) RTAsn1MemInitArrayAllocation(PRTASN1ARRAYALLOCATION pAllocation,
254 PCRTASN1ALLOCATORVTABLE pAllocator, size_t cbEntry);
255
256/**
257 * Resize an array with zero initialized memory.
258 *
259 * @returns IPRT status code.
260 * @param pAllocation The allocation record (initialized by
261 * RTAsn1CursorInitAllocation or similar).
262 * @param ppapvArray Pointer to the variable pointing to the array. This is
263 * both input and output. Remains valid on failure.
264 * @param cCurrent The current entry count. (Relevant for zero
265 * initialization of the new entries.)
266 * @param cNew The new entry count.
267 */
268RTDECL(int) RTAsn1MemResizeArray(PRTASN1ARRAYALLOCATION pAllocation, void ***ppapvArray, uint32_t cCurrent, uint32_t cNew);
269
270/**
271 * Frees an array and all its entries.
272 *
273 * @param pAllocation The array allocation record (initialized by
274 * RTAsn1CursorInitArrayAllocation or similar).
275 * @param papvArray The array to free. NULL is ignored.
276 */
277RTDECL(void) RTAsn1MemFreeArray(PRTASN1ARRAYALLOCATION pAllocation, void **papvArray);
278
279
280/** Pointer to a core ASN.1 encoding info structure. */
281typedef struct RTASN1CORE *PRTASN1CORE;
282/** Pointer to a const core ASN.1 encoding info structure. */
283typedef struct RTASN1CORE const *PCRTASN1CORE;
284
285RTDECL(int) RTAsn1ContentAllocZ(struct RTASN1CORE *pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator);
286RTDECL(int) RTAsn1ContentDup(struct RTASN1CORE *pAsn1Core, void const *pvSrc, size_t cbSrc, PCRTASN1ALLOCATORVTABLE pAllocator);
287RTDECL(int) RTAsn1ContentReallocZ(struct RTASN1CORE *pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator);
288RTDECL(void) RTAsn1ContentFree(struct RTASN1CORE *pAsn1Core);
289
290
291
292/**
293 * ASN.1 object enumeration callback.
294 *
295 * @returns IPRT status code. VINF_SUCCESS continues the enumberation, all
296 * others quit it and is returned to the caller's caller.
297 * @param pAsn1Core The ASN.1 object we're called back about.
298 * @param pszName The member name. Array member names ends with
299 * '[#]'.
300 * @param uDepth The current depth.
301 * @param pvUser Callback user parameter.
302 */
303typedef DECLCALLBACK(int) FNRTASN1ENUMCALLBACK(struct RTASN1CORE *pAsn1Core, const char *pszName, uint32_t uDepth, void *pvUser);
304/** Pointer to an ASN.1 object enumeration callback. */
305typedef FNRTASN1ENUMCALLBACK *PFNRTASN1ENUMCALLBACK;
306
307/**
308 * ASN.1 object encoding writer callback.
309 *
310 * @returns IPRT status code.
311 * @param pbBuf Pointer to the bytes to output.
312 * @param cbToWrite The number of bytes to write.
313 * @param pvUser Callback user parameter.
314 * @param pErrInfo Where to store extended error info. Optional.
315 */
316typedef DECLCALLBACK(int) FNRTASN1ENCODEWRITER(const void *pvBuf, size_t cbToWrite, void *pvUser, PRTERRINFO pErrInfo);
317/** Pointer to an ASN.1 encoding writer callback. */
318typedef FNRTASN1ENCODEWRITER *PFNRTASN1ENCODEWRITER;
319
320/** @name ASN.1 Vtable Method Types
321 * @{ */
322
323/**
324 * Destructor.
325 *
326 * RTAsn1Destroy will first destroy all children by recursive calls to pfnEnum,
327 * afterwards it will call this method to release any memory or other resources
328 * associated with this object. The memory backing the object structure shall
329 * not be freed by this method.
330 *
331 * @param pThisCore Pointer to the ASN.1 core to destroy.
332 */
333typedef DECLCALLBACK(void) FNRTASN1COREVTDTOR(PRTASN1CORE pThisCore);
334/** Pointer to a FNRTASN1COREVTDTOR method. */
335typedef FNRTASN1COREVTDTOR *PFNRTASN1COREVTDTOR;
336
337/**
338 * Enumerate members (not necessary for primitive objects).
339 *
340 * @returns IPRT status code, any non VINF_SUCCESS value stems from pfnCallback.
341 * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
342 * @param pfnCallback The callback.
343 * @param uDepth The depth of this object. Children are at +1.
344 * @param pvUser Callback user argument.
345 */
346typedef DECLCALLBACK(int) FNRTASN1COREVTENUM(PRTASN1CORE pThisCore, PFNRTASN1ENUMCALLBACK pfnCallback,
347 uint32_t uDepth, void *pvUser);
348/** Pointer to a FNRTASN1COREVTENUM method. */
349typedef FNRTASN1COREVTENUM *PFNRTASN1COREVTENUM;
350
351/**
352 * Clone method.
353 *
354 * @param pThisCore Pointer to the ASN.1 core to initialize as a clone
355 * of pSrcClone. (The caller is responsible for making
356 * sure there is sufficent space and such.)
357 * @param pSrcCore The object to clone.
358 * @param pAllocator The allocator to use.
359 */
360typedef DECLCALLBACK(int) FNRTASN1COREVTCLONE(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore, PCRTASN1ALLOCATORVTABLE pAllocator);
361/** Pointer to a FNRTASN1COREVTCLONE method. */
362typedef FNRTASN1COREVTCLONE *PFNRTASN1COREVTCLONE;
363
364/**
365 * Compare method.
366 *
367 * The caller makes sure both cores are present and have the same Vtable.
368 *
369 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
370 * @param pLeftCore Pointer to the ASN.1 core of the left side object.
371 * @param pRightCore Pointer to the ASN.1 core of the right side object.
372 */
373typedef DECLCALLBACK(int) FNRTASN1COREVTCOMPARE(PCRTASN1CORE pLeftCore, PCRTASN1CORE pRightCore);
374/** Pointer to a FNRTASN1COREVTCOMPARE method. */
375typedef FNRTASN1COREVTCOMPARE *PFNRTASN1COREVTCOMPARE;
376
377/**
378 * Check sanity method.
379 *
380 * @returns IPRT status code.
381 * @param pThisCore Pointer to the ASN.1 core of the object to check out.
382 * @param fFlags See RTASN1_CHECK_SANITY_F_XXX.
383 * @param pErrInfo Where to return additional error details. Optional.
384 * @param pszErrorTag Tag for the additional error details.
385 */
386typedef DECLCALLBACK(int) FNRTASN1COREVTCHECKSANITY(PCRTASN1CORE pThisCore, uint32_t fFlags,
387 PRTERRINFO pErrInfo, const char *pszErrorTag);
388/** Pointer to a FNRTASN1COREVTCHECKSANITY method. */
389typedef FNRTASN1COREVTCHECKSANITY *PFNRTASN1COREVTCHECKSANITY;
390
391/**
392 * Optional encoding preparations.
393 *
394 * On successful return, the pThisCore->cb value shall be valid and up to date.
395 * Will be called for any present object, including ones with default values and
396 * similar.
397 *
398 * @returns IPRT status code
399 * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
400 * @param fFlags Encoding flags, RTASN1ENCODE_F_XXX.
401 * @param pErrInfo Where to return extra error information. Optional.
402 */
403typedef DECLCALLBACK(int) FNRTASN1COREVTENCODEPREP(PRTASN1CORE pThisCore, uint32_t fFlags, PRTERRINFO pErrInfo);
404/** Pointer to a FNRTASN1COREVTENCODEWRITE method. */
405typedef FNRTASN1COREVTENCODEPREP *PFNRTASN1COREVTENCODEPREP;
406
407/**
408 * Optional encoder writer.
409 *
410 * This writes the header as well as all the content. Will be called for any
411 * present object, including ones with default values and similar.
412 *
413 * @returns IPRT status code.
414 * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
415 * @param fFlags Encoding flags, RTASN1ENCODE_F_XXX.
416 * @param pfnWriter The output writer function.
417 * @param pvUser The user context for the writer function.
418 * @param pErrInfo Where to return extra error information. Optional.
419 */
420typedef DECLCALLBACK(int) FNRTASN1COREVTENCODEWRITE(PRTASN1CORE pThisCore, uint32_t fFlags, PFNRTASN1ENCODEWRITER pfnWriter,
421 void *pvUser, PRTERRINFO pErrInfo);
422/** Pointer to a FNRTASN1COREVTENCODEWRITE method. */
423typedef FNRTASN1COREVTENCODEWRITE *PFNRTASN1COREVTENCODEWRITE;
424/** @} */
425
426/** Mask of common flags. These will be propagated during sanity checking.
427 * Bits not in this mask are type specfic. */
428#define RTASN1_CHECK_SANITY_F_COMMON_MASK UINT32_C(0xffff0000)
429
430/**
431 * ASN.1 core vtable.
432 */
433typedef struct RTASN1COREVTABLE
434{
435 /** The name. */
436 const char *pszName;
437 /** Size of the structure. */
438 uint32_t cbStruct;
439 /** The default tag, UINT8_MAX if not applicable. */
440 uint8_t uDefaultTag;
441 /** The default class and flags. */
442 uint8_t fDefaultClass;
443 /** Reserved for later / alignment. */
444 uint16_t uReserved;
445 /** @copydoc FNRTASN1COREVTDTOR */
446 PFNRTASN1COREVTDTOR pfnDtor;
447 /** @copydoc FNRTASN1COREVTENUM */
448 PFNRTASN1COREVTENUM pfnEnum;
449 /** @copydoc FNRTASN1COREVTCLONE */
450 PFNRTASN1COREVTCLONE pfnClone;
451 /** @copydoc FNRTASN1COREVTCOMPARE */
452 PFNRTASN1COREVTCOMPARE pfnCompare;
453 /** @copydoc FNRTASN1COREVTCHECKSANITY */
454 PFNRTASN1COREVTCHECKSANITY pfnCheckSanity;
455 /** @copydoc FNRTASN1COREVTENCODEPREP */
456 PFNRTASN1COREVTENCODEPREP pfnEncodePrep;
457 /** @copydoc FNRTASN1COREVTENUM */
458 PFNRTASN1COREVTENCODEWRITE pfnEncodeWrite;
459} RTASN1COREVTABLE;
460/** Pointer to an ASN.1 allocator vtable. */
461typedef struct RTASN1COREVTABLE *PRTASN1COREVTABLE;
462/** Pointer to a const ASN.1 allocator vtable. */
463typedef RTASN1COREVTABLE const *PCRTASN1COREVTABLE;
464
465
466/** @name Helper macros for prototyping standard functions for an ASN.1 type.
467 * @{ */
468#define RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(a_TypeNm, a_DeclMacro, a_ImplExtNm) \
469 a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Init)(RT_CONCAT(P,a_TypeNm) pThis, PCRTASN1ALLOCATORVTABLE pAllocator); \
470 a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Clone)(RT_CONCAT(P,a_TypeNm) pThis, RT_CONCAT(PC,a_TypeNm) pSrc, \
471 PCRTASN1ALLOCATORVTABLE pAllocator); \
472 a_DeclMacro(void) RT_CONCAT(a_ImplExtNm,_Delete)(RT_CONCAT(P,a_TypeNm) pThis); \
473 a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Enum)(RT_CONCAT(P,a_TypeNm) pThis, PFNRTASN1ENUMCALLBACK pfnCallback, \
474 uint32_t uDepth, void *pvUser); \
475 a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Compare)(RT_CONCAT(PC,a_TypeNm) pLeft, RT_CONCAT(PC,a_TypeNm) pRight); \
476 a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, RT_CONCAT(P,a_TypeNm) pThis,\
477 const char *pszErrorTag); \
478 a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_CheckSanity)(RT_CONCAT(PC,a_TypeNm) pThis, uint32_t fFlags, \
479 PRTERRINFO pErrInfo, const char *pszErrorTag)
480
481
482/** @name Helper macros for prototyping standard functions for an ASN.1 type.
483 * @{ */
484#define RTASN1TYPE_STANDARD_PROTOTYPES(a_TypeNm, a_DeclMacro, a_ImplExtNm, a_Asn1CoreNm) \
485 DECL_FORCE_INLINE(PRTASN1CORE) RT_CONCAT(a_ImplExtNm,_GetAsn1Core)(RT_CONCAT(PC,a_TypeNm) pThis) \
486 { return (PRTASN1CORE)&pThis->a_Asn1CoreNm; } \
487 DECLINLINE(bool) RT_CONCAT(a_ImplExtNm,_IsPresent)(RT_CONCAT(PC,a_TypeNm) pThis) \
488 { return pThis && RTASN1CORE_IS_PRESENT(&pThis->a_Asn1CoreNm); } \
489 RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(a_TypeNm, a_DeclMacro, a_ImplExtNm)
490
491
492/** Aliases two ASN.1 types, no method aliases. */
493#define RTASN1TYPE_ALIAS_TYPE_ONLY(a_TypeNm, a_AliasType) \
494 typedef a_AliasType a_TypeNm; \
495 typedef a_TypeNm *RT_CONCAT(P,a_TypeNm); \
496 typedef a_TypeNm const *RT_CONCAT(PC,a_TypeNm)
497
498/** Aliases two ASN.1 types and methods. */
499#define RTASN1TYPE_ALIAS(a_TypeNm, a_AliasType, a_ImplExtNm, a_AliasExtNm) \
500 typedef a_AliasType a_TypeNm; \
501 typedef a_TypeNm *RT_CONCAT(P,a_TypeNm); \
502 \
503 DECLINLINE(PRTASN1CORE) RT_CONCAT(a_ImplExtNm,_GetAsn1Core)(a_TypeNm const *pThis) \
504 { return RT_CONCAT(a_AliasExtNm,_GetAsn1Core)(pThis); } \
505 DECLINLINE(bool) RT_CONCAT(a_ImplExtNm,_IsPresent)(a_TypeNm const *pThis) \
506 { return RT_CONCAT(a_AliasExtNm,_IsPresent)(pThis); } \
507 \
508 DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Init)(RT_CONCAT(P,a_TypeNm) pThis, PCRTASN1ALLOCATORVTABLE pAllocator) \
509 { return RT_CONCAT(a_AliasExtNm,_Init)(pThis, pAllocator); } \
510 DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Clone)(RT_CONCAT(P,a_TypeNm) pThis, a_TypeNm const *pSrc, \
511 PCRTASN1ALLOCATORVTABLE pAllocator) \
512 { return RT_CONCAT(a_AliasExtNm,_Clone)(pThis, pSrc, pAllocator); } \
513 DECLINLINE(void) RT_CONCAT(a_ImplExtNm,_Delete)(RT_CONCAT(P,a_TypeNm) pThis) \
514 { RT_CONCAT(a_AliasExtNm,_Delete)(pThis); } \
515 DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Enum)(a_TypeNm *pThis, PFNRTASN1ENUMCALLBACK pfnCallback, \
516 uint32_t uDepth, void *pvUser) \
517 { return RT_CONCAT(a_AliasExtNm,_Enum)(pThis, pfnCallback, uDepth, pvUser); } \
518 DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Compare)(a_TypeNm const *pLeft, a_TypeNm const *pRight) \
519 { return RT_CONCAT(a_AliasExtNm,_Compare)(pLeft, pRight); } \
520 DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, RT_CONCAT(P,a_TypeNm) pThis,\
521 const char *pszErrorTag) \
522 { return RT_CONCAT(a_AliasExtNm,_DecodeAsn1)(pCursor, fFlags, pThis, pszErrorTag); } \
523 DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_CheckSanity)(a_TypeNm const *pThis, uint32_t fFlags, \
524 PRTERRINFO pErrInfo, const char *pszErrorTag) \
525 { return RT_CONCAT(a_AliasExtNm,_CheckSanity)(pThis, fFlags, pErrInfo, pszErrorTag); } \
526 \
527 typedef a_TypeNm const *RT_CONCAT(PC,a_TypeNm)
528
529/** @} */
530
531
532/**
533 * Core ASN.1 structure for storing encoding details and data location.
534 *
535 * This is used as a 'parent' for all other decoded ASN.1 based structures.
536 */
537typedef struct RTASN1CORE
538{
539 /** The tag.
540 * @remarks 32-bit should be enough for everyone... We don't currently
541 * implement decoding tags larger than 30 anyway. :-) */
542 uint32_t uTag;
543 /** Tag class and flags (ASN1_TAGCLASS_XXX and ASN1_TAGFLAG_XXX). */
544 uint8_t fClass;
545 /** The real tag value for IMPLICT tag overrides. */
546 uint8_t uRealTag;
547 /** The real class value for IMPLICT tag overrides. */
548 uint8_t fRealClass;
549 /** The size of the tag and length ASN.1 header. */
550 uint8_t cbHdr;
551 /** Length. */
552 uint32_t cb;
553 /** IPRT flags (RTASN1CORE_F_XXX). */
554 uint32_t fFlags;
555 /** Pointer to the data.
556 * After decoding this generally points to the encoded data content. When
557 * preparting something for encoding or otherwise constructing things in memory,
558 * this generally points heap memory or read-only constants.
559 * @sa RTAsn1ContentAllocZ, RTAsn1ContentReallocZ, RTAsn1ContentDup,
560 * RTAsn1ContentFree. */
561 RTCPTRUNION uData;
562 /** Pointer to the virtual method table for this object. Optional. */
563 PCRTASN1COREVTABLE pOps;
564} RTASN1CORE;
565/** The Vtable for a RTASN1CORE structure when not in some way use used as a
566 * parent type/class. */
567extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Core_Vtable;
568
569RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(RTASN1CORE, RTDECL, RTAsn1Core);
570
571/** @name RTASN1CORE_F_XXX - Flags for RTASN1CORE::fFlags
572 * @{ */
573/** Present/valid. */
574#define RTASN1CORE_F_PRESENT RT_BIT_32(0)
575/** Not present in stream, using default value. */
576#define RTASN1CORE_F_DEFAULT RT_BIT_32(1)
577/** The tag was overriden by an implict context tag or some such thing,
578 * RTASN1CORE::uImplicitTag hold the universal tag value if one exists. */
579#define RTASN1CORE_F_TAG_IMPLICIT RT_BIT_32(2)
580/** Primitive tag with the corresponding RTASN1XXX struct. */
581#define RTASN1CORE_F_PRIMITE_TAG_STRUCT RT_BIT_32(3)
582/** Dummy node typically used with choices, has children, not encoded, must be
583 * ignored. */
584#define RTASN1CORE_F_DUMMY RT_BIT_32(4)
585/** Allocated content (pointed to by uData).
586 * The content should is still be considered 104% read-only by anyone other
587 * than then type methods (pOps and associates). */
588#define RTASN1CORE_F_ALLOCATED_CONTENT RT_BIT_32(5)
589/** Decoded content (pointed to by uData).
590 * Mutually exclusive with RTASN1CORE_F_ALLOCATED_CONTENT. If neither is
591 * set, uData might be NULL or point to some shared static memory for
592 * frequently used values. */
593#define RTASN1CORE_F_DECODED_CONTENT RT_BIT_32(6)
594/** @} */
595
596
597/** Check s whether an ASN.1 core object present in some way (default data,
598 * decoded data, ...). */
599#define RTASN1CORE_IS_PRESENT(a_pAsn1Core) ( RT_BOOL((a_pAsn1Core)->fFlags) )
600
601/** Check s whether an ASN.1 core object is a dummy object (and is present). */
602#define RTASN1CORE_IS_DUMMY(a_pAsn1Core) ( RT_BOOL((a_pAsn1Core)->fFlags & RTASN1CORE_F_DUMMY) )
603
604/**
605 * Calculates pointer to the raw ASN.1 record.
606 *
607 * ASSUMES that it's decoded content and that cbHdr and uData are both valid.
608 *
609 * @returns Byte pointer to the first tag byte.
610 * @param a_pAsn1Core The ASN.1 core.
611 */
612#define RTASN1CORE_GET_RAW_ASN1_PTR(a_pAsn1Core) ( (a_pAsn1Core)->uData.pu8 - (a_pAsn1Core)->cbHdr )
613
614/**
615 * Calculates the length of the raw ASN.1 record to go with the
616 * RTASN1CORE_GET_RAW_ASN1_PTR() result.
617 *
618 * ASSUMES that it's decoded content and that cbHdr and uData are both valid.
619 *
620 * @returns Size in bytes (uint32_t).
621 * @param a_pAsn1Core The ASN.1 core.
622 */
623#define RTASN1CORE_GET_RAW_ASN1_SIZE(a_pAsn1Core) ( (a_pAsn1Core)->cbHdr + (a_pAsn1Core)->cb )
624
625/**
626 * Retrievs the tag or implicit tag depending on the RTASN1CORE_F_TAG_IMPLICIT
627 * flag.
628 *
629 * @returns The ASN.1 tag of the object.
630 * @param a_pAsn1Core The ASN.1 core.
631 */
632#define RTASN1CORE_GET_TAG(a_pAsn1Core) ( !((a_pAsn1Core)->fFlags & RTASN1CORE_F_TAG_IMPLICIT) ? (a_pAsn1Core)->uTag : (a_pAsn1Core)->uRealTag )
633
634
635DECL_FORCE_INLINE(PRTASN1CORE) RTAsn1Core_GetAsn1Core(PCRTASN1CORE pThis)
636{
637 return (PRTASN1CORE)pThis;
638}
639
640
641DECL_FORCE_INLINE(bool) RTAsn1Core_IsPresent(PCRTASN1CORE pThis)
642{
643 return pThis && RTASN1CORE_IS_PRESENT(pThis);
644}
645
646
647RTDECL(int) RTAsn1Core_InitEx(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass, PCRTASN1COREVTABLE pOps, uint32_t fFlags);
648/**
649 * Initialize the ASN.1 core object representation to a default value.
650 *
651 * @returns VINF_SUCCESS
652 * @param pAsn1Core The ASN.1 core.
653 * @param uTag The tag number.
654 * @param fClass The tag class and flags.
655 */
656RTDECL(int) RTAsn1Core_InitDefault(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass);
657RTDECL(int) RTAsn1Core_CloneContent(PRTASN1CORE pThis, PCRTASN1CORE pSrc, PCRTASN1ALLOCATORVTABLE pAllocator);
658RTDECL(int) RTAsn1Core_CloneNoContent(PRTASN1CORE pThis, PCRTASN1CORE pSrc);
659RTDECL(int) RTAsn1Core_SetTagAndFlags(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass);
660RTDECL(int) RTAsn1Core_ChangeTag(PRTASN1CORE pAsn1Core, uint32_t uTag);
661RTDECL(void) RTAsn1Core_ResetImplict(PRTASN1CORE pThis);
662RTDECL(int) RTAsn1Core_CompareEx(PCRTASN1CORE pLeft, PCRTASN1CORE pRight, bool fIgnoreTagAndClass);
663
664
665/**
666 * Dummy ASN.1 object for use in choices and similar non-sequence structures.
667 *
668 * This allows hooking up destructors, enumerators and such, as well as not
669 * needing custom code for sequence-of / set-of collections.
670 */
671typedef struct RTASN1DUMMY
672{
673 /** Core ASN.1. */
674 RTASN1CORE Asn1Core;
675} RTASN1DUMMY;
676/** Pointer to a dummy record. */
677typedef RTASN1DUMMY *PRTASN1DUMMY;
678
679
680/**
681 * Initalizes a dummy ASN.1 object.
682 *
683 * @returns VINF_SUCCESS.
684 * @param pThis The dummy object.
685 */
686RTDECL(int) RTAsn1Dummy_InitEx(PRTASN1DUMMY pThis);
687
688/**
689 * Standard compliant initalizer.
690 *
691 * @returns VINF_SUCCESS.
692 * @param pThis The dummy object.
693 * @param pAllocator Ignored.
694 */
695DECLINLINE(int) RTAsn1Dummy_Init(PRTASN1DUMMY pThis, PCRTASN1ALLOCATORVTABLE pAllocator)
696{
697 NOREF(pAllocator);
698 return RTAsn1Dummy_InitEx(pThis);
699}
700
701
702/**
703 * ASN.1 sequence core (IPRT representation).
704 */
705typedef struct RTASN1SEQUENCECORE
706{
707 /** Core ASN.1 encoding details. */
708 RTASN1CORE Asn1Core;
709} RTASN1SEQUENCECORE;
710/** Pointer to an ASN.1 sequence core (IPRT representation). */
711typedef RTASN1SEQUENCECORE *PRTASN1SEQUENCECORE;
712/** Pointer to a const ASN.1 sequence core (IPRT representation). */
713typedef RTASN1SEQUENCECORE const *PCRTASN1SEQUENCECORE;
714
715RTDECL(int) RTAsn1SequenceCore_Init(PRTASN1SEQUENCECORE pSeqCore, PCRTASN1COREVTABLE pVtable);
716RTDECL(int) RTAsn1SequenceCore_Clone(PRTASN1SEQUENCECORE pSeqCore, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQUENCECORE pSrc);
717
718/**
719 * ASN.1 sequence-of core (IPRT representation).
720 */
721#if 0
722typedef struct RTASN1SEQOFCORE
723{
724 /** Core ASN.1 encoding details. */
725 RTASN1CORE Asn1Core;
726} RTASN1SEQUENCECORE;
727/** Pointer to an ASN.1 sequence-of core (IPRT representation). */
728typedef RTASN1SEQUENCECORE *PRTASN1SEQUENCECORE;
729/** Pointer to a const ASN.1 sequence-of core (IPRT representation). */
730typedef RTASN1SEQUENCECORE const *PCRTASN1SEQUENCECORE;
731#else
732# define RTASN1SEQOFCORE RTASN1SEQUENCECORE
733# define PRTASN1SEQOFCORE PRTASN1SEQUENCECORE
734# define PCRTASN1SEQOFCORE PCRTASN1SEQUENCECORE
735#endif
736RTDECL(int) RTAsn1SeqOfCore_Init(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable);
737RTDECL(int) RTAsn1SeqOfCore_Clone(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQOFCORE pSrc);
738
739
740/** Defines the typedefs and prototypes for a generic sequence-of type. */
741#define RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(a_SeqOfType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
742 typedef struct a_SeqOfType \
743 { \
744 /** Sequence core. */ \
745 RTASN1SEQUENCECORE SeqCore; \
746 /** The array allocation tracker. */ \
747 RTASN1ARRAYALLOCATION Allocation; \
748 /** Items in the array. */ \
749 uint32_t cItems; \
750 /** Array. */ \
751 RT_CONCAT(P,a_ItemType) *papItems; \
752 } a_SeqOfType; \
753 typedef a_SeqOfType *RT_CONCAT(P,a_SeqOfType); \
754 typedef a_SeqOfType const *RT_CONCAT(PC,a_SeqOfType); \
755 RTASN1TYPE_STANDARD_PROTOTYPES(a_SeqOfType, a_DeclMacro, a_ImplExtNm, SeqCore.Asn1Core)
756
757
758/**
759 * ASN.1 set core (IPRT representation).
760 */
761typedef struct RTASN1SETCORE
762{
763 /** Core ASN.1 encoding details. */
764 RTASN1CORE Asn1Core;
765} RTASN1SETCORE;
766/** Pointer to an ASN.1 set core (IPRT representation). */
767typedef RTASN1SETCORE *PRTASN1SETCORE;
768/** Pointer to a const ASN.1 set core (IPRT representation). */
769typedef RTASN1SETCORE const *PCRTASN1SETCORE;
770
771RTDECL(int) RTAsn1SetCore_Init(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable);
772RTDECL(int) RTAsn1SetCore_Clone(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETCORE pSrc);
773
774/**
775 * ASN.1 set-of core (IPRT representation).
776 */
777#if 0
778typedef struct RTASN1SETOFCORE
779{
780 /** Core ASN.1 encoding details. */
781 RTASN1CORE Asn1Core;
782} RTASN1SETUENCECORE;
783/** Pointer to an ASN.1 set-of core (IPRT representation). */
784typedef RTASN1SETUENCECORE *PRTASN1SETUENCECORE;
785/** Pointer to a const ASN.1 set-of core (IPRT representation). */
786typedef RTASN1SETUENCECORE const *PCRTASN1SETUENCECORE;
787#else
788# define RTASN1SETOFCORE RTASN1SETCORE
789# define PRTASN1SETOFCORE PRTASN1SETCORE
790# define PCRTASN1SETOFCORE PCRTASN1SETCORE
791#endif
792RTDECL(int) RTAsn1SetOfCore_Init(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable);
793RTDECL(int) RTAsn1SetOfCore_Clone(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETOFCORE pSrc);
794
795
796/** Defines the typedefs and prototypes for a generic set-of type. */
797#define RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(a_SetOfType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
798 typedef struct a_SetOfType \
799 { \
800 /** Set core. */ \
801 RTASN1SETCORE SetCore; \
802 /** The array allocation tracker. */ \
803 RTASN1ARRAYALLOCATION Allocation; \
804 /** Items in the array. */ \
805 uint32_t cItems; \
806 /** Array. */ \
807 RT_CONCAT(P,a_ItemType) *papItems; \
808 } a_SetOfType; \
809 typedef a_SetOfType *RT_CONCAT(P,a_SetOfType); \
810 typedef a_SetOfType const *RT_CONCAT(PC,a_SetOfType); \
811 RTASN1TYPE_STANDARD_PROTOTYPES(a_SetOfType, a_DeclMacro, a_ImplExtNm, SetCore.Asn1Core)
812
813
814/*
815 * Declare sets and sequences of the core structure.
816 */
817RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFCORES, RTASN1CORE, RTDECL, RTAsn1SeqOfCores);
818RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFCORES, RTASN1CORE, RTDECL, RTAsn1SetOfCores);
819
820
821/**
822 * ASN.1 null (IPRT representation).
823 */
824typedef struct RTASN1NULL
825{
826 /** Core ASN.1 encoding details. */
827 RTASN1CORE Asn1Core;
828} RTASN1NULL;
829/** Pointer to an ASN.1 null (IPRT representation). */
830typedef RTASN1NULL *PRTASN1NULL;
831/** Pointer to a const ASN.1 null (IPRT representation). */
832typedef RTASN1NULL const *PCRTASN1NULL;
833/** The Vtable for a RTASN1NULL structure. */
834extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Null_Vtable;
835
836RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1NULL, RTDECL, RTAsn1Null, Asn1Core);
837
838
839/**
840 * ASN.1 integer (IPRT representation).
841 */
842typedef struct RTASN1INTEGER
843{
844 /** Core ASN.1 encoding details. */
845 RTASN1CORE Asn1Core;
846 /** The unsigned C representation of the 64 least significant bits.
847 * @note A ASN.1 integer doesn't define signed/unsigned and can have any
848 * length you like. Thus, the user needs to check the size and
849 * preferably use the access APIs for signed numbers. */
850 RTUINT64U uValue;
851} RTASN1INTEGER;
852/** Pointer to an ASN.1 integer (IPRT representation). */
853typedef RTASN1INTEGER *PRTASN1INTEGER;
854/** Pointer to a const ASN.1 integer (IPRT representation). */
855typedef RTASN1INTEGER const *PCRTASN1INTEGER;
856/** The Vtable for a RTASN1INTEGER structure. */
857extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Integer_Vtable;
858
859RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1INTEGER, RTDECL, RTAsn1Integer, Asn1Core);
860
861/**
862 * Initializes an interger object to a default value.
863 * @returns VINF_SUCCESS.
864 * @param pInteger The integer object representation.
865 * @param uValue The default value (unsigned 64-bit).
866 * @param pAllocator The allocator (pro forma).
867 */
868RTDECL(int) RTAsn1Integer_InitDefault(PRTASN1INTEGER pInteger, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator);
869
870RTDECL(int) RTAsn1Integer_InitU64(PRTASN1INTEGER pThis, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator);
871
872/**
873 * Get the most significat bit that's set (1).
874 *
875 * @returns 0-base bit number, -1 if all clear.
876 * @param pInteger The integer to check.
877 */
878RTDECL(int32_t) RTAsn1Integer_UnsignedLastBit(PCRTASN1INTEGER pInteger);
879
880/**
881 * Compares two ASN.1 unsigned integers.
882 *
883 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
884 * @param pLeft The first ASN.1 integer.
885 * @param pRight The second ASN.1 integer.
886 */
887RTDECL(int) RTAsn1Integer_UnsignedCompare(PCRTASN1INTEGER pLeft, PCRTASN1INTEGER pRight);
888
889/**
890 * Compares an ASN.1 unsigned integer with a uint64_t.
891 *
892 * @returns 0 if equal, -1 if @a pInteger is smaller, 1 if @a pInteger is
893 * larger.
894 * @param pInteger The ASN.1 integer to treat as unsigned.
895 * @param u64Const The uint64_t constant to compare with.
896 */
897RTDECL(int) RTAsn1Integer_UnsignedCompareWithU64(PCRTASN1INTEGER pInteger, uint64_t u64Const);
898
899/**
900 * Compares an ASN.1 unsigned integer with a uint32_t.
901 *
902 * @returns 0 if equal, -1 if @a pInteger is smaller, 1 if @a pInteger is
903 * larger.
904 * @param pInteger The ASN.1 integer to treat as unsigned.
905 * @param u32Const The uint32_t constant to compare with.
906 * @remarks We don't bother with U16 and U8 variants, just use this instead.
907 */
908RTDECL(int) RTAsn1Integer_UnsignedCompareWithU32(PCRTASN1INTEGER pInteger, uint32_t u32Const);
909
910
911/**
912 * Initializes a big integer number from an ASN.1 integer.
913 *
914 * @returns IPRT status code.
915 * @param pInteger The ASN.1 integer.
916 * @param pBigNum The big integer number structure to initialize.
917 * @param fBigNumInit Subset of RTBIGNUMINIT_F_XXX that concerns
918 * senitivity, signedness and endianness.
919 */
920RTDECL(int) RTAsn1Integer_ToBigNum(PCRTASN1INTEGER pInteger, PRTBIGNUM pBigNum, uint32_t fBigNumInit);
921RTDECL(int) RTAsn1Integer_FromBigNum(PRTASN1INTEGER pThis, PCRTBIGNUM pBigNum, PCRTASN1ALLOCATORVTABLE pAllocator);
922
923/**
924 * Converts the integer to a string.
925 *
926 * This will produce a hex represenation of the number. If it fits in 64-bit, a
927 * C style hex number will be produced. If larger than 64-bit, it will be
928 * printed as a space separated string of hex bytes.
929 *
930 * @returns IPRT status code.
931 * @param pThis The ASN.1 integer.
932 * @param pszBuf The output buffer.
933 * @param cbBuf The buffer size.
934 * @param fFlags Flags reserved for future exploits. MBZ.
935 * @param pcbActual Where to return the amount of buffer space used
936 * (i.e. including terminator). Optional.
937 *
938 * @remarks Currently assume unsigned number.
939 */
940RTDECL(int) RTAsn1Integer_ToString(PRTASN1INTEGER pThis, char *pszBuf, size_t cbBuf, uint32_t fFlags, size_t *pcbActual);
941
942RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFINTEGERS, RTASN1INTEGER, RTDECL, RTAsn1SeqOfIntegers);
943RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFINTEGERS, RTASN1INTEGER, RTDECL, RTAsn1SetOfIntegers);
944
945
946
947/**
948 * ASN.1 boolean (IPRT representation).
949 */
950typedef struct RTASN1BOOLEAN
951{
952 /** Core ASN.1 encoding details. */
953 RTASN1CORE Asn1Core;
954 /** The boolean value. */
955 bool fValue;
956} RTASN1BOOLEAN;
957/** Pointer to the IPRT representation of an ASN.1 boolean. */
958typedef RTASN1BOOLEAN *PRTASN1BOOLEAN;
959/** Pointer to the const IPRT representation of an ASN.1 boolean. */
960typedef RTASN1BOOLEAN const *PCRTASN1BOOLEAN;
961/** The Vtable for a RTASN1BOOLEAN structure. */
962extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Boolean_Vtable;
963
964RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1BOOLEAN, RTDECL, RTAsn1Boolean, Asn1Core);
965
966/**
967 * Initializes a boolean object to a default value.
968 * @returns VINF_SUCCESS
969 * @param pBoolean The boolean object representation.
970 * @param fValue The default value.
971 * @param pAllocator The allocator (pro forma).
972 */
973RTDECL(int) RTAsn1Boolean_InitDefault(PRTASN1BOOLEAN pBoolean, bool fValue, PCRTASN1ALLOCATORVTABLE pAllocator);
974RTDECL(int) RTAsn1Boolean_Set(PRTASN1BOOLEAN pThis, bool fValue);
975
976RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFBOOLEANS, RTASN1BOOLEAN, RTDECL, RTAsn1SeqOfBooleans);
977RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFBOOLEANS, RTASN1BOOLEAN, RTDECL, RTAsn1SetOfBooleans);
978
979
980
981/**
982 * ASN.1 UTC and Generalized Time (IPRT representation).
983 *
984 * The two time types only differs in the precision the render (UTC time being
985 * the one for which you go "WTF were they thinking?!!" for in 2014).
986 */
987typedef struct RTASN1TIME
988{
989 /** The core structure, either ASN1_TAG_UTC_TIME or
990 * ASN1_TAG_GENERALIZED_TIME. */
991 RTASN1CORE Asn1Core;
992 /** The exploded time. */
993 RTTIME Time;
994} RTASN1TIME;
995/** Pointer to an IPRT representation of ASN.1 UTC/Generalized time. */
996typedef RTASN1TIME *PRTASN1TIME;
997/** Pointer to a const IPRT representation of ASN.1 UTC/Generalized time. */
998typedef RTASN1TIME const *PCRTASN1TIME;
999/** The Vtable for a RTASN1TIME structure. */
1000extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Time_Vtable;
1001
1002RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1Time, Asn1Core);
1003
1004RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1UtcTime, Asn1Core);
1005RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1GeneralizedTime, Asn1Core);
1006
1007/**
1008 * Compares two ASN.1 time values.
1009 *
1010 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
1011 * @param pLeft The first ASN.1 time object.
1012 * @param pTsRight The second time to compare.
1013 */
1014RTDECL(int) RTAsn1Time_CompareWithTimeSpec(PCRTASN1TIME pLeft, PCRTTIMESPEC pTsRight);
1015
1016/** @name Predicate macros for determing the exact type of RTASN1TIME.
1017 * @{ */
1018/** True if UTC time. */
1019#define RTASN1TIME_IS_UTC_TIME(a_pAsn1Time) ((a_pAsn1Time)->Asn1Core.uTag == ASN1_TAG_UTC_TIME)
1020/** True if generalized time. */
1021#define RTASN1TIME_IS_GENERALIZED_TIME(a_pAsn1Time) ((a_pAsn1Time)->Asn1Core.uTag == ASN1_TAG_GENERALIZED_TIME)
1022/** @} */
1023
1024RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFTIMES, RTASN1TIME, RTDECL, RTAsn1SeqOfTimes);
1025RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFTIMES, RTASN1TIME, RTDECL, RTAsn1SetOfTimes);
1026
1027
1028
1029/**
1030 * ASN.1 object identifier (IPRT representation).
1031 */
1032typedef struct RTASN1OBJID
1033{
1034 /** Core ASN.1 encoding details. */
1035 RTASN1CORE Asn1Core;
1036 /** Coverning the paComponents memory allocation if there isn't enough room in
1037 * szObjId for both the dottet string and the component values. */
1038 RTASN1ALLOCATION Allocation;
1039 /** Pointer to an array with the component values.
1040 * This may point within szObjId if there is enough space for both there. */
1041 uint32_t const *pauComponents;
1042 /** The number of components in the object identifier.
1043 * This ASSUMES that nobody will be ever needing more than 255 components. */
1044 uint8_t cComponents;
1045 /** The dotted string representation of the object identifier.
1046 * If there is sufficient space after the string, we will place the array that
1047 * paComponents points to here and/or the raw content bytes (Asn1Core.uData).
1048 *
1049 * An analysis of dumpasn1.cfg, hl7.org and our own _OID defines indicates
1050 * that we need space for at least 10 components and 30-something chars. We've
1051 * allocated 87 bytes, which we ASSUME should be enough for everyone. */
1052 char szObjId[87];
1053} RTASN1OBJID;
1054/** Pointer to an ASN.1 object identifier representation. */
1055typedef RTASN1OBJID *PRTASN1OBJID;
1056/** Pointer to a const ASN.1 object identifier representation. */
1057typedef RTASN1OBJID const *PCRTASN1OBJID;
1058/** The Vtable for a RTASN1OBJID structure. */
1059extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1ObjId_Vtable;
1060
1061RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1OBJID, RTDECL, RTAsn1ObjId, Asn1Core);
1062
1063RTDECL(int) RTAsn1ObjId_InitFromString(PRTASN1OBJID pThis, const char *pszObjId, PCRTASN1ALLOCATORVTABLE pAllocator);
1064
1065/**
1066 * Compares an ASN.1 object identifier with a dotted object identifier string.
1067 *
1068 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
1069 * @param pThis The ASN.1 object identifier.
1070 * @param pszRight The dotted object identifier string.
1071 */
1072RTDECL(int) RTAsn1ObjId_CompareWithString(PCRTASN1OBJID pThis, const char *pszRight);
1073
1074/**
1075 * Checks if an ASN.1 object identifier starts with the given dotted object
1076 * identifier string.
1077 *
1078 * The matching is only successful if the given string matches matches the last
1079 * component completely.
1080 *
1081 * @returns true / false.
1082 * @param pThis The ASN.1 object identifier.
1083 * @param pszStartsWith The dotted object identifier string.
1084 */
1085RTDECL(bool) RTAsn1ObjId_StartsWith(PCRTASN1OBJID pThis, const char *pszStartsWith);
1086
1087RTDECL(uint8_t) RTAsn1ObjIdCountComponents(PCRTASN1OBJID pThis);
1088RTDECL(uint32_t) RTAsn1ObjIdGetComponentsAsUInt32(PCRTASN1OBJID pThis, uint8_t iComponent);
1089RTDECL(uint32_t) RTAsn1ObjIdGetLastComponentsAsUInt32(PCRTASN1OBJID pThis);
1090
1091RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFOBJIDS, RTASN1OBJID, RTDECL, RTAsn1SeqOfObjIds);
1092RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOBJIDS, RTASN1OBJID, RTDECL, RTAsn1SetOfObjIds);
1093RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOBJIDSEQS, RTASN1SEQOFOBJIDS, RTDECL, RTAsn1SetOfObjIdSeqs);
1094
1095
1096/**
1097 * ASN.1 bit string (IPRT representation).
1098 */
1099typedef struct RTASN1BITSTRING
1100{
1101 /** Core ASN.1 encoding details. */
1102 RTASN1CORE Asn1Core;
1103 /** The number of bits. */
1104 uint32_t cBits;
1105 /** The max number of bits (given at decoding / construction). */
1106 uint32_t cMaxBits;
1107 /** Pointer to the bits. */
1108 RTCPTRUNION uBits;
1109 /** Pointer to user structure encapsulated in this string, if dynamically
1110 * allocated the EncapsulatedAllocation member can be used to track it and
1111 * trigger automatic cleanup on object destruction. If EncapsulatedAllocation
1112 * is zero, any object pointed to will only be deleted. */
1113 PRTASN1CORE pEncapsulated;
1114 /** Allocation tracking structure for pEncapsulated. */
1115 RTASN1ALLOCATION EncapsulatedAllocation;
1116} RTASN1BITSTRING;
1117/** Pointer to the IPRT representation of an ASN.1 bit string. */
1118typedef RTASN1BITSTRING *PRTASN1BITSTRING;
1119/** Pointer to the const IPRT representation of an ASN.1 bit string. */
1120typedef RTASN1BITSTRING const *PCRTASN1BITSTRING;
1121/** The Vtable for a RTASN1BITSTRING structure. */
1122extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1BitString_Vtable;
1123
1124RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1BITSTRING, RTDECL, RTAsn1BitString, Asn1Core);
1125
1126/**
1127 * Calculates pointer to the first bit.
1128 *
1129 * @returns Byte pointer to the first bit.
1130 * @param a_pBitString The ASN.1 bit string.
1131 */
1132#define RTASN1BITSTRING_GET_BIT0_PTR(a_pBitString) ( &(a_pBitString)->Asn1Core.uData.pu8[1] )
1133
1134/**
1135 * Calculates the size in bytes.
1136 *
1137 * @returns Rounded up size in bytes.
1138 * @param a_pBitString The ASN.1 bit string.
1139 */
1140#define RTASN1BITSTRING_GET_BYTE_SIZE(a_pBitString) ( ((a_pBitString)->cBits + 7U) >> 3 )
1141
1142RTDECL(int) RTAsn1BitString_DecodeAsn1Ex(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t cMaxBits, PRTASN1BITSTRING pThis,
1143 const char *pszErrorTag);
1144RTDECL(uint64_t) RTAsn1BitString_GetAsUInt64(PCRTASN1BITSTRING pThis);
1145
1146RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFBITSTRINGS, RTASN1BITSTRING, RTDECL, RTAsn1SeqOfBitStrings);
1147RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFBITSTRINGS, RTASN1BITSTRING, RTDECL, RTAsn1SetOfBitStrings);
1148
1149
1150/**
1151 * ASN.1 octet string (IPRT representation).
1152 */
1153typedef struct RTASN1OCTETSTRING
1154{
1155 /** Core ASN.1 encoding details. */
1156 RTASN1CORE Asn1Core;
1157 /** Pointer to user structure encapsulated in this string.
1158 *
1159 * If dynamically allocated the EncapsulatedAllocation member can be used to
1160 * track it and trigger automatic cleanup on object destruction. If
1161 * EncapsulatedAllocation is zero, any object pointed to will only be
1162 * deleted. */
1163 PRTASN1CORE pEncapsulated;
1164 /** Allocation tracking structure for pEncapsulated. */
1165 RTASN1ALLOCATION EncapsulatedAllocation;
1166} RTASN1OCTETSTRING;
1167/** Pointer to the IPRT representation of an ASN.1 octet string. */
1168typedef RTASN1OCTETSTRING *PRTASN1OCTETSTRING;
1169/** Pointer to the const IPRT representation of an ASN.1 octet string. */
1170typedef RTASN1OCTETSTRING const *PCRTASN1OCTETSTRING;
1171/** The Vtable for a RTASN1OCTETSTRING structure. */
1172extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1OctetString_Vtable;
1173
1174RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1OCTETSTRING, RTDECL, RTAsn1OctetString, Asn1Core);
1175
1176RTDECL(int) RTAsn1OctetStringCompare(PCRTASN1OCTETSTRING pLeft, PCRTASN1OCTETSTRING pRight);
1177
1178RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFOCTETSTRINGS, RTASN1OCTETSTRING, RTDECL, RTAsn1SeqOfOctetStrings);
1179RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOCTETSTRINGS, RTASN1OCTETSTRING, RTDECL, RTAsn1SetOfOctetStrings);
1180
1181
1182/**
1183 * ASN.1 string (IPRT representation).
1184 * All char string types except 'character string (29)'.
1185 */
1186typedef struct RTASN1STRING
1187{
1188 /** Core ASN.1 encoding details. */
1189 RTASN1CORE Asn1Core;
1190 /** Allocation tracking for pszUtf8. */
1191 RTASN1ALLOCATION Allocation;
1192 /** If conversion to UTF-8 was requested, we cache that here. */
1193 char const *pszUtf8;
1194 /** The length (chars, not code points) of the above UTF-8 string if
1195 * present. */
1196 uint32_t cchUtf8;
1197} RTASN1STRING;
1198/** Pointer to the IPRT representation of an ASN.1 string. */
1199typedef RTASN1STRING *PRTASN1STRING;
1200/** Pointer to the const IPRT representation of an ASN.1 string. */
1201typedef RTASN1STRING const *PCRTASN1STRING;
1202/** The Vtable for a RTASN1STRING structure. */
1203extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1String_Vtable;
1204
1205RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1String, Asn1Core);
1206
1207/** @name String type predicate macros.
1208 * @{ */
1209#define RTASN1STRING_IS_NUMERIC(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_NUMERIC_STRING )
1210#define RTASN1STRING_IS_PRINTABLE(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_PRINTABLE_STRING )
1211#define RTASN1STRING_IS_T61(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_T61_STRING )
1212#define RTASN1STRING_IS_VIDEOTEX(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_VIDEOTEX_STRING )
1213#define RTASN1STRING_IS_VISIBLE(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_VISIBLE_STRING )
1214#define RTASN1STRING_IS_IA5(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_IA5_STRING )
1215#define RTASN1STRING_IS_GRAPHIC(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_GRAPHIC_STRING )
1216#define RTASN1STRING_IS_GENERAL(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_GENERAL_STRING )
1217/** UTF-8. */
1218#define RTASN1STRING_IS_UTF8(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_UTF8_STRING )
1219/** UCS-2. */
1220#define RTASN1STRING_IS_BMP(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_BMP_STRING )
1221/** UCS-4. */
1222#define RTASN1STRING_IS_UNIVERSAL(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_UNIVERSAL_STRING )
1223/** @} */
1224
1225RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1NumericString, Asn1Core);
1226RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1PrintableString, Asn1Core);
1227RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1T61String, Asn1Core);
1228RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1VideoTexString, Asn1Core);
1229RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1VisibleString, Asn1Core);
1230RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1Ia5String, Asn1Core);
1231RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1GraphicString, Asn1Core);
1232RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1GeneralString, Asn1Core);
1233RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1Utf8String, Asn1Core);
1234RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1BmpString, Asn1Core);
1235RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1UniversalString, Asn1Core);
1236
1237RTDECL(int) RTAsn1String_InitWithValue(PRTASN1STRING pThis, const char *pszUtf8Value, PCRTASN1ALLOCATORVTABLE pAllocator);
1238RTDECL(int) RTAsn1String_InitEx(PRTASN1STRING pThis, uint32_t uTag, void const *pvValue, size_t cbValue,
1239 PCRTASN1ALLOCATORVTABLE pAllocator);
1240
1241/**
1242 * Compares two strings values, extended version.
1243 *
1244 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
1245 * @param pLeft The first string.
1246 * @param pRight The second string.
1247 * @param fTypeToo Set if the string types must match, false if
1248 * not.
1249 */
1250RTDECL(int) RTAsn1String_CompareEx(PCRTASN1STRING pLeft, PCRTASN1STRING pRight, bool fTypeToo);
1251
1252/**
1253 * Compares a ASN.1 string object with an UTF-8 string.
1254 *
1255 * @returns 0 if equal, -1 if @a pThis is smaller, 1 if @a pThis is larger.
1256 * @param pThis The ASN.1 string object.
1257 * @param pszString The UTF-8 string.
1258 * @param cchString The length of @a pszString, or RTSTR_MAX.
1259 */
1260RTDECL(int) RTAsn1String_CompareWithString(PCRTASN1STRING pThis, const char *pszString, size_t cchString);
1261
1262/**
1263 * Queries the UTF-8 length of an ASN.1 string object.
1264 *
1265 * This differs from RTAsn1String_QueryUtf8 in that it won't need to allocate
1266 * memory for the converted string, but just calculates the length.
1267 *
1268 * @returns IPRT status code.
1269 * @param pThis The ASN.1 string object.
1270 * @param pcch Where to return the string length.
1271 */
1272RTDECL(int) RTAsn1String_QueryUtf8Len(PCRTASN1STRING pThis, size_t *pcch);
1273
1274/**
1275 * Queries the UTF-8 string for an ASN.1 string object.
1276 *
1277 * This may fail as it may require memory to be allocated for storing the
1278 * string.
1279 *
1280 * @returns IPRT status code.
1281 * @param pString The ASN.1 string object. This is a const
1282 * parameter for making life easier on the caller,
1283 * however be aware that the object may be modified
1284 * by this call!
1285 * @param ppsz Where to return the pointer to the UTF-8 string.
1286 * Optional.
1287 * @param pcch Where to return the length (in 8-bit chars) to
1288 * of the UTF-8 string. Optional.
1289 */
1290RTDECL(int) RTAsn1String_QueryUtf8(PCRTASN1STRING pString, const char **ppsz, size_t *pcch);
1291RTDECL(int) RTAsn1String_RecodeAsUtf8(PRTASN1STRING pThis, PCRTASN1ALLOCATORVTABLE pAllocator);
1292
1293RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFSTRINGS, RTASN1STRING, RTDECL, RTAsn1SeqOfStrings);
1294RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFSTRINGS, RTASN1STRING, RTDECL, RTAsn1SetOfStrings);
1295
1296
1297
1298/**
1299 * ASN.1 generic context specific tag (IPRT representation).
1300 *
1301 * Normally used to tag something that's optional, version specific or such.
1302 *
1303 * For the purpose of documenting the format with typedefs as well as possibly
1304 * making it a little more type safe, there's a set of typedefs for the most
1305 * commonly used tag values defined. These typedefs have are identical to
1306 * RTASN1CONTEXTTAG, except from the C++ type system point of view.
1307 */
1308typedef struct RTASN1CONTEXTTAG
1309{
1310 /** Core ASN.1 encoding details. */
1311 RTASN1CORE Asn1Core;
1312} RTASN1CONTEXTTAG;
1313/** Pointer to an ASN.1 context tag (IPRT thing). */
1314typedef RTASN1CONTEXTTAG *PRTASN1CONTEXTTAG;
1315/** Pointer to a const ASN.1 context tag (IPRT thing). */
1316typedef RTASN1CONTEXTTAG const *PCRTASN1CONTEXTTAG;
1317
1318RTDECL(int) RTAsn1ContextTagN_Init(PRTASN1CONTEXTTAG pThis, uint32_t uTag, PCRTASN1COREVTABLE pVtable);
1319RTDECL(int) RTAsn1ContextTagN_Clone(PRTASN1CONTEXTTAG pThis, PCRTASN1CONTEXTTAG pSrc, uint32_t uTag);
1320
1321
1322/** @internal */
1323#define RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(a_uTag) \
1324 typedef struct RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) { RTASN1CORE Asn1Core; } RT_CONCAT(RTASN1CONTEXTTAG,a_uTag); \
1325 typedef RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) *RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag); \
1326 DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pThis, \
1327 PCRTASN1COREVTABLE pVtable, PCRTASN1ALLOCATORVTABLE pAllocator) \
1328 { \
1329 NOREF(pAllocator); \
1330 return RTAsn1ContextTagN_Init((PRTASN1CONTEXTTAG)pThis, a_uTag, pVtable); \
1331 } \
1332 DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pThis, \
1333 RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) const *pSrc) \
1334 { return RTAsn1ContextTagN_Clone((PRTASN1CONTEXTTAG)pThis, (PCRTASN1CONTEXTTAG)pSrc, a_uTag); } \
1335 typedef RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) const *RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag)
1336RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(0);
1337RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(1);
1338RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(2);
1339RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(3);
1340RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(4);
1341RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(5);
1342RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(6);
1343RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(7);
1344#undef RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE
1345
1346/** Helper for comparing optional context tags.
1347 * This will return if both are not present or if their precense differs.
1348 * @internal */
1349#define RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, a_uTag) \
1350 do { \
1351 /* type checks */ \
1352 RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag) const pMyLeftInternal = (a_pLeft); \
1353 RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag) const pMyRightInternal = (a_pRight); \
1354 (a_iDiff) = (int)RTASN1CORE_IS_PRESENT(&pMyLeftInternal->Asn1Core) \
1355 - (int)RTASN1CORE_IS_PRESENT(&pMyRightInternal->Asn1Core); \
1356 if ((a_iDiff) || !RTASN1CORE_IS_PRESENT(&pMyLeftInternal->Asn1Core)) return iDiff; \
1357 } while (0)
1358
1359/** Helpers for comparing optional context tags.
1360 * This will return if both are not present or if their precense differs.
1361 * @{ */
1362#define RTASN1CONTEXTTAG0_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 0)
1363#define RTASN1CONTEXTTAG1_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 1)
1364#define RTASN1CONTEXTTAG2_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 2)
1365#define RTASN1CONTEXTTAG3_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 3)
1366#define RTASN1CONTEXTTAG4_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 4)
1367#define RTASN1CONTEXTTAG5_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 5)
1368#define RTASN1CONTEXTTAG6_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 6)
1369#define RTASN1CONTEXTTAG7_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 7)
1370/** @} */
1371
1372
1373/**
1374 * Type information for dynamically bits (see RTASN1DYNTYPE).
1375 */
1376typedef enum RTASN1TYPE
1377{
1378 /** Not present. */
1379 RTASN1TYPE_NOT_PRESENT = 0,
1380 /** Generic ASN.1 for unknown tag/class. */
1381 RTASN1TYPE_CORE,
1382 /** ASN.1 NULL. */
1383 RTASN1TYPE_NULL,
1384 /** ASN.1 integer. */
1385 RTASN1TYPE_INTEGER,
1386 /** ASN.1 boolean. */
1387 RTASN1TYPE_BOOLEAN,
1388 /** ASN.1 character string. */
1389 RTASN1TYPE_STRING,
1390 /** ASN.1 octet string. */
1391 RTASN1TYPE_OCTET_STRING,
1392 /** ASN.1 bite string. */
1393 RTASN1TYPE_BIT_STRING,
1394 /** ASN.1 UTC or Generalize time. */
1395 RTASN1TYPE_TIME,
1396#if 0
1397 /** ASN.1 sequence core. */
1398 RTASN1TYPE_SEQUENCE_CORE,
1399 /** ASN.1 set core. */
1400 RTASN1TYPE_SET_CORE,
1401#endif
1402 /** ASN.1 object identifier. */
1403 RTASN1TYPE_OBJID,
1404 /** End of valid types. */
1405 RTASN1TYPE_END,
1406 /** Type size hack. */
1407 RTASN1TYPE_32BIT_HACK = 0x7fffffff
1408} RTASN1TYPE;
1409
1410
1411/**
1412 * ASN.1 dynamic type record.
1413 */
1414typedef struct RTASN1DYNTYPE
1415{
1416 /** Alternative interpretation provided by a user.
1417 * Before destroying this object, the user must explicitly free this and set
1418 * it to NULL, otherwise there will be memory leaks. */
1419 PRTASN1CORE pUser;
1420 /** The type of data we've got here. */
1421 RTASN1TYPE enmType;
1422 /** Union with data of the type dictated by enmType. */
1423 union
1424 {
1425 /** RTASN1TYPE_CORE. */
1426 RTASN1CORE Core;
1427 /** RTASN1TYPE_NULL. */
1428 RTASN1NULL Asn1Null;
1429 /** RTASN1TYPE_INTEGER. */
1430 RTASN1INTEGER Integer;
1431 /** RTASN1TYPE_BOOLEAN. */
1432 RTASN1BOOLEAN Boolean;
1433 /** RTASN1TYPE_STRING. */
1434 RTASN1STRING String;
1435 /** RTASN1TYPE_OCTET_STRING. */
1436 RTASN1OCTETSTRING OctetString;
1437 /** RTASN1TYPE_BIT_STRING. */
1438 RTASN1BITSTRING BitString;
1439 /** RTASN1TYPE_TIME. */
1440 RTASN1TIME Time;
1441#if 0
1442 /** RTASN1TYPE_SEQUENCE_CORE. */
1443 RTASN1SEQUENCECORE SeqCore;
1444 /** RTASN1TYPE_SET_CORE. */
1445 RTASN1SETCORE SetCore;
1446#endif
1447 /** RTASN1TYPE_OBJID. */
1448 RTASN1OBJID ObjId;
1449 } u;
1450} RTASN1DYNTYPE;
1451/** Pointer to an ASN.1 dynamic type record. */
1452typedef RTASN1DYNTYPE *PRTASN1DYNTYPE;
1453/** Pointer to a const ASN.1 dynamic type record. */
1454typedef RTASN1DYNTYPE const *PCRTASN1DYNTYPE;
1455RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1DYNTYPE, RTDECL, RTAsn1DynType, u.Core);
1456
1457
1458/** @name Virtual Method Table Based API
1459 * @{ */
1460/**
1461 * Calls the destructor of the ASN.1 object.
1462 *
1463 * @param pThisCore The IPRT representation of an ASN.1 object.
1464 */
1465RTDECL(void) RTAsn1VtDelete(PRTASN1CORE pThisCore);
1466
1467/**
1468 * Deep enumeration of all descendants.
1469 *
1470 * @returns IPRT status code, any non VINF_SUCCESS value stems from pfnCallback.
1471 * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
1472 * @param pfnCallback The callback.
1473 * @param uDepth The depth of this object. Children are at +1.
1474 * @param pvUser Callback user argument.
1475 * @param fDepthFirst When set, recurse into child objects before calling
1476 * pfnCallback on then. When clear, the child object
1477 * is first
1478 */
1479RTDECL(int) RTAsn1VtDeepEnum(PRTASN1CORE pThisCore, bool fDepthFirst, uint32_t uDepth,
1480 PFNRTASN1ENUMCALLBACK pfnCallback, void *pvUser);
1481
1482/**
1483 * Clones @a pSrcCore onto @a pThisCore.
1484 *
1485 * The caller must be sure that @a pSrcCore and @a pThisCore are of the same
1486 * types.
1487 *
1488 * @returns IPRT status code.
1489 * @param pThisCore Pointer to the ASN.1 core to clone onto. This shall
1490 * be uninitialized.
1491 * @param pSrcCore Pointer to the ASN.1 core to clone.
1492 * @param pAllocator The allocator to use.
1493 */
1494RTDECL(int) RTAsn1VtClone(PRTASN1CORE pThisCore, PRTASN1CORE pSrcCore, PCRTASN1ALLOCATORVTABLE pAllocator);
1495
1496/**
1497 * Compares two objects.
1498 *
1499 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
1500 * @param pLeftCore Pointer to the ASN.1 core of the left side object.
1501 * @param pRightCore Pointer to the ASN.1 core of the right side object.
1502 */
1503RTDECL(int) RTAsn1VtCompare(PCRTASN1CORE pLeftCore, PCRTASN1CORE pRightCore);
1504
1505/**
1506 * Check sanity.
1507 *
1508 * A primary criteria is that the object is present and initialized.
1509 *
1510 * @returns IPRT status code.
1511 * @param pThisCore Pointer to the ASN.1 core of the object to check out.
1512 * @param fFlags See RTASN1_CHECK_SANITY_F_XXX.
1513 * @param pErrInfo Where to return additional error details. Optional.
1514 * @param pszErrorTag Tag for the additional error details.
1515 */
1516RTDECL(int) RTAsn1VtCheckSanity(PCRTASN1CORE pThisCore, uint32_t fFlags,
1517 PRTERRINFO pErrInfo, const char *pszErrorTag);
1518/** @} */
1519
1520
1521/** @defgroup rp_asn1_encode RTAsn1Encode - ASN.1 Encoding
1522 * @{ */
1523
1524/** @name RTASN1ENCODE_F_XXX
1525 * @{ */
1526/** Use distinguished encoding rules (DER) to encode the object. */
1527#define RTASN1ENCODE_F_DER UINT32_C(0x00000001)
1528/** Use base encoding rules (BER) to encode the object.
1529 * This is currently the same as DER for practical reasons. */
1530#define RTASN1ENCODE_F_BER RTASN1ENCODE_F_DER
1531/** Mask of valid encoding rules. */
1532#define RTASN1ENCODE_F_RULE_MASK UINT32_C(0x00000007)
1533/** @} */
1534
1535
1536/**
1537 * Recalculates cbHdr of and ASN.1 object.
1538 *
1539 * @returns IPRT status code.
1540 * @retval VINF_ASN1_NOT_ENCODED if the header size is zero (default value,
1541 * whatever).
1542 * @param pAsn1Core The object in question.
1543 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1544 * flags. Must include the encoding type.
1545 * @param pErrInfo Extended error info. Optional.
1546 */
1547RTDECL(int) RTAsn1EncodeRecalcHdrSize(PRTASN1CORE pAsn1Core, uint32_t fFlags, PRTERRINFO pErrInfo);
1548
1549/**
1550 * Prepares the ASN.1 structure for encoding.
1551 *
1552 * The preparations is mainly calculating accurate object size, but may also
1553 * involve operations like recoding internal UTF-8 strings to the actual ASN.1
1554 * format and other things that may require memory to allocated/reallocated.
1555 *
1556 * @returns IPRT status code
1557 * @param pRoot The root of the ASN.1 object tree to encode.
1558 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1559 * flags. Must include the encoding type.
1560 * @param pcbEncoded Where to return the encoded size. Optional.
1561 * @param pErrInfo Where to store extended error information.
1562 * Optional.
1563 */
1564RTDECL(int) RTAsn1EncodePrepare(PRTASN1CORE pRoot, uint32_t fFlags, uint32_t *pcbEncoded, PRTERRINFO pErrInfo);
1565
1566/**
1567 * Encodes and writes the header of an ASN.1 object.
1568 *
1569 * @returns IPRT status code.
1570 * @retval VINF_ASN1_NOT_ENCODED if nothing was written (default value,
1571 * whatever).
1572 * @param pAsn1Core The object in question.
1573 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1574 * flags. Must include the encoding type.
1575 * @param pfnWriter The output writer callback.
1576 * @param pvUser The user argument to pass to @a pfnWriter.
1577 * @param pErrInfo Where to store extended error information.
1578 * Optional.
1579 */
1580RTDECL(int) RTAsn1EncodeWriteHeader(PCRTASN1CORE pAsn1Core, uint32_t fFlags, FNRTASN1ENCODEWRITER pfnWriter, void *pvUser,
1581 PRTERRINFO pErrInfo);
1582
1583/**
1584 * Encodes and writes an ASN.1 object.
1585 *
1586 * @returns IPRT status code
1587 * @param pRoot The root of the ASN.1 object tree to encode.
1588 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1589 * flags. Must include the encoding type.
1590 * @param pfnWriter The output writer callback.
1591 * @param pvUser The user argument to pass to @a pfnWriter.
1592 * @param pErrInfo Where to store extended error information.
1593 * Optional.
1594 */
1595RTDECL(int) RTAsn1EncodeWrite(PCRTASN1CORE pRoot, uint32_t fFlags, FNRTASN1ENCODEWRITER pfnWriter, void *pvUser,
1596 PRTERRINFO pErrInfo);
1597
1598/**
1599 * Encodes and writes an ASN.1 object into a caller allocated memory buffer.
1600 *
1601 * @returns IPRT status code
1602 * @param pRoot The root of the ASN.1 object tree to encode.
1603 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1604 * flags. Must include the encoding type.
1605 * @param pvBuf The output buffer.
1606 * @param cbBuf The buffer size. This should have the size
1607 * returned by RTAsn1EncodePrepare().
1608 * @param pErrInfo Where to store extended error information.
1609 * Optional.
1610 */
1611RTDECL(int) RTAsn1EncodeToBuffer(PCRTASN1CORE pRoot, uint32_t fFlags, void *pvBuf, size_t cbBuf, PRTERRINFO pErrInfo);
1612
1613/** @} */
1614
1615
1616
1617/** @defgroup rp_asn1_cursor RTAsn1Cursor - BER, DER, and CER cursor
1618 * @{ */
1619
1620/**
1621 * ASN.1 decoder byte cursor.
1622 */
1623typedef struct RTASN1CURSOR
1624{
1625 /** Pointer to the current (next) byte. */
1626 uint8_t const *pbCur;
1627 /** Number of bytes left to decode. */
1628 uint32_t cbLeft;
1629 /** RTASN1CURSOR_FLAGS_XXX. */
1630 uint8_t fFlags;
1631 /** The cursor depth. */
1632 uint8_t cDepth;
1633 /** Two bytes reserved for future tricks. */
1634 uint8_t abReserved[2];
1635 /** Pointer to the primary cursor. */
1636 struct RTASN1CURSORPRIMARY *pPrimary;
1637 /** Pointer to the parent cursor. */
1638 struct RTASN1CURSOR *pUp;
1639 /** The error tag for this cursor level. */
1640 const char *pszErrorTag;
1641} RTASN1CURSOR;
1642
1643/** @name RTASN1CURSOR_FLAGS_XXX - Cursor flags.
1644 * @{ */
1645/** Enforce DER rules. */
1646#define RTASN1CURSOR_FLAGS_DER RT_BIT(1)
1647/** Enforce CER rules. */
1648#define RTASN1CURSOR_FLAGS_CER RT_BIT(2)
1649/** @} */
1650
1651
1652typedef struct RTASN1CURSORPRIMARY
1653{
1654 /** The normal cursor bits. */
1655 RTASN1CURSOR Cursor;
1656 /** For error reporting. */
1657 PRTERRINFO pErrInfo;
1658 /** The allocator virtual method table. */
1659 PCRTASN1ALLOCATORVTABLE pAllocator;
1660} RTASN1CURSORPRIMARY;
1661typedef RTASN1CURSORPRIMARY *PRTASN1CURSORPRIMARY;
1662
1663
1664/**
1665 * Initializes a primary cursor.
1666 *
1667 * The primary cursor is special in that it stores information shared with the
1668 * sub-cursors created by methods like RTAsn1CursorGetContextTagNCursor and
1669 * RTAsn1CursorGetSequenceCursor. Even if just sharing a few items at present,
1670 * it still important to save every possible byte since stack space is scarce in
1671 * some of the execution environments.
1672 *
1673 * @returns Pointer to pCursor->Cursor.
1674 * @param pPrimaryCursor The primary cursor structure to initialize.
1675 * @param pvFirst The first byte to decode.
1676 * @param cb The number of bytes to decode.
1677 * @param pErrInfo Where to store error information.
1678 * @param pAllocator The allocator to use.
1679 * @param fFlags RTASN1CURSOR_FLAGS_XXX.
1680 * @param pszErrorTag The primary error tag.
1681 */
1682RTDECL(PRTASN1CURSOR) RTAsn1CursorInitPrimary(PRTASN1CURSORPRIMARY pPrimaryCursor, void const *pvFirst, uint32_t cb,
1683 PRTERRINFO pErrInfo, PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t fFlags,
1684 const char *pszErrorTag);
1685
1686
1687/**
1688 * Initialize a sub-cursor for traversing the content of an ASN.1 object.
1689 *
1690 * @returns IPRT status code.
1691 * @param pParent The parent cursor.
1692 * @param pAsn1Core The ASN.1 object which content we should
1693 * traverse with the sub-cursor.
1694 * @param pChild The sub-cursor to initialize.
1695 * @param pszErrorTag The error tag of the sub-cursor.
1696 */
1697RTDECL(int) RTAsn1CursorInitSubFromCore(PRTASN1CURSOR pParent, PRTASN1CORE pAsn1Core,
1698 PRTASN1CURSOR pChild, const char *pszErrorTag);
1699
1700/**
1701 * Initalizes the an allocation structure prior to making an allocation.
1702 *
1703 * To try unify and optimize memory managment for decoding and in-memory
1704 * construction of ASN.1 objects, each allocation has an allocation structure
1705 * associated with it. This stores the allocator and keep statistics for
1706 * optimizing resizable allocations.
1707 *
1708 * @returns Pointer to the allocator info (for call in alloc parameter).
1709 * @param pCursor The cursor.
1710 * @param pAllocation The allocation structure to initialize.
1711 */
1712RTDECL(PRTASN1ALLOCATION) RTAsn1CursorInitAllocation(PRTASN1CURSOR pCursor, PRTASN1ALLOCATION pAllocation);
1713
1714/**
1715 * Initalizes the an array allocation structure prior to making an allocation.
1716 *
1717 * This is a special case of RTAsn1CursorInitAllocation. We store a little bit
1718 * more detail here in order to optimize growing and shrinking of arrays.
1719 *
1720 * @returns Pointer to the allocator info (for call in alloc parameter).
1721 * @param pCursor The cursor.
1722 * @param pAllocation The allocation structure to initialize.
1723 * @param cbEntry The array entry size.
1724 */
1725RTDECL(PRTASN1ARRAYALLOCATION) RTAsn1CursorInitArrayAllocation(PRTASN1CURSOR pCursor, PRTASN1ARRAYALLOCATION pAllocation,
1726 size_t cbEntry);
1727
1728/**
1729 * Wrapper around RTErrInfoSetV.
1730 *
1731 * @returns @a rc
1732 * @param pCursor The cursor.
1733 * @param rc The return code to return.
1734 * @param pszMsg Message format string.
1735 * @param ... Format arguments.
1736 */
1737RTDECL(int) RTAsn1CursorSetInfo(PRTASN1CURSOR pCursor, int rc, const char *pszMsg, ...) RT_IPRT_FORMAT_ATTR(3, 4);
1738
1739/**
1740 * Wrapper around RTErrInfoSetV.
1741 *
1742 * @returns @a rc
1743 * @param pCursor The cursor.
1744 * @param rc The return code to return.
1745 * @param pszMsg Message format string.
1746 * @param va Format arguments.
1747 */
1748RTDECL(int) RTAsn1CursorSetInfoV(PRTASN1CURSOR pCursor, int rc, const char *pszMsg, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
1749
1750/**
1751 * Checks that we've reached the end of the data for the cursor.
1752 *
1753 * @returns IPRT status code.
1754 * @param pCursor The cursor we're decoding from.
1755 */
1756RTDECL(int) RTAsn1CursorCheckEnd(PRTASN1CURSOR pCursor);
1757
1758
1759/**
1760 * Skips a given number of bytes.
1761 *
1762 * @returns @a pCursor
1763 * @param pCursor The cursor.
1764 * @param cb The number of bytes to skip.
1765 * @internal
1766 */
1767DECLINLINE(PRTASN1CURSOR) RTAsn1CursorSkip(PRTASN1CURSOR pCursor, uint32_t cb)
1768{
1769 if (cb <= pCursor->cbLeft)
1770 {
1771 pCursor->cbLeft -= cb;
1772 pCursor->pbCur += cb;
1773 }
1774 else
1775 {
1776 pCursor->pbCur += pCursor->cbLeft;
1777 pCursor->cbLeft = 0;
1778 }
1779
1780 return pCursor;
1781}
1782
1783/**
1784 * Low-level function for reading an ASN.1 header.
1785 *
1786 * @returns IPRT status code.
1787 * @param pCursor The cursor we're decoding from.
1788 * @param pAsn1Core The output object core.
1789 * @param pszErrorTag Error tag.
1790 * @internal
1791 */
1792RTDECL(int) RTAsn1CursorReadHdr(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, const char *pszErrorTag);
1793
1794/**
1795 * Common helper for simple tag matching.
1796 *
1797 * @returns IPRT status code.
1798 * @param pCursor The cursor (for error reporting).
1799 * @param pAsn1Core The ASN.1 core structure.
1800 * @param uTag The expected tag.
1801 * @param fClass The expected class.
1802 * @param fString Set if it's a string type that shall follow
1803 * special CER and DER rules wrt to constructed and
1804 * primitive encoding.
1805 * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
1806 * @param pszErrorTag The error tag.
1807 * @param pszWhat The type/whatever name.
1808 */
1809RTDECL(int) RTAsn1CursorMatchTagClassFlagsEx(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
1810 bool fString, uint32_t fFlags, const char *pszErrorTag, const char *pszWhat);
1811
1812/**
1813 * Common helper for simple tag matching.
1814 *
1815 * @returns IPRT status code.
1816 * @param pCursor The cursor (for error reporting).
1817 * @param pAsn1Core The ASN.1 core structure.
1818 * @param uTag The expected tag.
1819 * @param fClass The expected class.
1820 * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
1821 * @param pszErrorTag The error tag.
1822 * @param pszWhat The type/whatever name.
1823 * @internal
1824 */
1825DECLINLINE(int) RTAsn1CursorMatchTagClassFlags(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
1826 uint32_t fFlags, const char *pszErrorTag, const char *pszWhat)
1827{
1828 if (pAsn1Core->uTag == uTag && pAsn1Core->fClass == fClass)
1829 return VINF_SUCCESS;
1830 return RTAsn1CursorMatchTagClassFlagsEx(pCursor, pAsn1Core, uTag, fClass, false /*fString*/, fFlags, pszErrorTag, pszWhat);
1831}
1832
1833
1834/**
1835 * Common helper for simple tag matching for strings.
1836 *
1837 * Check string encoding considerations.
1838 *
1839 * @returns IPRT status code.
1840 * @param pCursor The cursor (for error reporting).
1841 * @param pAsn1Core The ASN.1 core structure.
1842 * @param uTag The expected tag.
1843 * @param fClass The expected class.
1844 * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
1845 * @param pszErrorTag The error tag.
1846 * @param pszWhat The type/whatever name.
1847 * @internal
1848 */
1849DECLINLINE(int) RTAsn1CursorMatchTagClassFlagsString(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
1850 uint32_t fFlags, const char *pszErrorTag, const char *pszWhat)
1851{
1852 if (pAsn1Core->uTag == uTag && pAsn1Core->fClass == fClass)
1853 return VINF_SUCCESS;
1854 return RTAsn1CursorMatchTagClassFlagsEx(pCursor, pAsn1Core, uTag, fClass, true /*fString*/, fFlags, pszErrorTag, pszWhat);
1855}
1856
1857
1858
1859/** @name RTASN1CURSOR_GET_F_XXX - Common flags for all the getters.
1860 * @{ */
1861/** Used for decoding objects with implicit tags assigned to them. This only
1862 * works when calling getters with a unambigious types. */
1863#define RTASN1CURSOR_GET_F_IMPLICIT RT_BIT_32(0)
1864/** @} */
1865
1866/**
1867 * Read ANY object.
1868 *
1869 * @returns IPRT status code.
1870 * @param pCursor The cursor we're decoding from.
1871 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1872 * @param pAsn1Core The output object core.
1873 * @param pszErrorTag Error tag.
1874 */
1875RTDECL(int) RTAsn1CursorGetCore(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1CORE pAsn1Core, const char *pszErrorTag);
1876
1877/**
1878 * Read a NULL object.
1879 *
1880 * @returns IPRT status code.
1881 * @param pCursor The cursor we're decoding from.
1882 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1883 * @param pNull The output NULL object.
1884 * @param pszErrorTag Error tag.
1885 */
1886RTDECL(int) RTAsn1CursorGetNull(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1NULL pNull, const char *pszErrorTag);
1887
1888/**
1889 * Read an INTEGER object.
1890 *
1891 * @returns IPRT status code.
1892 * @param pCursor The cursor we're decoding from.
1893 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1894 * @param pInteger The output integer object.
1895 * @param pszErrorTag Error tag.
1896 */
1897RTDECL(int) RTAsn1CursorGetInteger(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1INTEGER pInteger, const char *pszErrorTag);
1898
1899/**
1900 * Read an BOOLEAN object.
1901 *
1902 * @returns IPRT status code.
1903 * @param pCursor The cursor we're decoding from.
1904 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1905 * @param pBoolean The output boolean object.
1906 * @param pszErrorTag Error tag.
1907 */
1908RTDECL(int) RTAsn1CursorGetBoolean(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1BOOLEAN pBoolean, const char *pszErrorTag);
1909
1910/**
1911 * Retrives an object identifier (aka ObjId or OID) item from the ASN.1 stream.
1912 *
1913 * @returns IPRT status code.
1914 * @param pCursor The cursor.
1915 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1916 * @param pObjId The output ODI object.
1917 * @param pszErrorTag Error tag.
1918 */
1919RTDECL(int) RTAsn1CursorGetObjId(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pObjId, const char *pszErrorTag);
1920
1921/**
1922 * Retrives and verifies an object identifier.
1923 *
1924 * @returns IPRT status code.
1925 * @param pCursor The cursor.
1926 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1927 * @param pObjId Where to return the parsed object ID, optional.
1928 * @param pszExpectedObjId The expected object identifier (dotted).
1929 * @param pszErrorTag Error tag.
1930 */
1931RTDECL(int) RTAsn1CursorGetAndCheckObjId(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pObjId,
1932 const char *pszExpectedObjId, const char *pszErrorTag);
1933
1934/**
1935 * Read an UTC TIME or GENERALIZED TIME object.
1936 *
1937 * @returns IPRT status code.
1938 * @param pCursor The cursor we're decoding from.
1939 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1940 * @param pTime The output time object.
1941 * @param pszErrorTag Error tag.
1942 */
1943RTDECL(int) RTAsn1CursorGetTime(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1TIME pTime, const char *pszErrorTag);
1944
1945/**
1946 * Read an BIT STRING object (skips past the content).
1947 *
1948 * @returns IPRT status ocde.
1949 * @param pCursor The cursor.
1950 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1951 * @param pBitString The output bit string object.
1952 * @param pszErrorTag Error tag.
1953 */
1954RTDECL(int) RTAsn1CursorGetBitString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1BITSTRING pBitString,
1955 const char *pszErrorTag);
1956
1957/**
1958 * Read an BIT STRING object (skips past the content), extended version with
1959 * cMaxBits.
1960 *
1961 * @returns IPRT status ocde.
1962 * @param pCursor The cursor.
1963 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1964 * @param cMaxBits The max length of the bit string in bits. Pass
1965 * UINT32_MAX if variable size.
1966 * @param pBitString The output bit string object.
1967 * @param pszErrorTag Error tag.
1968 */
1969RTDECL(int) RTAsn1CursorGetBitStringEx(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t cMaxBits, PRTASN1BITSTRING pBitString,
1970 const char *pszErrorTag);
1971
1972/**
1973 * Read an OCTET STRING object (skips past the content).
1974 *
1975 * @returns IPRT status ocde.
1976 * @param pCursor The cursor.
1977 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1978 * @param pOctetString The output octet string object.
1979 * @param pszErrorTag Error tag.
1980 */
1981RTDECL(int) RTAsn1CursorGetOctetString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OCTETSTRING pOctetString,
1982 const char *pszErrorTag);
1983
1984/**
1985 * Read any kind of string object, except 'character string (29)'.
1986 *
1987 * @returns IPRT status code.
1988 * @param pCursor The cursor we're decoding from.
1989 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1990 * @param pString The output boolean object.
1991 * @param pszErrorTag Error tag.
1992 */
1993RTDECL(int) RTAsn1CursorGetString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
1994
1995/**
1996 * Read a IA5 STRING object.
1997 *
1998 * @returns IPRT status code.
1999 * @param pCursor The cursor we're decoding from.
2000 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2001 * @param pString The output boolean object.
2002 * @param pszErrorTag Error tag.
2003 */
2004RTDECL(int) RTAsn1CursorGetIa5String(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
2005
2006/**
2007 * Read a UTF8 STRING object.
2008 *
2009 * @returns IPRT status code.
2010 * @param pCursor The cursor we're decoding from.
2011 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2012 * @param pString The output boolean object.
2013 * @param pszErrorTag Error tag.
2014 */
2015RTDECL(int) RTAsn1CursorGetUtf8String(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
2016
2017/**
2018 * Read a BMP STRING (UCS-2) object.
2019 *
2020 * @returns IPRT status code.
2021 * @param pCursor The cursor we're decoding from.
2022 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2023 * @param pString The output boolean object.
2024 * @param pszErrorTag Error tag.
2025 */
2026RTDECL(int) RTAsn1CursorGetBmpString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
2027
2028/**
2029 * Read a SEQUENCE object and create a cursor for its content.
2030 *
2031 * @returns IPRT status code.
2032 * @param pCursor The cursor we're decoding from.
2033 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2034 * @param pSeqCore The output sequence core object.
2035 * @param pSeqCursor The output cursor for the sequence content.
2036 * @param pszErrorTag Error tag, this will be associated with the
2037 * returned cursor.
2038 */
2039RTDECL(int) RTAsn1CursorGetSequenceCursor(PRTASN1CURSOR pCursor, uint32_t fFlags,
2040 PRTASN1SEQUENCECORE pSeqCore, PRTASN1CURSOR pSeqCursor, const char *pszErrorTag);
2041
2042/**
2043 * Read a SET object and create a cursor for its content.
2044 *
2045 * @returns IPRT status code.
2046 * @param pCursor The cursor we're decoding from.
2047 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2048 * @param pSetCore The output set core object.
2049 * @param pSetCursor The output cursor for the set content.
2050 * @param pszErrorTag Error tag, this will be associated with the
2051 * returned cursor.
2052 */
2053RTDECL(int) RTAsn1CursorGetSetCursor(PRTASN1CURSOR pCursor, uint32_t fFlags,
2054 PRTASN1SETCORE pSetCore, PRTASN1CURSOR pSetCursor, const char *pszErrorTag);
2055
2056/**
2057 * Read a given constructed context tag and create a cursor for its content.
2058 *
2059 * @returns IPRT status code.
2060 * @param pCursor The cursor we're decoding from.
2061 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2062 * @param uExpectedTag The expected tag.
2063 * @param pVtable The vtable for the context tag node (see
2064 * RTASN1TMPL_PASS_XTAG).
2065 * @param pCtxTag The output context tag object.
2066 * @param pCtxTagCursor The output cursor for the context tag content.
2067 * @param pszErrorTag Error tag, this will be associated with the
2068 * returned cursor.
2069 *
2070 * @remarks There are specialized version of this function for each of the
2071 * numbered context tag structures, like for RTASN1CONTEXTTAG0 there is
2072 * RTAsn1CursorGetContextTag0Cursor.
2073 */
2074RTDECL(int) RTAsn1CursorGetContextTagNCursor(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t uExpectedTag,
2075 PCRTASN1COREVTABLE pVtable, PRTASN1CONTEXTTAG pCtxTag, PRTASN1CURSOR pCtxTagCursor,
2076 const char *pszErrorTag);
2077
2078/**
2079 * Read a dynamic ASN.1 type.
2080 *
2081 * @returns IPRT status code.
2082 * @param pCursor The cursor we're decoding from.
2083 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2084 * @param pDynType The output context tag object.
2085 * @param pszErrorTag Error tag.
2086 */
2087RTDECL(int) RTAsn1CursorGetDynType(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1DYNTYPE pDynType, const char *pszErrorTag);
2088
2089/**
2090 * Peeks at the next ASN.1 object.
2091 *
2092 * @returns IPRT status code.
2093 * @param pCursor The cursore we're decoding from.
2094 * @param pAsn1Core Where to store the output of the peek.
2095 */
2096RTDECL(int) RTAsn1CursorPeek(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core);
2097
2098/**
2099 * Checks if the next ASN.1 object matches the given tag and class/flags.
2100 *
2101 * @returns @c true on match, @c false on mismatch.
2102 * @param pCursor The cursore we're decoding from.
2103 * @param uTag The tag number to match against.
2104 * @param fClass The tag class and flags to match against.
2105 */
2106RTDECL(bool) RTAsn1CursorIsNextEx(PRTASN1CURSOR pCursor, uint32_t uTag, uint8_t fClass);
2107
2108
2109
2110/** @internal */
2111#define RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(a_uTag) \
2112 DECLINLINE(int) RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(PRTASN1CURSOR pCursor, uint32_t fFlags, \
2113 PCRTASN1COREVTABLE pVtable, \
2114 RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pCtxTag, \
2115 PRTASN1CURSOR pCtxTagCursor, const char *pszErrorTag) \
2116 { /* Constructed is automatically implied if you need a cursor to it. */ \
2117 return RTAsn1CursorGetContextTagNCursor(pCursor, fFlags, a_uTag, pVtable, (PRTASN1CONTEXTTAG)pCtxTag, pCtxTagCursor, pszErrorTag); \
2118 } \
2119 DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,InitDefault)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pCtxTag) \
2120 { /* Constructed is automatically implied if you need to init it with a default value. */ \
2121 return RTAsn1Core_InitDefault(&pCtxTag->Asn1Core, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED); \
2122 } \
2123 DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsConstructedContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
2124 { \
2125 return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED); \
2126 } \
2127 DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsPrimitiveContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
2128 { \
2129 return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE); \
2130 } \
2131 DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsAnyContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
2132 { \
2133 return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED) \
2134 || RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE);\
2135 } \
2136
2137RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(0)
2138RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(1)
2139RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(2)
2140RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(3)
2141RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(4)
2142RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(5)
2143RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(6)
2144RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(7)
2145#undef RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES
2146
2147
2148/**
2149 * Checks if the next object is a boolean.
2150 *
2151 * @returns true / false
2152 * @param pCursor The cursor we're decoding from.
2153 * @remarks May produce error info output on mismatch.
2154 */
2155DECLINLINE(bool) RTAsn1CursorIsBooleanNext(PRTASN1CURSOR pCursor)
2156{
2157 return RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_BOOLEAN, ASN1_TAGFLAG_PRIMITIVE | ASN1_TAGCLASS_UNIVERSAL);
2158}
2159
2160
2161/**
2162 * Checks if the next object is a set.
2163 *
2164 * @returns true / false
2165 * @param pCursor The cursor we're decoding from.
2166 * @remarks May produce error info output on mismatch.
2167 */
2168DECLINLINE(bool) RTAsn1CursorIsSetNext(PRTASN1CURSOR pCursor)
2169{
2170 return RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_SET, ASN1_TAGFLAG_CONSTRUCTED | ASN1_TAGCLASS_UNIVERSAL);
2171}
2172
2173
2174/** @} */
2175
2176
2177/** @name ASN.1 Utility APIs
2178 * @{ */
2179
2180/**
2181 * Dumps an IPRT representation of a ASN.1 object tree.
2182 *
2183 * @returns IPRT status code.
2184 * @param pAsn1Core The ASN.1 object which members should be dumped.
2185 * @param fFlags RTASN1DUMP_F_XXX.
2186 * @param uLevel The indentation level to start at.
2187 * @param pfnPrintfV The output function.
2188 * @param pvUser Argument to the output function.
2189 */
2190RTDECL(int) RTAsn1Dump(PCRTASN1CORE pAsn1Core, uint32_t fFlags, uint32_t uLevel, PFNRTDUMPPRINTFV pfnPrintfV, void *pvUser);
2191
2192/**
2193 * Queries the name for an object identifier.
2194 *
2195 * This API is very simple due to how we store the data.
2196 *
2197 * @returns IPRT status code.
2198 * @retval VINF_SUCCESS on success.
2199 * @retval VERR_NOT_FOUND if not found.
2200 * @retval VERR_BUFFER_OVERFLOW if more buffer space is required.
2201 *
2202 * @param pObjId The object ID to name.
2203 * @param pszDst Where to store the name if found.
2204 * @param cbDst The size of the destination buffer.
2205 */
2206RTDECL(int) RTAsn1QueryObjIdName(PCRTASN1OBJID pObjId, char *pszDst, size_t cbDst);
2207
2208/** @} */
2209
2210/** @} */
2211
2212RT_C_DECLS_END
2213
2214#endif
2215
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette