VirtualBox

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

Last change on this file since 69206 was 69105, checked in by vboxsync, 7 years ago

include/iprt/: (C) year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 92.6 KB
Line 
1/** @file
2 * IPRT - Abstract Syntax Notation One (ASN.1).
3 */
4
5/*
6 * Copyright (C) 2006-2017 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/** Checks 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/** Checks 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/set-of type. */
741#define RTASN1_IMPL_GEN_SEQ_OR_SET_OF_TYPEDEFS_AND_PROTOS(a_CoreType, a_CoreMember, \
742 a_ThisType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
743 typedef struct a_ThisType \
744 { \
745 /** Sequence/set core. */ \
746 a_CoreType a_CoreMember; \
747 /** The array allocation tracker. */ \
748 RTASN1ARRAYALLOCATION Allocation; \
749 /** Items in the array. */ \
750 uint32_t cItems; \
751 /** Array. */ \
752 RT_CONCAT(P,a_ItemType) *papItems; \
753 } a_ThisType; \
754 typedef a_ThisType *RT_CONCAT(P,a_ThisType); \
755 typedef a_ThisType const *RT_CONCAT(PC,a_ThisType); \
756 a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Erase)(RT_CONCAT(P,a_ThisType) pThis, uint32_t iPosition); \
757 a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_InsertEx)(RT_CONCAT(P,a_ThisType) pThis, uint32_t iPosition, \
758 RT_CONCAT(PC,a_ItemType) pToClone, \
759 PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t *piActualPos); \
760 /** Appends entry with default content, returns index or negative error code. */ \
761 DECLINLINE(int32_t) RT_CONCAT(a_ImplExtNm,_Append)(RT_CONCAT(P,a_ThisType) pThis) \
762 { \
763 uint32_t uPos = pThis->cItems; \
764 int rc = RT_CONCAT(a_ImplExtNm,_InsertEx)(pThis, uPos, NULL /*pToClone*/, pThis->Allocation.pAllocator, &uPos); \
765 if (RT_SUCCESS(rc)) \
766 return uPos; \
767 return rc; \
768 } \
769 RTASN1TYPE_STANDARD_PROTOTYPES(a_ThisType, a_DeclMacro, a_ImplExtNm, a_CoreMember.Asn1Core)
770
771/** Defines the typedefs and prototypes for a generic sequence-of type. */
772#define RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(a_SeqOfType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
773 RTASN1_IMPL_GEN_SEQ_OR_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQUENCECORE, SeqCore, a_SeqOfType, a_ItemType, a_DeclMacro, a_ImplExtNm)
774
775
776/**
777 * ASN.1 set core (IPRT representation).
778 */
779typedef struct RTASN1SETCORE
780{
781 /** Core ASN.1 encoding details. */
782 RTASN1CORE Asn1Core;
783} RTASN1SETCORE;
784/** Pointer to an ASN.1 set core (IPRT representation). */
785typedef RTASN1SETCORE *PRTASN1SETCORE;
786/** Pointer to a const ASN.1 set core (IPRT representation). */
787typedef RTASN1SETCORE const *PCRTASN1SETCORE;
788
789RTDECL(int) RTAsn1SetCore_Init(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable);
790RTDECL(int) RTAsn1SetCore_Clone(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETCORE pSrc);
791
792/**
793 * ASN.1 set-of core (IPRT representation).
794 */
795#if 0
796typedef struct RTASN1SETOFCORE
797{
798 /** Core ASN.1 encoding details. */
799 RTASN1CORE Asn1Core;
800} RTASN1SETUENCECORE;
801/** Pointer to an ASN.1 set-of core (IPRT representation). */
802typedef RTASN1SETUENCECORE *PRTASN1SETUENCECORE;
803/** Pointer to a const ASN.1 set-of core (IPRT representation). */
804typedef RTASN1SETUENCECORE const *PCRTASN1SETUENCECORE;
805#else
806# define RTASN1SETOFCORE RTASN1SETCORE
807# define PRTASN1SETOFCORE PRTASN1SETCORE
808# define PCRTASN1SETOFCORE PCRTASN1SETCORE
809#endif
810RTDECL(int) RTAsn1SetOfCore_Init(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable);
811RTDECL(int) RTAsn1SetOfCore_Clone(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETOFCORE pSrc);
812
813
814/** Defines the typedefs and prototypes for a generic set-of type. */
815#define RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(a_SetOfType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
816 RTASN1_IMPL_GEN_SEQ_OR_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETCORE, SetCore, a_SetOfType, a_ItemType, a_DeclMacro, a_ImplExtNm)
817
818
819/*
820 * Declare sets and sequences of the core structure.
821 */
822RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFCORES, RTASN1CORE, RTDECL, RTAsn1SeqOfCores);
823RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFCORES, RTASN1CORE, RTDECL, RTAsn1SetOfCores);
824
825
826/**
827 * ASN.1 null (IPRT representation).
828 */
829typedef struct RTASN1NULL
830{
831 /** Core ASN.1 encoding details. */
832 RTASN1CORE Asn1Core;
833} RTASN1NULL;
834/** Pointer to an ASN.1 null (IPRT representation). */
835typedef RTASN1NULL *PRTASN1NULL;
836/** Pointer to a const ASN.1 null (IPRT representation). */
837typedef RTASN1NULL const *PCRTASN1NULL;
838/** The Vtable for a RTASN1NULL structure. */
839extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Null_Vtable;
840
841RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1NULL, RTDECL, RTAsn1Null, Asn1Core);
842
843
844/**
845 * ASN.1 integer (IPRT representation).
846 */
847typedef struct RTASN1INTEGER
848{
849 /** Core ASN.1 encoding details. */
850 RTASN1CORE Asn1Core;
851 /** The unsigned C representation of the 64 least significant bits.
852 * @note A ASN.1 integer doesn't define signed/unsigned and can have any
853 * length you like. Thus, the user needs to check the size and
854 * preferably use the access APIs for signed numbers. */
855 RTUINT64U uValue;
856} RTASN1INTEGER;
857/** Pointer to an ASN.1 integer (IPRT representation). */
858typedef RTASN1INTEGER *PRTASN1INTEGER;
859/** Pointer to a const ASN.1 integer (IPRT representation). */
860typedef RTASN1INTEGER const *PCRTASN1INTEGER;
861/** The Vtable for a RTASN1INTEGER structure. */
862extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Integer_Vtable;
863
864RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1INTEGER, RTDECL, RTAsn1Integer, Asn1Core);
865
866/**
867 * Initializes an interger object to a default value.
868 * @returns VINF_SUCCESS.
869 * @param pInteger The integer object representation.
870 * @param uValue The default value (unsigned 64-bit).
871 * @param pAllocator The allocator (pro forma).
872 */
873RTDECL(int) RTAsn1Integer_InitDefault(PRTASN1INTEGER pInteger, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator);
874
875RTDECL(int) RTAsn1Integer_InitU64(PRTASN1INTEGER pThis, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator);
876
877/**
878 * Get the most significat bit that's set (1).
879 *
880 * @returns 0-base bit number, -1 if all clear.
881 * @param pInteger The integer to check.
882 */
883RTDECL(int32_t) RTAsn1Integer_UnsignedLastBit(PCRTASN1INTEGER pInteger);
884
885/**
886 * Compares two ASN.1 unsigned integers.
887 *
888 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
889 * @param pLeft The first ASN.1 integer.
890 * @param pRight The second ASN.1 integer.
891 */
892RTDECL(int) RTAsn1Integer_UnsignedCompare(PCRTASN1INTEGER pLeft, PCRTASN1INTEGER pRight);
893
894/**
895 * Compares an ASN.1 unsigned integer with a uint64_t.
896 *
897 * @returns 0 if equal, -1 if @a pInteger is smaller, 1 if @a pInteger is
898 * larger.
899 * @param pInteger The ASN.1 integer to treat as unsigned.
900 * @param u64Const The uint64_t constant to compare with.
901 */
902RTDECL(int) RTAsn1Integer_UnsignedCompareWithU64(PCRTASN1INTEGER pInteger, uint64_t u64Const);
903
904/**
905 * Compares an ASN.1 unsigned integer with a uint32_t.
906 *
907 * @returns 0 if equal, -1 if @a pInteger is smaller, 1 if @a pInteger is
908 * larger.
909 * @param pInteger The ASN.1 integer to treat as unsigned.
910 * @param u32Const The uint32_t constant to compare with.
911 * @remarks We don't bother with U16 and U8 variants, just use this instead.
912 */
913RTDECL(int) RTAsn1Integer_UnsignedCompareWithU32(PCRTASN1INTEGER pInteger, uint32_t u32Const);
914
915
916/**
917 * Initializes a big integer number from an ASN.1 integer.
918 *
919 * @returns IPRT status code.
920 * @param pInteger The ASN.1 integer.
921 * @param pBigNum The big integer number structure to initialize.
922 * @param fBigNumInit Subset of RTBIGNUMINIT_F_XXX that concerns
923 * senitivity, signedness and endianness.
924 */
925RTDECL(int) RTAsn1Integer_ToBigNum(PCRTASN1INTEGER pInteger, PRTBIGNUM pBigNum, uint32_t fBigNumInit);
926RTDECL(int) RTAsn1Integer_FromBigNum(PRTASN1INTEGER pThis, PCRTBIGNUM pBigNum, PCRTASN1ALLOCATORVTABLE pAllocator);
927
928/**
929 * Converts the integer to a string.
930 *
931 * This will produce a hex represenation of the number. If it fits in 64-bit, a
932 * C style hex number will be produced. If larger than 64-bit, it will be
933 * printed as a space separated string of hex bytes.
934 *
935 * @returns IPRT status code.
936 * @param pThis The ASN.1 integer.
937 * @param pszBuf The output buffer.
938 * @param cbBuf The buffer size.
939 * @param fFlags Flags reserved for future exploits. MBZ.
940 * @param pcbActual Where to return the amount of buffer space used
941 * (i.e. including terminator). Optional.
942 *
943 * @remarks Currently assume unsigned number.
944 */
945RTDECL(int) RTAsn1Integer_ToString(PRTASN1INTEGER pThis, char *pszBuf, size_t cbBuf, uint32_t fFlags, size_t *pcbActual);
946
947RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFINTEGERS, RTASN1INTEGER, RTDECL, RTAsn1SeqOfIntegers);
948RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFINTEGERS, RTASN1INTEGER, RTDECL, RTAsn1SetOfIntegers);
949
950
951
952/**
953 * ASN.1 boolean (IPRT representation).
954 */
955typedef struct RTASN1BOOLEAN
956{
957 /** Core ASN.1 encoding details. */
958 RTASN1CORE Asn1Core;
959 /** The boolean value. */
960 bool fValue;
961} RTASN1BOOLEAN;
962/** Pointer to the IPRT representation of an ASN.1 boolean. */
963typedef RTASN1BOOLEAN *PRTASN1BOOLEAN;
964/** Pointer to the const IPRT representation of an ASN.1 boolean. */
965typedef RTASN1BOOLEAN const *PCRTASN1BOOLEAN;
966/** The Vtable for a RTASN1BOOLEAN structure. */
967extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Boolean_Vtable;
968
969RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1BOOLEAN, RTDECL, RTAsn1Boolean, Asn1Core);
970
971/**
972 * Initializes a boolean object to a default value.
973 * @returns VINF_SUCCESS
974 * @param pBoolean The boolean object representation.
975 * @param fValue The default value.
976 * @param pAllocator The allocator (pro forma).
977 */
978RTDECL(int) RTAsn1Boolean_InitDefault(PRTASN1BOOLEAN pBoolean, bool fValue, PCRTASN1ALLOCATORVTABLE pAllocator);
979RTDECL(int) RTAsn1Boolean_Set(PRTASN1BOOLEAN pThis, bool fValue);
980
981RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFBOOLEANS, RTASN1BOOLEAN, RTDECL, RTAsn1SeqOfBooleans);
982RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFBOOLEANS, RTASN1BOOLEAN, RTDECL, RTAsn1SetOfBooleans);
983
984
985
986/**
987 * ASN.1 UTC and Generalized Time (IPRT representation).
988 *
989 * The two time types only differs in the precision the render (UTC time being
990 * the one for which you go "WTF were they thinking?!!" for in 2014).
991 */
992typedef struct RTASN1TIME
993{
994 /** The core structure, either ASN1_TAG_UTC_TIME or
995 * ASN1_TAG_GENERALIZED_TIME. */
996 RTASN1CORE Asn1Core;
997 /** The exploded time. */
998 RTTIME Time;
999} RTASN1TIME;
1000/** Pointer to an IPRT representation of ASN.1 UTC/Generalized time. */
1001typedef RTASN1TIME *PRTASN1TIME;
1002/** Pointer to a const IPRT representation of ASN.1 UTC/Generalized time. */
1003typedef RTASN1TIME const *PCRTASN1TIME;
1004/** The Vtable for a RTASN1TIME structure. */
1005extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Time_Vtable;
1006
1007RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1Time, Asn1Core);
1008
1009RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1UtcTime, Asn1Core);
1010RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1GeneralizedTime, Asn1Core);
1011
1012/**
1013 * Compares two ASN.1 time values.
1014 *
1015 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
1016 * @param pLeft The first ASN.1 time object.
1017 * @param pTsRight The second time to compare.
1018 */
1019RTDECL(int) RTAsn1Time_CompareWithTimeSpec(PCRTASN1TIME pLeft, PCRTTIMESPEC pTsRight);
1020
1021/** @name Predicate macros for determing the exact type of RTASN1TIME.
1022 * @{ */
1023/** True if UTC time. */
1024#define RTASN1TIME_IS_UTC_TIME(a_pAsn1Time) ((a_pAsn1Time)->Asn1Core.uTag == ASN1_TAG_UTC_TIME)
1025/** True if generalized time. */
1026#define RTASN1TIME_IS_GENERALIZED_TIME(a_pAsn1Time) ((a_pAsn1Time)->Asn1Core.uTag == ASN1_TAG_GENERALIZED_TIME)
1027/** @} */
1028
1029RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFTIMES, RTASN1TIME, RTDECL, RTAsn1SeqOfTimes);
1030RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFTIMES, RTASN1TIME, RTDECL, RTAsn1SetOfTimes);
1031
1032
1033
1034/**
1035 * ASN.1 object identifier (IPRT representation).
1036 */
1037typedef struct RTASN1OBJID
1038{
1039 /** Core ASN.1 encoding details. */
1040 RTASN1CORE Asn1Core;
1041 /** Coverning the paComponents memory allocation if there isn't enough room in
1042 * szObjId for both the dottet string and the component values. */
1043 RTASN1ALLOCATION Allocation;
1044 /** Pointer to an array with the component values.
1045 * This may point within szObjId if there is enough space for both there. */
1046 uint32_t const *pauComponents;
1047 /** The number of components in the object identifier.
1048 * This ASSUMES that nobody will be ever needing more than 255 components. */
1049 uint8_t cComponents;
1050 /** The dotted string representation of the object identifier.
1051 * If there is sufficient space after the string, we will place the array that
1052 * paComponents points to here and/or the raw content bytes (Asn1Core.uData).
1053 *
1054 * An analysis of dumpasn1.cfg, hl7.org and our own _OID defines indicates
1055 * that we need space for at least 10 components and 30-something chars. We've
1056 * allocated 87 bytes, which we ASSUME should be enough for everyone. */
1057 char szObjId[87];
1058} RTASN1OBJID;
1059/** Pointer to an ASN.1 object identifier representation. */
1060typedef RTASN1OBJID *PRTASN1OBJID;
1061/** Pointer to a const ASN.1 object identifier representation. */
1062typedef RTASN1OBJID const *PCRTASN1OBJID;
1063/** The Vtable for a RTASN1OBJID structure. */
1064extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1ObjId_Vtable;
1065
1066RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1OBJID, RTDECL, RTAsn1ObjId, Asn1Core);
1067
1068RTDECL(int) RTAsn1ObjId_InitFromString(PRTASN1OBJID pThis, const char *pszObjId, PCRTASN1ALLOCATORVTABLE pAllocator);
1069
1070/**
1071 * Compares an ASN.1 object identifier with a dotted object identifier string.
1072 *
1073 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
1074 * @param pThis The ASN.1 object identifier.
1075 * @param pszRight The dotted object identifier string.
1076 */
1077RTDECL(int) RTAsn1ObjId_CompareWithString(PCRTASN1OBJID pThis, const char *pszRight);
1078
1079/**
1080 * Checks if an ASN.1 object identifier starts with the given dotted object
1081 * identifier string.
1082 *
1083 * The matching is only successful if the given string matches matches the last
1084 * component completely.
1085 *
1086 * @returns true / false.
1087 * @param pThis The ASN.1 object identifier.
1088 * @param pszStartsWith The dotted object identifier string.
1089 */
1090RTDECL(bool) RTAsn1ObjId_StartsWith(PCRTASN1OBJID pThis, const char *pszStartsWith);
1091
1092RTDECL(uint8_t) RTAsn1ObjIdCountComponents(PCRTASN1OBJID pThis);
1093RTDECL(uint32_t) RTAsn1ObjIdGetComponentsAsUInt32(PCRTASN1OBJID pThis, uint8_t iComponent);
1094RTDECL(uint32_t) RTAsn1ObjIdGetLastComponentsAsUInt32(PCRTASN1OBJID pThis);
1095
1096RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFOBJIDS, RTASN1OBJID, RTDECL, RTAsn1SeqOfObjIds);
1097RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOBJIDS, RTASN1OBJID, RTDECL, RTAsn1SetOfObjIds);
1098RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOBJIDSEQS, RTASN1SEQOFOBJIDS, RTDECL, RTAsn1SetOfObjIdSeqs);
1099
1100
1101/**
1102 * ASN.1 bit string (IPRT representation).
1103 */
1104typedef struct RTASN1BITSTRING
1105{
1106 /** Core ASN.1 encoding details. */
1107 RTASN1CORE Asn1Core;
1108 /** The number of bits. */
1109 uint32_t cBits;
1110 /** The max number of bits (given at decoding / construction). */
1111 uint32_t cMaxBits;
1112 /** Pointer to the bits. */
1113 RTCPTRUNION uBits;
1114 /** Pointer to user structure encapsulated in this string, if dynamically
1115 * allocated the EncapsulatedAllocation member can be used to track it and
1116 * trigger automatic cleanup on object destruction. If EncapsulatedAllocation
1117 * is zero, any object pointed to will only be deleted. */
1118 PRTASN1CORE pEncapsulated;
1119 /** Allocation tracking structure for pEncapsulated. */
1120 RTASN1ALLOCATION EncapsulatedAllocation;
1121} RTASN1BITSTRING;
1122/** Pointer to the IPRT representation of an ASN.1 bit string. */
1123typedef RTASN1BITSTRING *PRTASN1BITSTRING;
1124/** Pointer to the const IPRT representation of an ASN.1 bit string. */
1125typedef RTASN1BITSTRING const *PCRTASN1BITSTRING;
1126/** The Vtable for a RTASN1BITSTRING structure. */
1127extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1BitString_Vtable;
1128
1129RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1BITSTRING, RTDECL, RTAsn1BitString, Asn1Core);
1130
1131/**
1132 * Calculates pointer to the first bit.
1133 *
1134 * @returns Byte pointer to the first bit.
1135 * @param a_pBitString The ASN.1 bit string.
1136 */
1137#define RTASN1BITSTRING_GET_BIT0_PTR(a_pBitString) ( &(a_pBitString)->Asn1Core.uData.pu8[1] )
1138
1139/**
1140 * Calculates the size in bytes.
1141 *
1142 * @returns Rounded up size in bytes.
1143 * @param a_pBitString The ASN.1 bit string.
1144 */
1145#define RTASN1BITSTRING_GET_BYTE_SIZE(a_pBitString) ( ((a_pBitString)->cBits + 7U) >> 3 )
1146
1147RTDECL(int) RTAsn1BitString_DecodeAsn1Ex(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t cMaxBits, PRTASN1BITSTRING pThis,
1148 const char *pszErrorTag);
1149RTDECL(uint64_t) RTAsn1BitString_GetAsUInt64(PCRTASN1BITSTRING pThis);
1150
1151RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFBITSTRINGS, RTASN1BITSTRING, RTDECL, RTAsn1SeqOfBitStrings);
1152RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFBITSTRINGS, RTASN1BITSTRING, RTDECL, RTAsn1SetOfBitStrings);
1153
1154
1155/**
1156 * ASN.1 octet string (IPRT representation).
1157 */
1158typedef struct RTASN1OCTETSTRING
1159{
1160 /** Core ASN.1 encoding details. */
1161 RTASN1CORE Asn1Core;
1162 /** Pointer to user structure encapsulated in this string.
1163 *
1164 * If dynamically allocated the EncapsulatedAllocation member can be used to
1165 * track it and trigger automatic cleanup on object destruction. If
1166 * EncapsulatedAllocation is zero, any object pointed to will only be
1167 * deleted. */
1168 PRTASN1CORE pEncapsulated;
1169 /** Allocation tracking structure for pEncapsulated. */
1170 RTASN1ALLOCATION EncapsulatedAllocation;
1171} RTASN1OCTETSTRING;
1172/** Pointer to the IPRT representation of an ASN.1 octet string. */
1173typedef RTASN1OCTETSTRING *PRTASN1OCTETSTRING;
1174/** Pointer to the const IPRT representation of an ASN.1 octet string. */
1175typedef RTASN1OCTETSTRING const *PCRTASN1OCTETSTRING;
1176/** The Vtable for a RTASN1OCTETSTRING structure. */
1177extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1OctetString_Vtable;
1178
1179RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1OCTETSTRING, RTDECL, RTAsn1OctetString, Asn1Core);
1180
1181RTDECL(int) RTAsn1OctetStringCompare(PCRTASN1OCTETSTRING pLeft, PCRTASN1OCTETSTRING pRight);
1182
1183RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFOCTETSTRINGS, RTASN1OCTETSTRING, RTDECL, RTAsn1SeqOfOctetStrings);
1184RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOCTETSTRINGS, RTASN1OCTETSTRING, RTDECL, RTAsn1SetOfOctetStrings);
1185
1186
1187/**
1188 * ASN.1 string (IPRT representation).
1189 * All char string types except 'character string (29)'.
1190 */
1191typedef struct RTASN1STRING
1192{
1193 /** Core ASN.1 encoding details. */
1194 RTASN1CORE Asn1Core;
1195 /** Allocation tracking for pszUtf8. */
1196 RTASN1ALLOCATION Allocation;
1197 /** If conversion to UTF-8 was requested, we cache that here. */
1198 char const *pszUtf8;
1199 /** The length (chars, not code points) of the above UTF-8 string if
1200 * present. */
1201 uint32_t cchUtf8;
1202} RTASN1STRING;
1203/** Pointer to the IPRT representation of an ASN.1 string. */
1204typedef RTASN1STRING *PRTASN1STRING;
1205/** Pointer to the const IPRT representation of an ASN.1 string. */
1206typedef RTASN1STRING const *PCRTASN1STRING;
1207/** The Vtable for a RTASN1STRING structure. */
1208extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1String_Vtable;
1209
1210RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1String, Asn1Core);
1211
1212/** @name String type predicate macros.
1213 * @{ */
1214#define RTASN1STRING_IS_NUMERIC(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_NUMERIC_STRING )
1215#define RTASN1STRING_IS_PRINTABLE(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_PRINTABLE_STRING )
1216#define RTASN1STRING_IS_T61(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_T61_STRING )
1217#define RTASN1STRING_IS_VIDEOTEX(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_VIDEOTEX_STRING )
1218#define RTASN1STRING_IS_VISIBLE(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_VISIBLE_STRING )
1219#define RTASN1STRING_IS_IA5(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_IA5_STRING )
1220#define RTASN1STRING_IS_GRAPHIC(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_GRAPHIC_STRING )
1221#define RTASN1STRING_IS_GENERAL(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_GENERAL_STRING )
1222/** UTF-8. */
1223#define RTASN1STRING_IS_UTF8(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_UTF8_STRING )
1224/** UCS-2. */
1225#define RTASN1STRING_IS_BMP(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_BMP_STRING )
1226/** UCS-4. */
1227#define RTASN1STRING_IS_UNIVERSAL(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_UNIVERSAL_STRING )
1228/** @} */
1229
1230RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1NumericString, Asn1Core);
1231RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1PrintableString, Asn1Core);
1232RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1T61String, Asn1Core);
1233RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1VideoTexString, Asn1Core);
1234RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1VisibleString, Asn1Core);
1235RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1Ia5String, Asn1Core);
1236RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1GraphicString, Asn1Core);
1237RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1GeneralString, Asn1Core);
1238RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1Utf8String, Asn1Core);
1239RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1BmpString, Asn1Core);
1240RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1UniversalString, Asn1Core);
1241
1242RTDECL(int) RTAsn1String_InitWithValue(PRTASN1STRING pThis, const char *pszUtf8Value, PCRTASN1ALLOCATORVTABLE pAllocator);
1243RTDECL(int) RTAsn1String_InitEx(PRTASN1STRING pThis, uint32_t uTag, void const *pvValue, size_t cbValue,
1244 PCRTASN1ALLOCATORVTABLE pAllocator);
1245
1246/**
1247 * Compares two strings values, extended version.
1248 *
1249 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
1250 * @param pLeft The first string.
1251 * @param pRight The second string.
1252 * @param fTypeToo Set if the string types must match, false if
1253 * not.
1254 */
1255RTDECL(int) RTAsn1String_CompareEx(PCRTASN1STRING pLeft, PCRTASN1STRING pRight, bool fTypeToo);
1256
1257/**
1258 * Compares a ASN.1 string object with an UTF-8 string.
1259 *
1260 * @returns 0 if equal, -1 if @a pThis is smaller, 1 if @a pThis is larger.
1261 * @param pThis The ASN.1 string object.
1262 * @param pszString The UTF-8 string.
1263 * @param cchString The length of @a pszString, or RTSTR_MAX.
1264 */
1265RTDECL(int) RTAsn1String_CompareWithString(PCRTASN1STRING pThis, const char *pszString, size_t cchString);
1266
1267/**
1268 * Queries the UTF-8 length of an ASN.1 string object.
1269 *
1270 * This differs from RTAsn1String_QueryUtf8 in that it won't need to allocate
1271 * memory for the converted string, but just calculates the length.
1272 *
1273 * @returns IPRT status code.
1274 * @param pThis The ASN.1 string object.
1275 * @param pcch Where to return the string length.
1276 */
1277RTDECL(int) RTAsn1String_QueryUtf8Len(PCRTASN1STRING pThis, size_t *pcch);
1278
1279/**
1280 * Queries the UTF-8 string for an ASN.1 string object.
1281 *
1282 * This may fail as it may require memory to be allocated for storing the
1283 * string.
1284 *
1285 * @returns IPRT status code.
1286 * @param pString The ASN.1 string object. This is a const
1287 * parameter for making life easier on the caller,
1288 * however be aware that the object may be modified
1289 * by this call!
1290 * @param ppsz Where to return the pointer to the UTF-8 string.
1291 * Optional.
1292 * @param pcch Where to return the length (in 8-bit chars) to
1293 * of the UTF-8 string. Optional.
1294 */
1295RTDECL(int) RTAsn1String_QueryUtf8(PCRTASN1STRING pString, const char **ppsz, size_t *pcch);
1296RTDECL(int) RTAsn1String_RecodeAsUtf8(PRTASN1STRING pThis, PCRTASN1ALLOCATORVTABLE pAllocator);
1297
1298RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFSTRINGS, RTASN1STRING, RTDECL, RTAsn1SeqOfStrings);
1299RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFSTRINGS, RTASN1STRING, RTDECL, RTAsn1SetOfStrings);
1300
1301
1302
1303/**
1304 * ASN.1 generic context specific tag (IPRT representation).
1305 *
1306 * Normally used to tag something that's optional, version specific or such.
1307 *
1308 * For the purpose of documenting the format with typedefs as well as possibly
1309 * making it a little more type safe, there's a set of typedefs for the most
1310 * commonly used tag values defined. These typedefs have are identical to
1311 * RTASN1CONTEXTTAG, except from the C++ type system point of view.
1312 */
1313typedef struct RTASN1CONTEXTTAG
1314{
1315 /** Core ASN.1 encoding details. */
1316 RTASN1CORE Asn1Core;
1317} RTASN1CONTEXTTAG;
1318/** Pointer to an ASN.1 context tag (IPRT thing). */
1319typedef RTASN1CONTEXTTAG *PRTASN1CONTEXTTAG;
1320/** Pointer to a const ASN.1 context tag (IPRT thing). */
1321typedef RTASN1CONTEXTTAG const *PCRTASN1CONTEXTTAG;
1322
1323RTDECL(int) RTAsn1ContextTagN_Init(PRTASN1CONTEXTTAG pThis, uint32_t uTag, PCRTASN1COREVTABLE pVtable);
1324RTDECL(int) RTAsn1ContextTagN_Clone(PRTASN1CONTEXTTAG pThis, PCRTASN1CONTEXTTAG pSrc, uint32_t uTag);
1325
1326
1327/** @internal */
1328#define RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(a_uTag) \
1329 typedef struct RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) { RTASN1CORE Asn1Core; } RT_CONCAT(RTASN1CONTEXTTAG,a_uTag); \
1330 typedef RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) *RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag); \
1331 DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pThis, \
1332 PCRTASN1COREVTABLE pVtable, PCRTASN1ALLOCATORVTABLE pAllocator) \
1333 { \
1334 NOREF(pAllocator); \
1335 return RTAsn1ContextTagN_Init((PRTASN1CONTEXTTAG)pThis, a_uTag, pVtable); \
1336 } \
1337 DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pThis, \
1338 RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) const *pSrc) \
1339 { return RTAsn1ContextTagN_Clone((PRTASN1CONTEXTTAG)pThis, (PCRTASN1CONTEXTTAG)pSrc, a_uTag); } \
1340 typedef RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) const *RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag)
1341RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(0);
1342RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(1);
1343RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(2);
1344RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(3);
1345RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(4);
1346RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(5);
1347RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(6);
1348RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(7);
1349#undef RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE
1350
1351/** Helper for comparing optional context tags.
1352 * This will return if both are not present or if their precense differs.
1353 * @internal */
1354#define RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, a_uTag) \
1355 do { \
1356 /* type checks */ \
1357 RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag) const pMyLeftInternal = (a_pLeft); \
1358 RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag) const pMyRightInternal = (a_pRight); \
1359 (a_iDiff) = (int)RTASN1CORE_IS_PRESENT(&pMyLeftInternal->Asn1Core) \
1360 - (int)RTASN1CORE_IS_PRESENT(&pMyRightInternal->Asn1Core); \
1361 if ((a_iDiff) || !RTASN1CORE_IS_PRESENT(&pMyLeftInternal->Asn1Core)) return iDiff; \
1362 } while (0)
1363
1364/** Helpers for comparing optional context tags.
1365 * This will return if both are not present or if their precense differs.
1366 * @{ */
1367#define RTASN1CONTEXTTAG0_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 0)
1368#define RTASN1CONTEXTTAG1_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 1)
1369#define RTASN1CONTEXTTAG2_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 2)
1370#define RTASN1CONTEXTTAG3_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 3)
1371#define RTASN1CONTEXTTAG4_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 4)
1372#define RTASN1CONTEXTTAG5_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 5)
1373#define RTASN1CONTEXTTAG6_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 6)
1374#define RTASN1CONTEXTTAG7_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 7)
1375/** @} */
1376
1377
1378/**
1379 * Type information for dynamically bits (see RTASN1DYNTYPE).
1380 */
1381typedef enum RTASN1TYPE
1382{
1383 /** Not present. */
1384 RTASN1TYPE_NOT_PRESENT = 0,
1385 /** Generic ASN.1 for unknown tag/class. */
1386 RTASN1TYPE_CORE,
1387 /** ASN.1 NULL. */
1388 RTASN1TYPE_NULL,
1389 /** ASN.1 integer. */
1390 RTASN1TYPE_INTEGER,
1391 /** ASN.1 boolean. */
1392 RTASN1TYPE_BOOLEAN,
1393 /** ASN.1 character string. */
1394 RTASN1TYPE_STRING,
1395 /** ASN.1 octet string. */
1396 RTASN1TYPE_OCTET_STRING,
1397 /** ASN.1 bite string. */
1398 RTASN1TYPE_BIT_STRING,
1399 /** ASN.1 UTC or Generalize time. */
1400 RTASN1TYPE_TIME,
1401#if 0
1402 /** ASN.1 sequence core. */
1403 RTASN1TYPE_SEQUENCE_CORE,
1404 /** ASN.1 set core. */
1405 RTASN1TYPE_SET_CORE,
1406#endif
1407 /** ASN.1 object identifier. */
1408 RTASN1TYPE_OBJID,
1409 /** End of valid types. */
1410 RTASN1TYPE_END,
1411 /** Type size hack. */
1412 RTASN1TYPE_32BIT_HACK = 0x7fffffff
1413} RTASN1TYPE;
1414
1415
1416/**
1417 * ASN.1 dynamic type record.
1418 */
1419typedef struct RTASN1DYNTYPE
1420{
1421 /** Alternative interpretation provided by a user.
1422 * Before destroying this object, the user must explicitly free this and set
1423 * it to NULL, otherwise there will be memory leaks. */
1424 PRTASN1CORE pUser;
1425 /** The type of data we've got here. */
1426 RTASN1TYPE enmType;
1427 /** Union with data of the type dictated by enmType. */
1428 union
1429 {
1430 /** RTASN1TYPE_CORE. */
1431 RTASN1CORE Core;
1432 /** RTASN1TYPE_NULL. */
1433 RTASN1NULL Asn1Null;
1434 /** RTASN1TYPE_INTEGER. */
1435 RTASN1INTEGER Integer;
1436 /** RTASN1TYPE_BOOLEAN. */
1437 RTASN1BOOLEAN Boolean;
1438 /** RTASN1TYPE_STRING. */
1439 RTASN1STRING String;
1440 /** RTASN1TYPE_OCTET_STRING. */
1441 RTASN1OCTETSTRING OctetString;
1442 /** RTASN1TYPE_BIT_STRING. */
1443 RTASN1BITSTRING BitString;
1444 /** RTASN1TYPE_TIME. */
1445 RTASN1TIME Time;
1446#if 0
1447 /** RTASN1TYPE_SEQUENCE_CORE. */
1448 RTASN1SEQUENCECORE SeqCore;
1449 /** RTASN1TYPE_SET_CORE. */
1450 RTASN1SETCORE SetCore;
1451#endif
1452 /** RTASN1TYPE_OBJID. */
1453 RTASN1OBJID ObjId;
1454 } u;
1455} RTASN1DYNTYPE;
1456/** Pointer to an ASN.1 dynamic type record. */
1457typedef RTASN1DYNTYPE *PRTASN1DYNTYPE;
1458/** Pointer to a const ASN.1 dynamic type record. */
1459typedef RTASN1DYNTYPE const *PCRTASN1DYNTYPE;
1460RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1DYNTYPE, RTDECL, RTAsn1DynType, u.Core);
1461
1462
1463/** @name Virtual Method Table Based API
1464 * @{ */
1465/**
1466 * Calls the destructor of the ASN.1 object.
1467 *
1468 * @param pThisCore The IPRT representation of an ASN.1 object.
1469 */
1470RTDECL(void) RTAsn1VtDelete(PRTASN1CORE pThisCore);
1471
1472/**
1473 * Deep enumeration of all descendants.
1474 *
1475 * @returns IPRT status code, any non VINF_SUCCESS value stems from pfnCallback.
1476 * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
1477 * @param pfnCallback The callback.
1478 * @param uDepth The depth of this object. Children are at +1.
1479 * @param pvUser Callback user argument.
1480 * @param fDepthFirst When set, recurse into child objects before calling
1481 * pfnCallback on then. When clear, the child object
1482 * is first
1483 */
1484RTDECL(int) RTAsn1VtDeepEnum(PRTASN1CORE pThisCore, bool fDepthFirst, uint32_t uDepth,
1485 PFNRTASN1ENUMCALLBACK pfnCallback, void *pvUser);
1486
1487/**
1488 * Clones @a pSrcCore onto @a pThisCore.
1489 *
1490 * The caller must be sure that @a pSrcCore and @a pThisCore are of the same
1491 * types.
1492 *
1493 * @returns IPRT status code.
1494 * @param pThisCore Pointer to the ASN.1 core to clone onto. This shall
1495 * be uninitialized.
1496 * @param pSrcCore Pointer to the ASN.1 core to clone.
1497 * @param pAllocator The allocator to use.
1498 */
1499RTDECL(int) RTAsn1VtClone(PRTASN1CORE pThisCore, PRTASN1CORE pSrcCore, PCRTASN1ALLOCATORVTABLE pAllocator);
1500
1501/**
1502 * Compares two objects.
1503 *
1504 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
1505 * @param pLeftCore Pointer to the ASN.1 core of the left side object.
1506 * @param pRightCore Pointer to the ASN.1 core of the right side object.
1507 */
1508RTDECL(int) RTAsn1VtCompare(PCRTASN1CORE pLeftCore, PCRTASN1CORE pRightCore);
1509
1510/**
1511 * Check sanity.
1512 *
1513 * A primary criteria is that the object is present and initialized.
1514 *
1515 * @returns IPRT status code.
1516 * @param pThisCore Pointer to the ASN.1 core of the object to check out.
1517 * @param fFlags See RTASN1_CHECK_SANITY_F_XXX.
1518 * @param pErrInfo Where to return additional error details. Optional.
1519 * @param pszErrorTag Tag for the additional error details.
1520 */
1521RTDECL(int) RTAsn1VtCheckSanity(PCRTASN1CORE pThisCore, uint32_t fFlags,
1522 PRTERRINFO pErrInfo, const char *pszErrorTag);
1523/** @} */
1524
1525
1526/** @defgroup rp_asn1_encode RTAsn1Encode - ASN.1 Encoding
1527 * @{ */
1528
1529/** @name RTASN1ENCODE_F_XXX
1530 * @{ */
1531/** Use distinguished encoding rules (DER) to encode the object. */
1532#define RTASN1ENCODE_F_DER UINT32_C(0x00000001)
1533/** Use base encoding rules (BER) to encode the object.
1534 * This is currently the same as DER for practical reasons. */
1535#define RTASN1ENCODE_F_BER RTASN1ENCODE_F_DER
1536/** Mask of valid encoding rules. */
1537#define RTASN1ENCODE_F_RULE_MASK UINT32_C(0x00000007)
1538/** @} */
1539
1540
1541/**
1542 * Recalculates cbHdr of and ASN.1 object.
1543 *
1544 * @returns IPRT status code.
1545 * @retval VINF_ASN1_NOT_ENCODED if the header size is zero (default value,
1546 * whatever).
1547 * @param pAsn1Core The object in question.
1548 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1549 * flags. Must include the encoding type.
1550 * @param pErrInfo Extended error info. Optional.
1551 */
1552RTDECL(int) RTAsn1EncodeRecalcHdrSize(PRTASN1CORE pAsn1Core, uint32_t fFlags, PRTERRINFO pErrInfo);
1553
1554/**
1555 * Prepares the ASN.1 structure for encoding.
1556 *
1557 * The preparations is mainly calculating accurate object size, but may also
1558 * involve operations like recoding internal UTF-8 strings to the actual ASN.1
1559 * format and other things that may require memory to allocated/reallocated.
1560 *
1561 * @returns IPRT status code
1562 * @param pRoot The root of the ASN.1 object tree to encode.
1563 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1564 * flags. Must include the encoding type.
1565 * @param pcbEncoded Where to return the encoded size. Optional.
1566 * @param pErrInfo Where to store extended error information.
1567 * Optional.
1568 */
1569RTDECL(int) RTAsn1EncodePrepare(PRTASN1CORE pRoot, uint32_t fFlags, uint32_t *pcbEncoded, PRTERRINFO pErrInfo);
1570
1571/**
1572 * Encodes and writes the header of an ASN.1 object.
1573 *
1574 * @returns IPRT status code.
1575 * @retval VINF_ASN1_NOT_ENCODED if nothing was written (default value,
1576 * whatever).
1577 * @param pAsn1Core The object in question.
1578 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1579 * flags. Must include the encoding type.
1580 * @param pfnWriter The output writer callback.
1581 * @param pvUser The user argument to pass to @a pfnWriter.
1582 * @param pErrInfo Where to store extended error information.
1583 * Optional.
1584 */
1585RTDECL(int) RTAsn1EncodeWriteHeader(PCRTASN1CORE pAsn1Core, uint32_t fFlags, FNRTASN1ENCODEWRITER pfnWriter, void *pvUser,
1586 PRTERRINFO pErrInfo);
1587
1588/**
1589 * Encodes and writes an ASN.1 object.
1590 *
1591 * @returns IPRT status code
1592 * @param pRoot The root of the ASN.1 object tree to encode.
1593 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1594 * flags. Must include the encoding type.
1595 * @param pfnWriter The output writer callback.
1596 * @param pvUser The user argument to pass to @a pfnWriter.
1597 * @param pErrInfo Where to store extended error information.
1598 * Optional.
1599 */
1600RTDECL(int) RTAsn1EncodeWrite(PCRTASN1CORE pRoot, uint32_t fFlags, FNRTASN1ENCODEWRITER pfnWriter, void *pvUser,
1601 PRTERRINFO pErrInfo);
1602
1603/**
1604 * Encodes and writes an ASN.1 object into a caller allocated memory buffer.
1605 *
1606 * @returns IPRT status code
1607 * @param pRoot The root of the ASN.1 object tree to encode.
1608 * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
1609 * flags. Must include the encoding type.
1610 * @param pvBuf The output buffer.
1611 * @param cbBuf The buffer size. This should have the size
1612 * returned by RTAsn1EncodePrepare().
1613 * @param pErrInfo Where to store extended error information.
1614 * Optional.
1615 */
1616RTDECL(int) RTAsn1EncodeToBuffer(PCRTASN1CORE pRoot, uint32_t fFlags, void *pvBuf, size_t cbBuf, PRTERRINFO pErrInfo);
1617
1618/** @} */
1619
1620
1621
1622/** @defgroup rp_asn1_cursor RTAsn1Cursor - BER, DER, and CER cursor
1623 * @{ */
1624
1625/**
1626 * ASN.1 decoder byte cursor.
1627 */
1628typedef struct RTASN1CURSOR
1629{
1630 /** Pointer to the current (next) byte. */
1631 uint8_t const *pbCur;
1632 /** Number of bytes left to decode. */
1633 uint32_t cbLeft;
1634 /** RTASN1CURSOR_FLAGS_XXX. */
1635 uint8_t fFlags;
1636 /** The cursor depth. */
1637 uint8_t cDepth;
1638 /** Two bytes reserved for future tricks. */
1639 uint8_t abReserved[2];
1640 /** Pointer to the primary cursor. */
1641 struct RTASN1CURSORPRIMARY *pPrimary;
1642 /** Pointer to the parent cursor. */
1643 struct RTASN1CURSOR *pUp;
1644 /** The error tag for this cursor level. */
1645 const char *pszErrorTag;
1646} RTASN1CURSOR;
1647
1648/** @name RTASN1CURSOR_FLAGS_XXX - Cursor flags.
1649 * @{ */
1650/** Enforce DER rules. */
1651#define RTASN1CURSOR_FLAGS_DER RT_BIT(1)
1652/** Enforce CER rules. */
1653#define RTASN1CURSOR_FLAGS_CER RT_BIT(2)
1654/** @} */
1655
1656
1657typedef struct RTASN1CURSORPRIMARY
1658{
1659 /** The normal cursor bits. */
1660 RTASN1CURSOR Cursor;
1661 /** For error reporting. */
1662 PRTERRINFO pErrInfo;
1663 /** The allocator virtual method table. */
1664 PCRTASN1ALLOCATORVTABLE pAllocator;
1665} RTASN1CURSORPRIMARY;
1666typedef RTASN1CURSORPRIMARY *PRTASN1CURSORPRIMARY;
1667
1668
1669/**
1670 * Initializes a primary cursor.
1671 *
1672 * The primary cursor is special in that it stores information shared with the
1673 * sub-cursors created by methods like RTAsn1CursorGetContextTagNCursor and
1674 * RTAsn1CursorGetSequenceCursor. Even if just sharing a few items at present,
1675 * it still important to save every possible byte since stack space is scarce in
1676 * some of the execution environments.
1677 *
1678 * @returns Pointer to pCursor->Cursor.
1679 * @param pPrimaryCursor The primary cursor structure to initialize.
1680 * @param pvFirst The first byte to decode.
1681 * @param cb The number of bytes to decode.
1682 * @param pErrInfo Where to store error information.
1683 * @param pAllocator The allocator to use.
1684 * @param fFlags RTASN1CURSOR_FLAGS_XXX.
1685 * @param pszErrorTag The primary error tag.
1686 */
1687RTDECL(PRTASN1CURSOR) RTAsn1CursorInitPrimary(PRTASN1CURSORPRIMARY pPrimaryCursor, void const *pvFirst, uint32_t cb,
1688 PRTERRINFO pErrInfo, PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t fFlags,
1689 const char *pszErrorTag);
1690
1691
1692/**
1693 * Initialize a sub-cursor for traversing the content of an ASN.1 object.
1694 *
1695 * @returns IPRT status code.
1696 * @param pParent The parent cursor.
1697 * @param pAsn1Core The ASN.1 object which content we should
1698 * traverse with the sub-cursor.
1699 * @param pChild The sub-cursor to initialize.
1700 * @param pszErrorTag The error tag of the sub-cursor.
1701 */
1702RTDECL(int) RTAsn1CursorInitSubFromCore(PRTASN1CURSOR pParent, PRTASN1CORE pAsn1Core,
1703 PRTASN1CURSOR pChild, const char *pszErrorTag);
1704
1705/**
1706 * Initalizes the an allocation structure prior to making an allocation.
1707 *
1708 * To try unify and optimize memory managment for decoding and in-memory
1709 * construction of ASN.1 objects, each allocation has an allocation structure
1710 * associated with it. This stores the allocator and keep statistics for
1711 * optimizing resizable allocations.
1712 *
1713 * @returns Pointer to the allocator info (for call in alloc parameter).
1714 * @param pCursor The cursor.
1715 * @param pAllocation The allocation structure to initialize.
1716 */
1717RTDECL(PRTASN1ALLOCATION) RTAsn1CursorInitAllocation(PRTASN1CURSOR pCursor, PRTASN1ALLOCATION pAllocation);
1718
1719/**
1720 * Initalizes the an array allocation structure prior to making an allocation.
1721 *
1722 * This is a special case of RTAsn1CursorInitAllocation. We store a little bit
1723 * more detail here in order to optimize growing and shrinking of arrays.
1724 *
1725 * @returns Pointer to the allocator info (for call in alloc parameter).
1726 * @param pCursor The cursor.
1727 * @param pAllocation The allocation structure to initialize.
1728 * @param cbEntry The array entry size.
1729 */
1730RTDECL(PRTASN1ARRAYALLOCATION) RTAsn1CursorInitArrayAllocation(PRTASN1CURSOR pCursor, PRTASN1ARRAYALLOCATION pAllocation,
1731 size_t cbEntry);
1732
1733/**
1734 * Wrapper around RTErrInfoSetV.
1735 *
1736 * @returns @a rc
1737 * @param pCursor The cursor.
1738 * @param rc The return code to return.
1739 * @param pszMsg Message format string.
1740 * @param ... Format arguments.
1741 */
1742RTDECL(int) RTAsn1CursorSetInfo(PRTASN1CURSOR pCursor, int rc, const char *pszMsg, ...) RT_IPRT_FORMAT_ATTR(3, 4);
1743
1744/**
1745 * Wrapper around RTErrInfoSetV.
1746 *
1747 * @returns @a rc
1748 * @param pCursor The cursor.
1749 * @param rc The return code to return.
1750 * @param pszMsg Message format string.
1751 * @param va Format arguments.
1752 */
1753RTDECL(int) RTAsn1CursorSetInfoV(PRTASN1CURSOR pCursor, int rc, const char *pszMsg, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
1754
1755/**
1756 * Checks that we've reached the end of the data for the cursor.
1757 *
1758 * @returns IPRT status code.
1759 * @param pCursor The cursor we're decoding from.
1760 */
1761RTDECL(int) RTAsn1CursorCheckEnd(PRTASN1CURSOR pCursor);
1762
1763
1764/**
1765 * Skips a given number of bytes.
1766 *
1767 * @returns @a pCursor
1768 * @param pCursor The cursor.
1769 * @param cb The number of bytes to skip.
1770 * @internal
1771 */
1772DECLINLINE(PRTASN1CURSOR) RTAsn1CursorSkip(PRTASN1CURSOR pCursor, uint32_t cb)
1773{
1774 if (cb <= pCursor->cbLeft)
1775 {
1776 pCursor->cbLeft -= cb;
1777 pCursor->pbCur += cb;
1778 }
1779 else
1780 {
1781 pCursor->pbCur += pCursor->cbLeft;
1782 pCursor->cbLeft = 0;
1783 }
1784
1785 return pCursor;
1786}
1787
1788/**
1789 * Low-level function for reading an ASN.1 header.
1790 *
1791 * @returns IPRT status code.
1792 * @param pCursor The cursor we're decoding from.
1793 * @param pAsn1Core The output object core.
1794 * @param pszErrorTag Error tag.
1795 * @internal
1796 */
1797RTDECL(int) RTAsn1CursorReadHdr(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, const char *pszErrorTag);
1798
1799/**
1800 * Common helper for simple tag matching.
1801 *
1802 * @returns IPRT status code.
1803 * @param pCursor The cursor (for error reporting).
1804 * @param pAsn1Core The ASN.1 core structure.
1805 * @param uTag The expected tag.
1806 * @param fClass The expected class.
1807 * @param fString Set if it's a string type that shall follow
1808 * special CER and DER rules wrt to constructed and
1809 * primitive encoding.
1810 * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
1811 * @param pszErrorTag The error tag.
1812 * @param pszWhat The type/whatever name.
1813 */
1814RTDECL(int) RTAsn1CursorMatchTagClassFlagsEx(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
1815 bool fString, uint32_t fFlags, const char *pszErrorTag, const char *pszWhat);
1816
1817/**
1818 * Common helper for simple tag matching.
1819 *
1820 * @returns IPRT status code.
1821 * @param pCursor The cursor (for error reporting).
1822 * @param pAsn1Core The ASN.1 core structure.
1823 * @param uTag The expected tag.
1824 * @param fClass The expected class.
1825 * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
1826 * @param pszErrorTag The error tag.
1827 * @param pszWhat The type/whatever name.
1828 * @internal
1829 */
1830DECLINLINE(int) RTAsn1CursorMatchTagClassFlags(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
1831 uint32_t fFlags, const char *pszErrorTag, const char *pszWhat)
1832{
1833 if (pAsn1Core->uTag == uTag && pAsn1Core->fClass == fClass)
1834 return VINF_SUCCESS;
1835 return RTAsn1CursorMatchTagClassFlagsEx(pCursor, pAsn1Core, uTag, fClass, false /*fString*/, fFlags, pszErrorTag, pszWhat);
1836}
1837
1838
1839/**
1840 * Common helper for simple tag matching for strings.
1841 *
1842 * Check string encoding considerations.
1843 *
1844 * @returns IPRT status code.
1845 * @param pCursor The cursor (for error reporting).
1846 * @param pAsn1Core The ASN.1 core structure.
1847 * @param uTag The expected tag.
1848 * @param fClass The expected class.
1849 * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
1850 * @param pszErrorTag The error tag.
1851 * @param pszWhat The type/whatever name.
1852 * @internal
1853 */
1854DECLINLINE(int) RTAsn1CursorMatchTagClassFlagsString(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
1855 uint32_t fFlags, const char *pszErrorTag, const char *pszWhat)
1856{
1857 if (pAsn1Core->uTag == uTag && pAsn1Core->fClass == fClass)
1858 return VINF_SUCCESS;
1859 return RTAsn1CursorMatchTagClassFlagsEx(pCursor, pAsn1Core, uTag, fClass, true /*fString*/, fFlags, pszErrorTag, pszWhat);
1860}
1861
1862
1863
1864/** @name RTASN1CURSOR_GET_F_XXX - Common flags for all the getters.
1865 * @{ */
1866/** Used for decoding objects with implicit tags assigned to them. This only
1867 * works when calling getters with a unambigious types. */
1868#define RTASN1CURSOR_GET_F_IMPLICIT RT_BIT_32(0)
1869/** @} */
1870
1871/**
1872 * Read ANY object.
1873 *
1874 * @returns IPRT status code.
1875 * @param pCursor The cursor we're decoding from.
1876 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1877 * @param pAsn1Core The output object core.
1878 * @param pszErrorTag Error tag.
1879 */
1880RTDECL(int) RTAsn1CursorGetCore(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1CORE pAsn1Core, const char *pszErrorTag);
1881
1882/**
1883 * Read a NULL object.
1884 *
1885 * @returns IPRT status code.
1886 * @param pCursor The cursor we're decoding from.
1887 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1888 * @param pNull The output NULL object.
1889 * @param pszErrorTag Error tag.
1890 */
1891RTDECL(int) RTAsn1CursorGetNull(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1NULL pNull, const char *pszErrorTag);
1892
1893/**
1894 * Read an INTEGER object.
1895 *
1896 * @returns IPRT status code.
1897 * @param pCursor The cursor we're decoding from.
1898 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1899 * @param pInteger The output integer object.
1900 * @param pszErrorTag Error tag.
1901 */
1902RTDECL(int) RTAsn1CursorGetInteger(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1INTEGER pInteger, const char *pszErrorTag);
1903
1904/**
1905 * Read an BOOLEAN object.
1906 *
1907 * @returns IPRT status code.
1908 * @param pCursor The cursor we're decoding from.
1909 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1910 * @param pBoolean The output boolean object.
1911 * @param pszErrorTag Error tag.
1912 */
1913RTDECL(int) RTAsn1CursorGetBoolean(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1BOOLEAN pBoolean, const char *pszErrorTag);
1914
1915/**
1916 * Retrives an object identifier (aka ObjId or OID) item from the ASN.1 stream.
1917 *
1918 * @returns IPRT status code.
1919 * @param pCursor The cursor.
1920 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1921 * @param pObjId The output ODI object.
1922 * @param pszErrorTag Error tag.
1923 */
1924RTDECL(int) RTAsn1CursorGetObjId(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pObjId, const char *pszErrorTag);
1925
1926/**
1927 * Retrives and verifies an object identifier.
1928 *
1929 * @returns IPRT status code.
1930 * @param pCursor The cursor.
1931 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1932 * @param pObjId Where to return the parsed object ID, optional.
1933 * @param pszExpectedObjId The expected object identifier (dotted).
1934 * @param pszErrorTag Error tag.
1935 */
1936RTDECL(int) RTAsn1CursorGetAndCheckObjId(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pObjId,
1937 const char *pszExpectedObjId, const char *pszErrorTag);
1938
1939/**
1940 * Read an UTC TIME or GENERALIZED TIME object.
1941 *
1942 * @returns IPRT status code.
1943 * @param pCursor The cursor we're decoding from.
1944 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1945 * @param pTime The output time object.
1946 * @param pszErrorTag Error tag.
1947 */
1948RTDECL(int) RTAsn1CursorGetTime(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1TIME pTime, const char *pszErrorTag);
1949
1950/**
1951 * Read an BIT STRING object (skips past the content).
1952 *
1953 * @returns IPRT status ocde.
1954 * @param pCursor The cursor.
1955 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1956 * @param pBitString The output bit string object.
1957 * @param pszErrorTag Error tag.
1958 */
1959RTDECL(int) RTAsn1CursorGetBitString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1BITSTRING pBitString,
1960 const char *pszErrorTag);
1961
1962/**
1963 * Read an BIT STRING object (skips past the content), extended version with
1964 * cMaxBits.
1965 *
1966 * @returns IPRT status ocde.
1967 * @param pCursor The cursor.
1968 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1969 * @param cMaxBits The max length of the bit string in bits. Pass
1970 * UINT32_MAX if variable size.
1971 * @param pBitString The output bit string object.
1972 * @param pszErrorTag Error tag.
1973 */
1974RTDECL(int) RTAsn1CursorGetBitStringEx(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t cMaxBits, PRTASN1BITSTRING pBitString,
1975 const char *pszErrorTag);
1976
1977/**
1978 * Read an OCTET STRING object (skips past the content).
1979 *
1980 * @returns IPRT status ocde.
1981 * @param pCursor The cursor.
1982 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1983 * @param pOctetString The output octet string object.
1984 * @param pszErrorTag Error tag.
1985 */
1986RTDECL(int) RTAsn1CursorGetOctetString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OCTETSTRING pOctetString,
1987 const char *pszErrorTag);
1988
1989/**
1990 * Read any kind of string object, except 'character string (29)'.
1991 *
1992 * @returns IPRT status code.
1993 * @param pCursor The cursor we're decoding from.
1994 * @param fFlags RTASN1CURSOR_GET_F_XXX.
1995 * @param pString The output boolean object.
1996 * @param pszErrorTag Error tag.
1997 */
1998RTDECL(int) RTAsn1CursorGetString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
1999
2000/**
2001 * Read a IA5 STRING object.
2002 *
2003 * @returns IPRT status code.
2004 * @param pCursor The cursor we're decoding from.
2005 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2006 * @param pString The output boolean object.
2007 * @param pszErrorTag Error tag.
2008 */
2009RTDECL(int) RTAsn1CursorGetIa5String(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
2010
2011/**
2012 * Read a UTF8 STRING object.
2013 *
2014 * @returns IPRT status code.
2015 * @param pCursor The cursor we're decoding from.
2016 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2017 * @param pString The output boolean object.
2018 * @param pszErrorTag Error tag.
2019 */
2020RTDECL(int) RTAsn1CursorGetUtf8String(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
2021
2022/**
2023 * Read a BMP STRING (UCS-2) object.
2024 *
2025 * @returns IPRT status code.
2026 * @param pCursor The cursor we're decoding from.
2027 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2028 * @param pString The output boolean object.
2029 * @param pszErrorTag Error tag.
2030 */
2031RTDECL(int) RTAsn1CursorGetBmpString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
2032
2033/**
2034 * Read a SEQUENCE object and create a cursor for its content.
2035 *
2036 * @returns IPRT status code.
2037 * @param pCursor The cursor we're decoding from.
2038 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2039 * @param pSeqCore The output sequence core object.
2040 * @param pSeqCursor The output cursor for the sequence content.
2041 * @param pszErrorTag Error tag, this will be associated with the
2042 * returned cursor.
2043 */
2044RTDECL(int) RTAsn1CursorGetSequenceCursor(PRTASN1CURSOR pCursor, uint32_t fFlags,
2045 PRTASN1SEQUENCECORE pSeqCore, PRTASN1CURSOR pSeqCursor, const char *pszErrorTag);
2046
2047/**
2048 * Read a SET object and create a cursor for its content.
2049 *
2050 * @returns IPRT status code.
2051 * @param pCursor The cursor we're decoding from.
2052 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2053 * @param pSetCore The output set core object.
2054 * @param pSetCursor The output cursor for the set content.
2055 * @param pszErrorTag Error tag, this will be associated with the
2056 * returned cursor.
2057 */
2058RTDECL(int) RTAsn1CursorGetSetCursor(PRTASN1CURSOR pCursor, uint32_t fFlags,
2059 PRTASN1SETCORE pSetCore, PRTASN1CURSOR pSetCursor, const char *pszErrorTag);
2060
2061/**
2062 * Read a given constructed context tag and create a cursor for its content.
2063 *
2064 * @returns IPRT status code.
2065 * @param pCursor The cursor we're decoding from.
2066 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2067 * @param uExpectedTag The expected tag.
2068 * @param pVtable The vtable for the context tag node (see
2069 * RTASN1TMPL_PASS_XTAG).
2070 * @param pCtxTag The output context tag object.
2071 * @param pCtxTagCursor The output cursor for the context tag content.
2072 * @param pszErrorTag Error tag, this will be associated with the
2073 * returned cursor.
2074 *
2075 * @remarks There are specialized version of this function for each of the
2076 * numbered context tag structures, like for RTASN1CONTEXTTAG0 there is
2077 * RTAsn1CursorGetContextTag0Cursor.
2078 */
2079RTDECL(int) RTAsn1CursorGetContextTagNCursor(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t uExpectedTag,
2080 PCRTASN1COREVTABLE pVtable, PRTASN1CONTEXTTAG pCtxTag, PRTASN1CURSOR pCtxTagCursor,
2081 const char *pszErrorTag);
2082
2083/**
2084 * Read a dynamic ASN.1 type.
2085 *
2086 * @returns IPRT status code.
2087 * @param pCursor The cursor we're decoding from.
2088 * @param fFlags RTASN1CURSOR_GET_F_XXX.
2089 * @param pDynType The output context tag object.
2090 * @param pszErrorTag Error tag.
2091 */
2092RTDECL(int) RTAsn1CursorGetDynType(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1DYNTYPE pDynType, const char *pszErrorTag);
2093
2094/**
2095 * Peeks at the next ASN.1 object.
2096 *
2097 * @returns IPRT status code.
2098 * @param pCursor The cursore we're decoding from.
2099 * @param pAsn1Core Where to store the output of the peek.
2100 */
2101RTDECL(int) RTAsn1CursorPeek(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core);
2102
2103/**
2104 * Checks if the next ASN.1 object matches the given tag and class/flags.
2105 *
2106 * @returns @c true on match, @c false on mismatch.
2107 * @param pCursor The cursore we're decoding from.
2108 * @param uTag The tag number to match against.
2109 * @param fClass The tag class and flags to match against.
2110 */
2111RTDECL(bool) RTAsn1CursorIsNextEx(PRTASN1CURSOR pCursor, uint32_t uTag, uint8_t fClass);
2112
2113
2114
2115/** @internal */
2116#define RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(a_uTag) \
2117 DECLINLINE(int) RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(PRTASN1CURSOR pCursor, uint32_t fFlags, \
2118 PCRTASN1COREVTABLE pVtable, \
2119 RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pCtxTag, \
2120 PRTASN1CURSOR pCtxTagCursor, const char *pszErrorTag) \
2121 { /* Constructed is automatically implied if you need a cursor to it. */ \
2122 return RTAsn1CursorGetContextTagNCursor(pCursor, fFlags, a_uTag, pVtable, (PRTASN1CONTEXTTAG)pCtxTag, pCtxTagCursor, pszErrorTag); \
2123 } \
2124 DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,InitDefault)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pCtxTag) \
2125 { /* Constructed is automatically implied if you need to init it with a default value. */ \
2126 return RTAsn1Core_InitDefault(&pCtxTag->Asn1Core, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED); \
2127 } \
2128 DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsConstructedContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
2129 { \
2130 return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED); \
2131 } \
2132 DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsPrimitiveContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
2133 { \
2134 return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE); \
2135 } \
2136 DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsAnyContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
2137 { \
2138 return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED) \
2139 || RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE);\
2140 } \
2141
2142RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(0)
2143RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(1)
2144RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(2)
2145RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(3)
2146RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(4)
2147RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(5)
2148RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(6)
2149RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(7)
2150#undef RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES
2151
2152
2153/**
2154 * Checks if the next object is a boolean.
2155 *
2156 * @returns true / false
2157 * @param pCursor The cursor we're decoding from.
2158 * @remarks May produce error info output on mismatch.
2159 */
2160DECLINLINE(bool) RTAsn1CursorIsBooleanNext(PRTASN1CURSOR pCursor)
2161{
2162 return RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_BOOLEAN, ASN1_TAGFLAG_PRIMITIVE | ASN1_TAGCLASS_UNIVERSAL);
2163}
2164
2165
2166/**
2167 * Checks if the next object is a set.
2168 *
2169 * @returns true / false
2170 * @param pCursor The cursor we're decoding from.
2171 * @remarks May produce error info output on mismatch.
2172 */
2173DECLINLINE(bool) RTAsn1CursorIsSetNext(PRTASN1CURSOR pCursor)
2174{
2175 return RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_SET, ASN1_TAGFLAG_CONSTRUCTED | ASN1_TAGCLASS_UNIVERSAL);
2176}
2177
2178
2179/** @} */
2180
2181
2182/** @name ASN.1 Utility APIs
2183 * @{ */
2184
2185/**
2186 * Dumps an IPRT representation of a ASN.1 object tree.
2187 *
2188 * @returns IPRT status code.
2189 * @param pAsn1Core The ASN.1 object which members should be dumped.
2190 * @param fFlags RTASN1DUMP_F_XXX.
2191 * @param uLevel The indentation level to start at.
2192 * @param pfnPrintfV The output function.
2193 * @param pvUser Argument to the output function.
2194 */
2195RTDECL(int) RTAsn1Dump(PCRTASN1CORE pAsn1Core, uint32_t fFlags, uint32_t uLevel, PFNRTDUMPPRINTFV pfnPrintfV, void *pvUser);
2196
2197/**
2198 * Queries the name for an object identifier.
2199 *
2200 * This API is very simple due to how we store the data.
2201 *
2202 * @returns IPRT status code.
2203 * @retval VINF_SUCCESS on success.
2204 * @retval VERR_NOT_FOUND if not found.
2205 * @retval VERR_BUFFER_OVERFLOW if more buffer space is required.
2206 *
2207 * @param pObjId The object ID to name.
2208 * @param pszDst Where to store the name if found.
2209 * @param cbDst The size of the destination buffer.
2210 */
2211RTDECL(int) RTAsn1QueryObjIdName(PCRTASN1OBJID pObjId, char *pszDst, size_t cbDst);
2212
2213/** @} */
2214
2215/** @} */
2216
2217RT_C_DECLS_END
2218
2219#endif
2220
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