VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/asn1/asn1-basics.cpp@ 106580

Last change on this file since 106580 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1/* $Id: asn1-basics.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT - ASN.1, Basic Operations.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include "internal/iprt.h"
42#include <iprt/asn1.h>
43
44#include <iprt/alloca.h>
45#include <iprt/bignum.h>
46#include <iprt/ctype.h>
47#include <iprt/err.h>
48#include <iprt/string.h>
49#include <iprt/uni.h>
50
51#include <iprt/formats/asn1.h>
52
53
54/*********************************************************************************************************************************
55* Structures and Typedefs *
56*********************************************************************************************************************************/
57/**
58 * ASN.1 content/value allocation.
59 *
60 * The currently most frequent use of the RTAsn1 module is to decode ASN.1 byte
61 * streams. In that scenario we do not allocate memory for the raw content
62 * bytes, but share it with the byte stream. Also, a great number of RTASN1CORE
63 * structures will never need to have any content bytes allocated with this.
64 *
65 * So, in order to avoid adding an extra 16 (64-bit) or 8 (32-bit) bytes to each
66 * RTASN1CORE structure just to keep track of the occational content allocation,
67 * we put the allocator tracking structure inside the allocation. During
68 * allocator operations it lives temporarily on the stack.
69 */
70typedef struct RTASN1MEMCONTENT
71{
72 /** The allocation tracker. */
73 RTASN1ALLOCATION Allocation;
74#if ARCH_BITS == 32
75 uint32_t Padding; /**< Alignment padding. */
76#endif
77 /** The content bytes, i.e. what RTASN1CORE::uData.pv points to. Use a 64-bit
78 * type here to emphasize that it's 8-byte aligned on all platforms. */
79 uint64_t au64Content[1];
80} RTASN1MEMCONTENT;
81AssertCompileMemberAlignment(RTASN1MEMCONTENT, au64Content, 8);
82/** Pointer to a ASN.1 content allocation. */
83typedef RTASN1MEMCONTENT *PRTASN1MEMCONTENT;
84
85
86
87RTDECL(int) RTAsn1MemResizeArray(PRTASN1ARRAYALLOCATION pAllocation, void ***ppapvArray, uint32_t cCurrent, uint32_t cNew)
88{
89 AssertReturn(pAllocation->pAllocator != NULL, VERR_WRONG_ORDER);
90 AssertReturn(pAllocation->cbEntry > 0, VERR_WRONG_ORDER);
91 AssertReturn(cCurrent <= pAllocation->cEntriesAllocated, VERR_INVALID_PARAMETER);
92 AssertReturn(cCurrent <= pAllocation->cPointersAllocated, VERR_INVALID_PARAMETER);
93 AssertReturn(cNew < _1M, VERR_OUT_OF_RANGE);
94 Assert(pAllocation->cEntriesAllocated <= pAllocation->cPointersAllocated);
95
96 /*
97 * Is there sufficent space allocated already?
98 *
99 * We keep unused entires ZEROed, therefore we must always call the allocator
100 * when shrinking (this also helps with the electric fence allocator).
101 */
102 if (cNew <= pAllocation->cEntriesAllocated)
103 {
104 if (cCurrent <= cNew)
105 return VINF_SUCCESS;
106 pAllocation->pAllocator->pfnShrinkArray(pAllocation->pAllocator, pAllocation, ppapvArray, cCurrent, cNew);
107 return VINF_SUCCESS;
108 }
109
110 /*
111 * Must grow (or do initial alloc).
112 */
113 pAllocation->cResizeCalls++;
114 return pAllocation->pAllocator->pfnGrowArray(pAllocation->pAllocator, pAllocation, ppapvArray, cNew);
115}
116
117
118RTDECL(void) RTAsn1MemFreeArray(PRTASN1ARRAYALLOCATION pAllocation, void **papvArray)
119{
120 Assert(pAllocation->pAllocator != NULL);
121 if (papvArray)
122 {
123 pAllocation->pAllocator->pfnFreeArray(pAllocation->pAllocator, pAllocation, papvArray);
124 Assert(pAllocation->cPointersAllocated == 0);
125 Assert(pAllocation->cEntriesAllocated == 0);
126 }
127}
128
129
130RTDECL(int) RTAsn1MemAllocZ(PRTASN1ALLOCATION pAllocation, void **ppvMem, size_t cbMem)
131{
132 AssertReturn(pAllocation->pAllocator != NULL, VERR_WRONG_ORDER);
133 AssertPtr(ppvMem);
134 Assert(cbMem > 0);
135 int rc = pAllocation->pAllocator->pfnAlloc(pAllocation->pAllocator, pAllocation, ppvMem, cbMem);
136 Assert(pAllocation->cbAllocated >= cbMem || RT_FAILURE_NP(rc));
137 return rc;
138}
139
140
141RTDECL(int) RTAsn1MemDup(PRTASN1ALLOCATION pAllocation, void **ppvMem, const void *pvSrc, size_t cbMem)
142{
143 AssertReturn(pAllocation->pAllocator != NULL, VERR_WRONG_ORDER);
144 AssertPtr(ppvMem);
145 AssertPtr(pvSrc);
146 Assert(cbMem > 0);
147 int rc = pAllocation->pAllocator->pfnAlloc(pAllocation->pAllocator, pAllocation, ppvMem, cbMem);
148 if (RT_SUCCESS(rc))
149 {
150 Assert(pAllocation->cbAllocated >= cbMem);
151 memcpy(*ppvMem, pvSrc, cbMem);
152 return VINF_SUCCESS;
153 }
154 return rc;
155}
156
157
158RTDECL(void) RTAsn1MemFree(PRTASN1ALLOCATION pAllocation, void *pv)
159{
160 Assert(pAllocation->pAllocator != NULL);
161 if (pv)
162 {
163 pAllocation->pAllocator->pfnFree(pAllocation->pAllocator, pAllocation, pv);
164 Assert(pAllocation->cbAllocated == 0);
165 }
166}
167
168
169RTDECL(PRTASN1ALLOCATION) RTAsn1MemInitAllocation(PRTASN1ALLOCATION pAllocation, PCRTASN1ALLOCATORVTABLE pAllocator)
170{
171 pAllocation->cbAllocated = 0;
172 pAllocation->cReallocs = 0;
173 pAllocation->uReserved0 = 0;
174 pAllocation->pAllocator = pAllocator;
175 return pAllocation;
176}
177
178
179RTDECL(PRTASN1ARRAYALLOCATION) RTAsn1MemInitArrayAllocation(PRTASN1ARRAYALLOCATION pAllocation,
180 PCRTASN1ALLOCATORVTABLE pAllocator, size_t cbEntry)
181{
182 Assert(cbEntry >= sizeof(RTASN1CORE));
183 Assert(cbEntry < _1M);
184 Assert(RT_ALIGN_Z(cbEntry, sizeof(void *)) == cbEntry);
185 pAllocation->cbEntry = (uint32_t)cbEntry;
186 pAllocation->cPointersAllocated = 0;
187 pAllocation->cEntriesAllocated = 0;
188 pAllocation->cResizeCalls = 0;
189 pAllocation->uReserved0 = 0;
190 pAllocation->pAllocator = pAllocator;
191 return pAllocation;
192}
193
194
195RTDECL(int) RTAsn1ContentAllocZ(PRTASN1CORE pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator)
196{
197 AssertReturn(pAllocator != NULL, VERR_WRONG_ORDER);
198 AssertReturn(cb > 0 && cb < _1G, VERR_INVALID_PARAMETER);
199 AssertPtr(pAsn1Core);
200 AssertReturn(!(pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT), VERR_INVALID_STATE);
201
202 /* Initialize the temporary allocation tracker. */
203 RTASN1ALLOCATION Allocation;
204 Allocation.cbAllocated = 0;
205 Allocation.cReallocs = 0;
206 Allocation.uReserved0 = 0;
207 Allocation.pAllocator = pAllocator;
208
209 /* Make the allocation. */
210 uint32_t cbAlloc = RT_UOFFSETOF(RTASN1MEMCONTENT, au64Content) + (uint32_t)cb;
211 PRTASN1MEMCONTENT pHdr;
212 int rc = pAllocator->pfnAlloc(pAllocator, &Allocation, (void **)&pHdr, cbAlloc);
213 if (RT_SUCCESS(rc))
214 {
215 Assert(Allocation.cbAllocated >= cbAlloc);
216 pHdr->Allocation = Allocation;
217 pAsn1Core->cb = (uint32_t)cb;
218 pAsn1Core->uData.pv = &pHdr->au64Content[0];
219 pAsn1Core->fFlags |= RTASN1CORE_F_ALLOCATED_CONTENT;
220 }
221
222 return rc;
223}
224
225
226RTDECL(int) RTAsn1ContentDup(PRTASN1CORE pAsn1Core, void const *pvSrc, size_t cbSrc, PCRTASN1ALLOCATORVTABLE pAllocator)
227{
228 int rc = RTAsn1ContentAllocZ(pAsn1Core, cbSrc, pAllocator);
229 if (RT_SUCCESS(rc))
230 memcpy((void *)pAsn1Core->uData.pv, pvSrc, cbSrc);
231 return rc;
232}
233
234
235RTDECL(int) RTAsn1ContentReallocZ(PRTASN1CORE pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator)
236{
237 /* Validate input. */
238 AssertPtr(pAsn1Core);
239 AssertReturn(cb < _1G, VERR_INVALID_PARAMETER);
240
241 if (cb > 0)
242 {
243 /*
244 * Case 1 - Initial allocation.
245 */
246 uint32_t cbNeeded = RT_UOFFSETOF(RTASN1MEMCONTENT, au64Content) + (uint32_t)cb;
247 if (!(pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT))
248 return RTAsn1ContentAllocZ(pAsn1Core, cb, pAllocator);
249
250 /* Locate the header. */
251 PRTASN1MEMCONTENT pHdr = RT_FROM_MEMBER(pAsn1Core->uData.pv, RTASN1MEMCONTENT, au64Content);
252
253 /*
254 * Case 2 - Reallocation using the same allocator.
255 */
256 if ( pHdr->Allocation.pAllocator == pAllocator
257 || !pAllocator)
258 {
259 pHdr->Allocation.cReallocs++;
260
261 /* Modify the allocation if necessary. */
262 if (pHdr->Allocation.cbAllocated < cbNeeded)
263 {
264 RTASN1ALLOCATION Allocation = pHdr->Allocation;
265 int rc = Allocation.pAllocator->pfnRealloc(Allocation.pAllocator, &Allocation, pHdr, (void **)&pHdr, cbNeeded);
266 if (RT_FAILURE(rc))
267 return rc;
268 Assert(Allocation.cbAllocated >= cbNeeded);
269 pAsn1Core->uData.pv = &pHdr->au64Content[0];
270 pHdr->Allocation = Allocation;
271 }
272
273 /* Clear any additional memory we're letting the user use and
274 update the content size. */
275 if (pAsn1Core->cb < cb)
276 RT_BZERO((uint8_t *)&pAsn1Core->uData.pu8[pAsn1Core->cb], cb - pAsn1Core->cb);
277 pAsn1Core->cb = (uint32_t)cb;
278 }
279 /*
280 * Case 3 - Reallocation using a different allocator.
281 */
282 else
283 {
284 /* Initialize the temporary allocation tracker. */
285 RTASN1ALLOCATION Allocation;
286 Allocation.cbAllocated = 0;
287 Allocation.cReallocs = pHdr->Allocation.cReallocs + 1;
288 Allocation.uReserved0 = 0;
289 Allocation.pAllocator = pAllocator;
290
291 /* Make the allocation. */
292 PRTASN1MEMCONTENT pHdrNew;
293 int rc = pAllocator->pfnAlloc(pAllocator, &Allocation, (void **)&pHdrNew, cbNeeded);
294 if (RT_FAILURE(rc))
295 return rc;
296 Assert(Allocation.cbAllocated >= cbNeeded);
297
298 /* Duplicate the old content and zero any new memory we might've added. */
299 if (pAsn1Core->cb >= cb)
300 memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], cb);
301 else
302 {
303 memcpy(&pHdrNew->au64Content[0], &pHdr->au64Content[0], pAsn1Core->cb);
304 RT_BZERO((uint8_t *)&pHdrNew->au64Content[0] + pAsn1Core->cb, cb - pAsn1Core->cb);
305 }
306
307 /* Update the core. */
308 pHdrNew->Allocation = Allocation;
309 pAsn1Core->uData.pv = &pHdrNew->au64Content[0];
310 pAsn1Core->fFlags |= RTASN1CORE_F_ALLOCATED_CONTENT; /* free cleared it. */
311 pAsn1Core->cb = (uint32_t)cb;
312
313 /* Free the old content. */
314 Allocation = pHdr->Allocation;
315 Allocation.pAllocator->pfnFree(Allocation.pAllocator, &Allocation, pHdr);
316 Assert(Allocation.cbAllocated == 0);
317 }
318 }
319 /*
320 * Case 4 - It's a request to free the memory.
321 */
322 else
323 RTAsn1ContentFree(pAsn1Core);
324 return VINF_SUCCESS;
325}
326
327
328RTDECL(void) RTAsn1ContentFree(PRTASN1CORE pAsn1Core)
329{
330 if (pAsn1Core)
331 {
332 pAsn1Core->cb = 0;
333 if (pAsn1Core->fFlags & RTASN1CORE_F_ALLOCATED_CONTENT)
334 {
335 pAsn1Core->fFlags &= ~RTASN1CORE_F_ALLOCATED_CONTENT;
336 AssertReturnVoid(pAsn1Core->uData.pv);
337
338 PRTASN1MEMCONTENT pHdr = RT_FROM_MEMBER(pAsn1Core->uData.pv, RTASN1MEMCONTENT, au64Content);
339 RTASN1ALLOCATION Allocation = pHdr->Allocation;
340
341 Allocation.pAllocator->pfnFree(Allocation.pAllocator, &Allocation, pHdr);
342 Assert(Allocation.cbAllocated == 0);
343 }
344 pAsn1Core->uData.pv = NULL;
345 }
346}
347
348
349
350/*
351 * Virtual method table based API.
352 */
353
354RTDECL(void) RTAsn1VtDelete(PRTASN1CORE pThisCore)
355{
356 if (pThisCore)
357 {
358 PCRTASN1COREVTABLE pOps = pThisCore->pOps;
359 if (pOps)
360 pOps->pfnDtor(pThisCore);
361 }
362}
363
364
365/**
366 * Context data passed by RTAsn1VtDeepEnum to it's worker callbacks.
367 */
368typedef struct RTASN1DEEPENUMCTX
369{
370 PFNRTASN1ENUMCALLBACK pfnCallback;
371 void *pvUser;
372} RTASN1DEEPENUMCTX;
373
374
375static DECLCALLBACK(int) rtAsn1VtDeepEnumDepthFirst(PRTASN1CORE pThisCore, const char *pszName, uint32_t uDepth, void *pvUser)
376{
377 AssertReturn(pThisCore, VINF_SUCCESS);
378
379 if (pThisCore->pOps && pThisCore->pOps->pfnEnum)
380 {
381 int rc = pThisCore->pOps->pfnEnum(pThisCore, rtAsn1VtDeepEnumDepthFirst, uDepth, pvUser);
382 if (rc != VINF_SUCCESS)
383 return rc;
384 }
385
386 RTASN1DEEPENUMCTX *pCtx = (RTASN1DEEPENUMCTX *)pvUser;
387 return pCtx->pfnCallback(pThisCore, pszName, uDepth, pCtx->pvUser);
388}
389
390
391static DECLCALLBACK(int) rtAsn1VtDeepEnumDepthLast(PRTASN1CORE pThisCore, const char *pszName, uint32_t uDepth, void *pvUser)
392{
393 AssertReturn(pThisCore, VINF_SUCCESS);
394
395 RTASN1DEEPENUMCTX *pCtx = (RTASN1DEEPENUMCTX *)pvUser;
396 int rc = pCtx->pfnCallback(pThisCore, pszName, uDepth, pCtx->pvUser);
397 if (rc == VINF_SUCCESS)
398 {
399 if (pThisCore->pOps && pThisCore->pOps->pfnEnum)
400 rc = pThisCore->pOps->pfnEnum(pThisCore, rtAsn1VtDeepEnumDepthFirst, uDepth, pvUser);
401 }
402 return rc;
403}
404
405
406RTDECL(int) RTAsn1VtDeepEnum(PRTASN1CORE pThisCore, bool fDepthFirst, uint32_t uDepth,
407 PFNRTASN1ENUMCALLBACK pfnCallback, void *pvUser)
408{
409 int rc;
410 if (RTAsn1Core_IsPresent(pThisCore))
411 {
412 PCRTASN1COREVTABLE pOps = pThisCore->pOps;
413 if (pOps && pOps->pfnEnum)
414 {
415 RTASN1DEEPENUMCTX Ctx;
416 Ctx.pfnCallback = pfnCallback;
417 Ctx.pvUser = pvUser;
418 rc = pOps->pfnEnum(pThisCore, fDepthFirst ? rtAsn1VtDeepEnumDepthFirst : rtAsn1VtDeepEnumDepthLast, uDepth, &Ctx);
419 }
420 else
421 rc = VINF_SUCCESS;
422 }
423 else
424 rc = VINF_SUCCESS;
425 return rc;
426}
427
428
429RTDECL(int) RTAsn1VtClone(PRTASN1CORE pThisCore, PRTASN1CORE pSrcCore, PCRTASN1ALLOCATORVTABLE pAllocator)
430{
431 AssertPtrReturn(pThisCore, VERR_INVALID_POINTER);
432 AssertPtrReturn(pSrcCore, VERR_INVALID_POINTER);
433 AssertPtrReturn(pAllocator, VERR_INVALID_POINTER);
434
435 if (RTAsn1Core_IsPresent(pSrcCore))
436 {
437 AssertPtrReturn(pSrcCore->pOps, VERR_INVALID_POINTER);
438 AssertPtr(pSrcCore->pOps->pfnClone);
439 return pSrcCore->pOps->pfnClone(pThisCore, pSrcCore, pAllocator);
440 }
441
442 RT_ZERO(*pThisCore);
443 return VINF_SUCCESS;
444}
445
446
447RTDECL(int) RTAsn1VtCompare(PCRTASN1CORE pLeftCore, PCRTASN1CORE pRightCore)
448{
449 int iDiff;
450 if (RTAsn1Core_IsPresent(pLeftCore))
451 {
452 if (RTAsn1Core_IsPresent(pRightCore))
453 {
454 PCRTASN1COREVTABLE pOps = pLeftCore->pOps;
455 if (pOps == pRightCore->pOps)
456 {
457 AssertPtr(pOps->pfnCompare);
458 iDiff = pOps->pfnCompare(pLeftCore, pRightCore);
459 }
460 else
461 iDiff = (uintptr_t)pOps < (uintptr_t)pRightCore->pOps ? -1 : 1;
462 }
463 else
464 iDiff = 1;
465 }
466 else
467 iDiff = 0 - (int)RTAsn1Core_IsPresent(pRightCore);
468 return iDiff;
469}
470
471
472RTDECL(int) RTAsn1VtCheckSanity(PCRTASN1CORE pThisCore, uint32_t fFlags,
473 PRTERRINFO pErrInfo, const char *pszErrorTag)
474{
475 int rc;
476 if (RTAsn1Core_IsPresent(pThisCore))
477 {
478 PCRTASN1COREVTABLE pOps = pThisCore->pOps;
479 if (pOps && pOps->pfnCheckSanity)
480 rc = pOps->pfnCheckSanity(pThisCore, fFlags, pErrInfo, pszErrorTag);
481 else if (pOps)
482 rc = RTErrInfoSetF(pErrInfo, VERR_ASN1_NO_CHECK_SANITY_METHOD,
483 "%s: Has no pfnCheckSanity function.", pszErrorTag);
484 else
485 rc = RTErrInfoSetF(pErrInfo, VERR_ASN1_NO_VTABLE, "%s: Has no Vtable function.", pszErrorTag);
486 }
487 else
488 rc = RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Not present.", pszErrorTag);
489 return rc;
490}
491
492
493
494/*
495 * Dummy ASN.1 object.
496 */
497
498RTDECL(int) RTAsn1Dummy_InitEx(PRTASN1DUMMY pThis)
499{
500 return RTAsn1Core_InitEx(&pThis->Asn1Core,
501 UINT32_MAX,
502 ASN1_TAGCLASS_PRIVATE | ASN1_TAGFLAG_CONSTRUCTED,
503 NULL,
504 RTASN1CORE_F_DUMMY);
505}
506
507
508/*
509 * ASN.1 SEQUENCE OF object.
510 */
511
512RTDECL(int) RTAsn1SeqOfCore_Init(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable)
513{
514 return RTAsn1Core_InitEx(&pThis->Asn1Core,
515 ASN1_TAG_SEQUENCE,
516 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED,
517 pVtable,
518 RTASN1CORE_F_PRESENT);
519}
520
521
522RTDECL(int) RTAsn1SeqOfCore_Clone(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQOFCORE pSrc)
523{
524 AssertReturn(pSrc->Asn1Core.pOps == pVtable, VERR_ASN1_INTERNAL_ERROR_5);
525 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
526}
527
528
529/*
530 * ASN.1 SET OF object.
531 */
532
533RTDECL(int) RTAsn1SetOfCore_Init(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable)
534{
535 return RTAsn1Core_InitEx(&pThis->Asn1Core,
536 ASN1_TAG_SET,
537 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED,
538 pVtable,
539 RTASN1CORE_F_PRESENT);
540}
541
542
543RTDECL(int) RTAsn1SetOfCore_Clone(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETOFCORE pSrc)
544{
545 AssertReturn(pSrc->Asn1Core.pOps == pVtable, VERR_ASN1_INTERNAL_ERROR_5);
546 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
547}
548
549
550/*
551 * ASN.1 SEQUENCE object.
552 */
553
554RTDECL(int) RTAsn1SequenceCore_Init(PRTASN1SEQUENCECORE pThis, PCRTASN1COREVTABLE pVtable)
555{
556 return RTAsn1Core_InitEx(&pThis->Asn1Core,
557 ASN1_TAG_SEQUENCE,
558 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED,
559 pVtable,
560 RTASN1CORE_F_PRESENT);
561}
562
563
564RTDECL(int) RTAsn1SequenceCore_Clone(PRTASN1SEQUENCECORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQUENCECORE pSrc)
565{
566 AssertReturn(pSrc->Asn1Core.pOps == pVtable, VERR_ASN1_INTERNAL_ERROR_5);
567 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
568}
569
570
571/*
572 * ASN.1 SEQUENCE object - only used by SPC, so probably doing something wrong there.
573 */
574
575RTDECL(int) RTAsn1SetCore_Init(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable)
576{
577 return RTAsn1Core_InitEx(&pThis->Asn1Core,
578 ASN1_TAG_SET,
579 ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED,
580 pVtable,
581 RTASN1CORE_F_PRESENT);
582}
583
584
585RTDECL(int) RTAsn1SetCore_Clone(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETCORE pSrc)
586{
587 AssertReturn(pSrc->Asn1Core.pOps == pVtable, VERR_ASN1_INTERNAL_ERROR_5);
588 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
589}
590
591
592/*
593 * ASN.1 Context Tag object.
594 */
595
596RTDECL(int) RTAsn1ContextTagN_Init(PRTASN1CONTEXTTAG pThis, uint32_t uTag, PCRTASN1COREVTABLE pVtable)
597{
598 return RTAsn1Core_InitEx(&pThis->Asn1Core,
599 uTag,
600 ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED,
601 pVtable,
602 RTASN1CORE_F_PRESENT);
603}
604
605
606RTDECL(int) RTAsn1ContextTagN_Clone(PRTASN1CONTEXTTAG pThis, PCRTASN1CONTEXTTAG pSrc, uint32_t uTag)
607{
608 Assert(pSrc->Asn1Core.uTag == uTag || !RTASN1CORE_IS_PRESENT(&pSrc->Asn1Core)); RT_NOREF_PV(uTag);
609 return RTAsn1Core_CloneNoContent(&pThis->Asn1Core, &pSrc->Asn1Core);
610}
611
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