VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/asn1/asn1-ut-core.cpp@ 83743

Last change on this file since 83743 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/* $Id: asn1-ut-core.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * IPRT - ASN.1, Generic Core Type.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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 * ASN.1 Core - Special methods (for all applications of RTASN1CORE).
46 */
47
48RTDECL(int) RTAsn1Core_SetTagAndFlags(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass)
49{
50 if (!(pAsn1Core->fFlags & RTASN1CORE_F_TAG_IMPLICIT))
51 {
52 pAsn1Core->fRealClass = pAsn1Core->fClass;
53 pAsn1Core->uRealTag = pAsn1Core->uTag;
54 Assert(pAsn1Core->uRealTag == pAsn1Core->uTag);
55 pAsn1Core->fFlags |= RTASN1CORE_F_TAG_IMPLICIT;
56 }
57 pAsn1Core->uTag = uTag;
58 pAsn1Core->fClass = fClass;
59 return VINF_SUCCESS;
60}
61
62
63RTDECL(int) RTAsn1Core_ChangeTag(PRTASN1CORE pAsn1Core, uint32_t uTag)
64{
65 if (!(pAsn1Core->fFlags & RTASN1CORE_F_TAG_IMPLICIT))
66 pAsn1Core->uTag = uTag;
67 pAsn1Core->uRealTag = uTag;
68 return VINF_SUCCESS;
69}
70
71
72RTDECL(void) RTAsn1Core_ResetImplict(PRTASN1CORE pThis)
73{
74 AssertPtr(pThis);
75 if (pThis->fFlags & RTASN1CORE_F_TAG_IMPLICIT)
76 {
77 pThis->fFlags &= ~RTASN1CORE_F_TAG_IMPLICIT;
78 pThis->uTag = pThis->uRealTag;
79 pThis->fClass = pThis->fRealClass;
80 }
81}
82
83
84RTDECL(int) RTAsn1Core_InitEx(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass, PCRTASN1COREVTABLE pOps, uint32_t fFlags)
85{
86 pAsn1Core->uTag = uTag;
87 pAsn1Core->fClass = fClass;
88 pAsn1Core->uRealTag = uTag;
89 pAsn1Core->fRealClass = fClass;
90 pAsn1Core->cbHdr = 0;
91 pAsn1Core->cb = 0;
92 pAsn1Core->fFlags = fFlags;
93 pAsn1Core->uData.pv = NULL;
94 pAsn1Core->pOps = pOps;
95 return VINF_SUCCESS;
96}
97
98
99RTDECL(int) RTAsn1Core_InitDefault(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass)
100{
101 return RTAsn1Core_InitEx(pAsn1Core, uTag, fClass, NULL, RTASN1CORE_F_DEFAULT);
102}
103
104
105static int rtAsn1Core_CloneEx(PRTASN1CORE pThis, PCRTASN1CORE pSrc, PCRTASN1ALLOCATORVTABLE pAllocator, bool fCopyContent)
106{
107 Assert(RTASN1CORE_IS_PRESENT(pSrc));
108 pThis->uTag = pSrc->uTag;
109 pThis->fClass = pSrc->fClass;
110 pThis->uRealTag = pSrc->uRealTag;
111 pThis->fRealClass = pSrc->fRealClass;
112 pThis->cbHdr = pSrc->cbHdr;
113 pThis->fFlags = pSrc->fFlags & ~(RTASN1CORE_F_ALLOCATED_CONTENT | RTASN1CORE_F_DECODED_CONTENT);
114 pThis->pOps = pSrc->pOps;
115 pThis->cb = 0;
116 pThis->uData.pv = NULL;
117 if (pSrc->cb)
118 {
119 if (!fCopyContent)
120 pThis->cb = pSrc->cb;
121 else
122 {
123 int rc = RTAsn1ContentDup(pThis, pSrc->uData.pv, pSrc->cb, pAllocator);
124 if (RT_FAILURE(rc))
125 {
126 RT_ZERO(*pThis);
127 return rc;
128 }
129 Assert(pThis->cb == pSrc->cb);
130 AssertPtr(pThis->uData.pv);
131 }
132 }
133 return VINF_SUCCESS;
134}
135
136
137RTDECL(int) RTAsn1Core_CloneContent(PRTASN1CORE pThis, PCRTASN1CORE pSrc, PCRTASN1ALLOCATORVTABLE pAllocator)
138{
139 return rtAsn1Core_CloneEx(pThis, pSrc, pAllocator, true /*fConpyContent*/);
140}
141
142
143RTDECL(int) RTAsn1Core_CloneNoContent(PRTASN1CORE pThis, PCRTASN1CORE pSrc)
144{
145 return rtAsn1Core_CloneEx(pThis, pSrc, NULL, false /*fConpyContent*/);
146}
147
148
149RTDECL(int) RTAsn1Core_CompareEx(PCRTASN1CORE pLeft, PCRTASN1CORE pRight, bool fIgnoreTagAndClass)
150{
151 int iDiff;
152 if (RTASN1CORE_IS_PRESENT(pLeft))
153 {
154 if (RTASN1CORE_IS_PRESENT(pRight))
155 {
156 iDiff = memcmp(pLeft->uData.pv, pRight->uData.pv, RT_MIN(pLeft->cb, pRight->cb));
157 if (!iDiff)
158 {
159 if (pLeft->cb != pRight->cb)
160 iDiff = pLeft->cb < pRight->cb ? -1 : 1;
161 else if (!fIgnoreTagAndClass)
162 {
163 if (pLeft->uTag != pRight->uTag)
164 iDiff = pLeft->uTag < pRight->uTag ? -1 : 1;
165 else if (pLeft->fClass != pRight->fClass)
166 iDiff = pLeft->fClass < pRight->fClass ? -1 : 1;
167 }
168 }
169 else
170 iDiff = iDiff < 0 ? -1 : 1;
171 }
172 else
173 iDiff = -1;
174 }
175 else
176 iDiff = 0 - (int)RTASN1CORE_IS_PRESENT(pRight);
177 return iDiff;
178}
179
180
181/**
182 * @interface_method_impl{RTASN1COREVTABLE,pfnEncodePrep,
183 * This is for not dropping the unparsed content of a 'core' structure when
184 * re-encoding it. }
185 */
186static DECLCALLBACK(int) rtAsn1Core_EncodePrep(PRTASN1CORE pThisCore, uint32_t fFlags, PRTERRINFO pErrInfo)
187{
188 /* We don't update anything here. */
189 RT_NOREF(pThisCore, fFlags, pErrInfo);
190 return VINF_SUCCESS;
191}
192
193
194/**
195 * @interface_method_impl{RTASN1COREVTABLE,pfnEncodeWrite,
196 * This is for not dropping the unparsed content of a 'core' structure when
197 * re-encoding it. }
198 */
199static DECLCALLBACK(int) rtAsn1Core_EncodeWrite(PRTASN1CORE pThisCore, uint32_t fFlags, PFNRTASN1ENCODEWRITER pfnWriter,
200 void *pvUser, PRTERRINFO pErrInfo)
201{
202 int rc = RTAsn1EncodeWriteHeader(pThisCore, fFlags, pfnWriter, pvUser, pErrInfo);
203 if ( RT_SUCCESS(rc)
204 && rc != VINF_ASN1_NOT_ENCODED)
205 {
206 Assert(!RTASN1CORE_IS_DUMMY(pThisCore));
207 if (pThisCore->cb)
208 {
209 AssertPtrReturn(pThisCore->uData.pv,
210 RTErrInfoSetF(pErrInfo, VERR_ASN1_INVALID_DATA_POINTER,
211 "Invalid uData pointer %p for lone ASN.1 core with %#x bytes of content",
212 pThisCore->uData.pv, pThisCore->cb));
213 rc = pfnWriter(pThisCore->uData.pv, pThisCore->cb, pvUser, pErrInfo);
214 }
215 }
216 return rc;
217}
218
219
220
221/*
222 * ASN.1 Core - Standard Methods.
223 *
224 * @note Children of the ASN.1 Core doesn't normally call these, they are for
225 * when RTASN1CORE is used as a member type.
226 */
227
228RT_DECL_DATA_CONST(RTASN1COREVTABLE const) g_RTAsn1Core_Vtable =
229{
230 "RTAsn1Core",
231 sizeof(RTASN1CORE),
232 UINT8_MAX,
233 UINT8_MAX,
234 0,
235 RTAsn1Core_Delete,
236 RTAsn1Core_Enum,
237 (PFNRTASN1COREVTCLONE)RTAsn1Core_Clone,
238 (PFNRTASN1COREVTCOMPARE)RTAsn1Core_Compare,
239 (PFNRTASN1COREVTCHECKSANITY)RTAsn1Core_CheckSanity,
240 rtAsn1Core_EncodePrep,
241 rtAsn1Core_EncodeWrite
242};
243
244
245RTDECL(int) RTAsn1Core_Init(PRTASN1CORE pThis, PCRTASN1ALLOCATORVTABLE pAllocator)
246{
247 RT_NOREF_PV(pAllocator);
248 return RTAsn1Core_InitEx(pThis, 0, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE,
249 &g_RTAsn1Core_Vtable, RTASN1CORE_F_PRESENT);
250}
251
252
253RTDECL(int) RTAsn1Core_Clone(PRTASN1CORE pThis, PCRTASN1CORE pSrc, PCRTASN1ALLOCATORVTABLE pAllocator)
254{
255 int rc;
256 RT_ZERO(*pThis);
257 if (RTASN1CORE_IS_PRESENT(pSrc))
258 {
259 Assert(pSrc->pOps == &g_RTAsn1Core_Vtable);
260
261 rc = RTAsn1Core_CloneContent(pThis, pSrc, pAllocator);
262 }
263 else
264 rc = VINF_SUCCESS;
265 return rc;
266}
267
268
269RTDECL(void) RTAsn1Core_Delete(PRTASN1CORE pThis)
270{
271 if (pThis && RTASN1CORE_IS_PRESENT(pThis))
272 {
273 Assert(pThis->pOps == &g_RTAsn1Core_Vtable);
274
275 RTAsn1ContentFree(pThis);
276 RT_ZERO(*pThis);
277 }
278}
279
280
281RTDECL(int) RTAsn1Core_Enum(PRTASN1CORE pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser)
282{
283 /* We have no children to enumerate. */
284 Assert(pThis && (!RTASN1CORE_IS_PRESENT(pThis) || pThis->pOps == &g_RTAsn1Core_Vtable));
285 NOREF(pThis);
286 NOREF(pfnCallback);
287 NOREF(uDepth);
288 NOREF(pvUser);
289 return VINF_SUCCESS;
290}
291
292
293RTDECL(int) RTAsn1Core_Compare(PCRTASN1CORE pLeft, PCRTASN1CORE pRight)
294{
295 Assert(pLeft && (!RTASN1CORE_IS_PRESENT(pLeft) || pLeft->pOps == &g_RTAsn1Core_Vtable));
296 Assert(pRight && (!RTASN1CORE_IS_PRESENT(pRight) || pRight->pOps == &g_RTAsn1Core_Vtable));
297
298 return RTAsn1Core_CompareEx(pLeft, pRight, false /*fIgnoreTagAndClass*/);
299}
300
301
302RTDECL(int) RTAsn1Core_CheckSanity(PCRTASN1CORE pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
303{
304 RT_NOREF_PV(fFlags);
305
306 /* We can only check that it's present. */
307 if (!RTAsn1Core_IsPresent(pThis))
308 return RTErrInfoSetF(pErrInfo, VERR_ASN1_NOT_PRESENT, "%s: Missing (RTASN1CORE).", pszErrorTag);
309 return VINF_SUCCESS;
310}
311
312
313/*
314 * Generate code for the associated collection types.
315 */
316#define RTASN1TMPL_TEMPLATE_FILE "../common/asn1/asn1-ut-core-template.h"
317#include <iprt/asn1-generator-internal-header.h>
318#include <iprt/asn1-generator-core.h>
319#include <iprt/asn1-generator-init.h>
320#include <iprt/asn1-generator-sanity.h>
321
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