VirtualBox

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

Last change on this file since 95596 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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