VirtualBox

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

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

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

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.1 KB
Line 
1/* $Id: asn1-basics.cpp 64883 2016-12-15 15:26:20Z vboxsync $ */
2/** @file
3 * IPRT - ASN.1, Basic Operations.
4 */
5
6/*
7 * Copyright (C) 2006-2016 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_OFFSETOF(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_OFFSETOF(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