VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/SecretKeyStore.cpp@ 108014

Last change on this file since 108014 was 107489, checked in by vboxsync, 7 weeks ago

Main/src-all/SecretKeyStore.cpp: Throw an error if RTMemSaferScramble() should ever fail (not possible right now), bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.7 KB
Line 
1/* $Id: SecretKeyStore.cpp 107489 2025-01-08 10:07:34Z vboxsync $ */
2/** @file
3 * Main - Secret key interface.
4 */
5
6/*
7 * Copyright (C) 2015-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 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include <VBox/err.h>
29#include <VBox/log.h>
30#include <iprt/assert.h>
31#include <iprt/asm.h>
32#include <iprt/memsafer.h>
33
34#include "SecretKeyStore.h"
35
36SecretKey::SecretKey(const uint8_t *pbKey, size_t cbKey, bool fKeyBufNonPageable)
37{
38 m_cRefs = 0;
39 m_fRemoveOnSuspend = false;
40 m_cUsers = 0;
41 m_cbKey = cbKey;
42
43 int vrc = RTMemSaferAllocZEx((void **)&this->m_pbKey, cbKey,
44 fKeyBufNonPageable ? RTMEMSAFER_F_REQUIRE_NOT_PAGABLE : 0);
45 if (RT_SUCCESS(vrc))
46 {
47 memcpy(this->m_pbKey, pbKey, cbKey);
48
49 /* Scramble content to make retrieving the key more difficult. */
50 vrc = RTMemSaferScramble(this->m_pbKey, cbKey);
51 }
52
53 if (RT_FAILURE(vrc))
54 throw vrc;
55}
56
57SecretKey::~SecretKey()
58{
59 Assert(!m_cRefs);
60
61 RTMemSaferFree(m_pbKey, m_cbKey);
62 m_cRefs = 0;
63 m_pbKey = NULL;
64 m_cbKey = 0;
65 m_fRemoveOnSuspend = false;
66 m_cUsers = 0;
67}
68
69uint32_t SecretKey::retain()
70{
71 uint32_t cRefs = ASMAtomicIncU32(&m_cRefs);
72 if (cRefs == 1)
73 {
74 int vrc = RTMemSaferUnscramble(m_pbKey, m_cbKey);
75 AssertRC(vrc);
76 }
77
78 return cRefs;
79}
80
81uint32_t SecretKey::release()
82{
83 uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
84 if (!cRefs)
85 {
86 int vrc = RTMemSaferScramble(m_pbKey, m_cbKey);
87 AssertRC(vrc);
88 }
89
90 return cRefs;
91}
92
93uint32_t SecretKey::refCount()
94{
95 return m_cRefs;
96}
97
98int SecretKey::setUsers(uint32_t cUsers)
99{
100 m_cUsers = cUsers;
101 return VINF_SUCCESS;
102}
103
104uint32_t SecretKey::getUsers()
105{
106 return m_cUsers;
107}
108
109int SecretKey::setRemoveOnSuspend(bool fRemoveOnSuspend)
110{
111 m_fRemoveOnSuspend = fRemoveOnSuspend;
112 return VINF_SUCCESS;
113}
114
115bool SecretKey::getRemoveOnSuspend()
116{
117 return m_fRemoveOnSuspend;
118}
119
120const void *SecretKey::getKeyBuffer()
121{
122 AssertReturn(m_cRefs > 0, NULL);
123 return m_pbKey;
124}
125
126size_t SecretKey::getKeySize()
127{
128 return m_cbKey;
129}
130
131SecretKeyStore::SecretKeyStore(bool fKeyBufNonPageable)
132{
133 m_fKeyBufNonPageable = fKeyBufNonPageable;
134}
135
136SecretKeyStore::~SecretKeyStore()
137{
138 int vrc = deleteAllSecretKeys(false /* fSuspend */, true /* fForce */);
139 AssertRC(vrc);
140}
141
142int SecretKeyStore::addSecretKey(const com::Utf8Str &strKeyId, const uint8_t *pbKey, size_t cbKey)
143{
144 /* Check that the ID is not existing already. */
145 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
146 if (it != m_mapSecretKeys.end())
147 return VERR_ALREADY_EXISTS;
148
149 SecretKey *pKey = NULL;
150 try
151 {
152 pKey = new SecretKey(pbKey, cbKey, m_fKeyBufNonPageable);
153
154 m_mapSecretKeys.insert(std::make_pair(strKeyId, pKey));
155 }
156 catch (int vrc)
157 {
158 return vrc;
159 }
160 catch (std::bad_alloc &)
161 {
162 if (pKey)
163 delete pKey;
164 return VERR_NO_MEMORY;
165 }
166
167 return VINF_SUCCESS;
168}
169
170int SecretKeyStore::deleteSecretKey(const com::Utf8Str &strKeyId)
171{
172 SecretKeyMap::iterator it = m_mapSecretKeys.find(strKeyId);
173 if (it == m_mapSecretKeys.end())
174 return VERR_NOT_FOUND;
175
176 SecretKey *pKey = it->second;
177 if (pKey->refCount() != 0)
178 return VERR_RESOURCE_IN_USE;
179
180 m_mapSecretKeys.erase(it);
181 delete pKey;
182
183 return VINF_SUCCESS;
184}
185
186int SecretKeyStore::retainSecretKey(const com::Utf8Str &strKeyId, SecretKey **ppKey)
187{
188 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
189 if (it == m_mapSecretKeys.end())
190 return VERR_NOT_FOUND;
191
192 SecretKey *pKey = it->second;
193 pKey->retain();
194
195 *ppKey = pKey;
196
197 return VINF_SUCCESS;
198}
199
200int SecretKeyStore::releaseSecretKey(const com::Utf8Str &strKeyId)
201{
202 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
203 if (it == m_mapSecretKeys.end())
204 return VERR_NOT_FOUND;
205
206 SecretKey *pKey = it->second;
207 pKey->release();
208 return VINF_SUCCESS;
209}
210
211int SecretKeyStore::deleteAllSecretKeys(bool fSuspend, bool fForce)
212{
213 /* First check whether a key is still in use. */
214 if (!fForce)
215 {
216 for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
217 it != m_mapSecretKeys.end();
218 ++it)
219 {
220 SecretKey *pKey = it->second;
221 if ( pKey->refCount()
222 && ( ( pKey->getRemoveOnSuspend()
223 && fSuspend)
224 || !fSuspend))
225 return VERR_RESOURCE_IN_USE;
226 }
227 }
228
229 SecretKeyMap::iterator it = m_mapSecretKeys.begin();
230 while (it != m_mapSecretKeys.end())
231 {
232 SecretKey *pKey = it->second;
233 if ( pKey->getRemoveOnSuspend()
234 || !fSuspend)
235 {
236 AssertMsg(!pKey->refCount(), ("No one should access the stored key at this point anymore!\n"));
237 delete pKey;
238 SecretKeyMap::iterator itNext = it;
239 ++itNext;
240 m_mapSecretKeys.erase(it);
241 it = itNext;
242 }
243 else
244 ++it;
245 }
246
247 return VINF_SUCCESS;
248}
249
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