VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 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: 5.7 KB
Line 
1/* $Id: SecretKeyStore.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * Main - Secret key interface.
4 */
5
6/*
7 * Copyright (C) 2015-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 * 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 else
53 throw vrc;
54}
55
56SecretKey::~SecretKey()
57{
58 Assert(!m_cRefs);
59
60 RTMemSaferFree(m_pbKey, m_cbKey);
61 m_cRefs = 0;
62 m_pbKey = NULL;
63 m_cbKey = 0;
64 m_fRemoveOnSuspend = false;
65 m_cUsers = 0;
66}
67
68uint32_t SecretKey::retain()
69{
70 uint32_t cRefs = ASMAtomicIncU32(&m_cRefs);
71 if (cRefs == 1)
72 {
73 int vrc = RTMemSaferUnscramble(m_pbKey, m_cbKey);
74 AssertRC(vrc);
75 }
76
77 return cRefs;
78}
79
80uint32_t SecretKey::release()
81{
82 uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
83 if (!cRefs)
84 {
85 int vrc = RTMemSaferScramble(m_pbKey, m_cbKey);
86 AssertRC(vrc);
87 }
88
89 return cRefs;
90}
91
92uint32_t SecretKey::refCount()
93{
94 return m_cRefs;
95}
96
97int SecretKey::setUsers(uint32_t cUsers)
98{
99 m_cUsers = cUsers;
100 return VINF_SUCCESS;
101}
102
103uint32_t SecretKey::getUsers()
104{
105 return m_cUsers;
106}
107
108int SecretKey::setRemoveOnSuspend(bool fRemoveOnSuspend)
109{
110 m_fRemoveOnSuspend = fRemoveOnSuspend;
111 return VINF_SUCCESS;
112}
113
114bool SecretKey::getRemoveOnSuspend()
115{
116 return m_fRemoveOnSuspend;
117}
118
119const void *SecretKey::getKeyBuffer()
120{
121 AssertReturn(m_cRefs > 0, NULL);
122 return m_pbKey;
123}
124
125size_t SecretKey::getKeySize()
126{
127 return m_cbKey;
128}
129
130SecretKeyStore::SecretKeyStore(bool fKeyBufNonPageable)
131{
132 m_fKeyBufNonPageable = fKeyBufNonPageable;
133}
134
135SecretKeyStore::~SecretKeyStore()
136{
137 int vrc = deleteAllSecretKeys(false /* fSuspend */, true /* fForce */);
138 AssertRC(vrc);
139}
140
141int SecretKeyStore::addSecretKey(const com::Utf8Str &strKeyId, const uint8_t *pbKey, size_t cbKey)
142{
143 /* Check that the ID is not existing already. */
144 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
145 if (it != m_mapSecretKeys.end())
146 return VERR_ALREADY_EXISTS;
147
148 SecretKey *pKey = NULL;
149 try
150 {
151 pKey = new SecretKey(pbKey, cbKey, m_fKeyBufNonPageable);
152
153 m_mapSecretKeys.insert(std::make_pair(strKeyId, pKey));
154 }
155 catch (int vrc)
156 {
157 return vrc;
158 }
159 catch (std::bad_alloc &)
160 {
161 if (pKey)
162 delete pKey;
163 return VERR_NO_MEMORY;
164 }
165
166 return VINF_SUCCESS;
167}
168
169int SecretKeyStore::deleteSecretKey(const com::Utf8Str &strKeyId)
170{
171 SecretKeyMap::iterator it = m_mapSecretKeys.find(strKeyId);
172 if (it == m_mapSecretKeys.end())
173 return VERR_NOT_FOUND;
174
175 SecretKey *pKey = it->second;
176 if (pKey->refCount() != 0)
177 return VERR_RESOURCE_IN_USE;
178
179 m_mapSecretKeys.erase(it);
180 delete pKey;
181
182 return VINF_SUCCESS;
183}
184
185int SecretKeyStore::retainSecretKey(const com::Utf8Str &strKeyId, SecretKey **ppKey)
186{
187 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
188 if (it == m_mapSecretKeys.end())
189 return VERR_NOT_FOUND;
190
191 SecretKey *pKey = it->second;
192 pKey->retain();
193
194 *ppKey = pKey;
195
196 return VINF_SUCCESS;
197}
198
199int SecretKeyStore::releaseSecretKey(const com::Utf8Str &strKeyId)
200{
201 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
202 if (it == m_mapSecretKeys.end())
203 return VERR_NOT_FOUND;
204
205 SecretKey *pKey = it->second;
206 pKey->release();
207 return VINF_SUCCESS;
208}
209
210int SecretKeyStore::deleteAllSecretKeys(bool fSuspend, bool fForce)
211{
212 /* First check whether a key is still in use. */
213 if (!fForce)
214 {
215 for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
216 it != m_mapSecretKeys.end();
217 ++it)
218 {
219 SecretKey *pKey = it->second;
220 if ( pKey->refCount()
221 && ( ( pKey->getRemoveOnSuspend()
222 && fSuspend)
223 || !fSuspend))
224 return VERR_RESOURCE_IN_USE;
225 }
226 }
227
228 SecretKeyMap::iterator it = m_mapSecretKeys.begin();
229 while (it != m_mapSecretKeys.end())
230 {
231 SecretKey *pKey = it->second;
232 if ( pKey->getRemoveOnSuspend()
233 || !fSuspend)
234 {
235 AssertMsg(!pKey->refCount(), ("No one should access the stored key at this point anymore!\n"));
236 delete pKey;
237 SecretKeyMap::iterator itNext = it;
238 ++itNext;
239 m_mapSecretKeys.erase(it);
240 it = itNext;
241 }
242 else
243 ++it;
244 }
245
246 return VINF_SUCCESS;
247}
248
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use