VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/asn1/asn1-safer-allocator.cpp

Last change on this file was 98103, checked in by vboxsync, 17 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: 7.6 KB
Line 
1/* $Id: asn1-safer-allocator.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - ASN.1, Safer Allocator, for sensitive data.
4 */
5
6/*
7 * Copyright (C) 2006-2023 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/memsafer.h>
45#include <iprt/errcore.h>
46#include <iprt/string.h>
47
48
49/**
50 * Aligns allocation sizes a little.
51 *
52 * @returns Aligned size.
53 * @param cb Requested size.
54 */
55static size_t rtAsn1SaferAllocator_AlignSize(size_t cb)
56{
57 if (cb >= 64)
58 return RT_ALIGN_Z(cb, 64);
59 if (cb >= 32)
60 return RT_ALIGN_Z(cb, 32);
61 if (cb >= 16)
62 return RT_ALIGN_Z(cb, 16);
63 return cb;
64}
65
66
67/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnFree} */
68static DECLCALLBACK(void) rtAsn1SaferAllocator_Free(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation, void *pv)
69{
70 RT_NOREF_PV(pThis);
71 RTMemSaferFree(pv, pAllocation->cbAllocated);
72 pAllocation->cbAllocated = 0;
73}
74
75
76/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnAlloc} */
77static DECLCALLBACK(int) rtAsn1SaferAllocator_Alloc(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation,
78 void **ppv, size_t cb)
79{
80 size_t cbAlloc = rtAsn1SaferAllocator_AlignSize(cb);
81 void *pv = RTMemSaferAllocZ(cbAlloc);
82 if (pv)
83 {
84 *ppv = pv;
85 pAllocation->cbAllocated = (uint32_t)cbAlloc;
86 return VINF_SUCCESS;
87 }
88 RT_NOREF_PV(pThis);
89 return VERR_NO_MEMORY;
90}
91
92
93/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnRealloc} */
94static DECLCALLBACK(int) rtAsn1SaferAllocator_Realloc(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation,
95 void *pvOld, void **ppvNew, size_t cbNew)
96{
97 Assert(pvOld);
98 Assert(cbNew);
99 size_t cbAlloc = rtAsn1SaferAllocator_AlignSize(cbNew);
100 void *pv = RTMemSaferReallocZ(pAllocation->cbAllocated, pvOld, cbAlloc);
101 if (pv)
102 {
103 *ppvNew = pv;
104 pAllocation->cbAllocated = (uint32_t)cbAlloc;
105 return VINF_SUCCESS;
106 }
107 RT_NOREF_PV(pThis);
108 return VERR_NO_MEMORY;
109}
110
111
112/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnFreeArray} */
113static DECLCALLBACK(void) rtAsn1SaferAllocator_FreeArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
114 void **papvArray)
115{
116 RT_NOREF_PV(pThis);
117 Assert(papvArray);
118 Assert(pAllocation->cbEntry);
119
120 uint32_t i = pAllocation->cEntriesAllocated;
121 while (i-- > 0)
122 RTMemSaferFree(papvArray[i], pAllocation->cbEntry);
123 RTMemFree(papvArray);
124
125 pAllocation->cEntriesAllocated = 0;
126 pAllocation->cPointersAllocated = 0;
127}
128
129
130/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnGrowArray} */
131static DECLCALLBACK(int) rtAsn1SaferAllocator_GrowArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
132 void ***ppapvArray, uint32_t cMinEntries)
133{
134 RT_NOREF_PV(pThis);
135
136 /*
137 * Resize the pointer array. We do chunks of 64 bytes for now.
138 */
139 void **papvArray = *ppapvArray;
140 uint32_t cPointers = RT_ALIGN_32(cMinEntries, 64 / sizeof(void *));
141 if (cPointers > pAllocation->cPointersAllocated)
142 {
143 void *pvPointers = RTMemRealloc(papvArray, cPointers * sizeof(void *));
144 if (pvPointers)
145 { /* likely */ }
146 else if (cMinEntries > pAllocation->cPointersAllocated)
147 {
148 cPointers = cMinEntries;
149 pvPointers = RTMemRealloc(*ppapvArray, cPointers * sizeof(void *));
150 if (!pvPointers)
151 return VERR_NO_MEMORY;
152 }
153 else
154 {
155 cPointers = pAllocation->cPointersAllocated;
156 pvPointers = papvArray;
157 }
158
159 *ppapvArray = papvArray = (void **)pvPointers;
160 RT_BZERO(&papvArray[pAllocation->cPointersAllocated], (cPointers - pAllocation->cPointersAllocated) * sizeof(void *));
161 pAllocation->cPointersAllocated = cPointers;
162 }
163
164 /*
165 * Add more entries. Do multiple as the array grows.
166 *
167 * Note! We could possibly optimize this by allocating slabs of entries and
168 * slice them up. However, keep things as simple as possible for now.
169 */
170 uint32_t cEntries = cMinEntries;
171 if (cEntries > 2)
172 {
173 if (cEntries > 8)
174 cEntries = RT_ALIGN_32(cEntries, 4);
175 else
176 cEntries = RT_ALIGN_32(cEntries, 2);
177 cEntries = RT_MIN(cEntries, cPointers);
178 Assert(cEntries >= cMinEntries);
179 }
180 Assert(cEntries <= pAllocation->cPointersAllocated);
181
182 while (pAllocation->cEntriesAllocated < cEntries)
183 {
184 void *pv;
185 papvArray[pAllocation->cEntriesAllocated] = pv = RTMemSaferAllocZ(pAllocation->cbEntry);
186 if (pv)
187 pAllocation->cEntriesAllocated++;
188 else if (pAllocation->cEntriesAllocated >= cMinEntries)
189 break;
190 else
191 return VERR_NO_MEMORY;
192 }
193
194 return VINF_SUCCESS;
195}
196
197
198/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnShrinkArray} */
199static DECLCALLBACK(void) rtAsn1SaferAllocator_ShrinkArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
200 void ***ppapvArray, uint32_t cNew, uint32_t cCurrent)
201{
202 RT_NOREF_PV(pThis);
203
204 /*
205 * For now we only zero the entries being removed.
206 */
207 void **papvArray = *ppapvArray;
208 while (cNew < cCurrent)
209 {
210 RTMemWipeThoroughly(papvArray[cNew], pAllocation->cbEntry, 3);
211 RT_BZERO(papvArray[cNew], pAllocation->cbEntry);
212 cNew++;
213 }
214}
215
216
217
218/** The Safer ASN.1 allocator. */
219#if 1 || !defined(IN_RING3) || defined(DOXYGEN_RUNNING)
220RT_DECL_DATA_CONST(RTASN1ALLOCATORVTABLE const) g_RTAsn1SaferAllocator =
221#else
222RT_DECL_DATA_CONST(RTASN1ALLOCATORVTABLE const) g_RTAsn1SaferAllocatorDisabled =
223#endif
224{
225 rtAsn1SaferAllocator_Free,
226 rtAsn1SaferAllocator_Alloc,
227 rtAsn1SaferAllocator_Realloc,
228 rtAsn1SaferAllocator_FreeArray,
229 rtAsn1SaferAllocator_GrowArray,
230 rtAsn1SaferAllocator_ShrinkArray
231};
232
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use