VirtualBox

source: vbox/trunk/src/VBox/ImageMounter/vboximg-mount/vboximgCrypto.cpp

最後變更 在這個檔案是 107506,由 vboxsync 提交於 2 月 前

ImageMounter/vboximg-mount: Some parfait warning fixes, bugref:3409

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 12.2 KB
 
1/* $Id: vboximgCrypto.cpp 107506 2025-01-08 13:14:48Z vboxsync $ $Revision: 107506 $ */
2
3/** @file
4 * vboximgCypto.cpp - Disk Image Flattening FUSE Program.
5 */
6
7/*
8 * Copyright (C) 2009-2024 Oracle and/or its affiliates.
9 *
10 * This file is part of VirtualBox base platform packages, as
11 * available from https://www.alldomusa.eu.org.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, in version 3 of the
16 * License.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <https://www.gnu.org/licenses>.
25 *
26 * SPDX-License-Identifier: GPL-3.0-only
27 */
28
29#include <iprt/cdefs.h>
30#include <VBox/err.h>
31#include <VBox/settings.h>
32#include <VBox/vd.h>
33#include "vboximgCrypto.h"
34#include <VBox/log.h>
35#include <iprt/assert.h>
36#include <iprt/asm.h>
37#include <iprt/memsafer.h>
38
39/*
40 * Apparently there is a more COM:: oriented (but less efficient?) approach to dealing
41 * with the keystore and disk encryption, which will need to be investigated. Keeping
42 * all this duplicated code in a separate file until the ideal approach is determined.
43 */
44SecretKey::SecretKey(const uint8_t *pbKey, size_t cbKey, bool fKeyBufNonPageable)
45{
46 m_cRefs = 0;
47 m_fRemoveOnSuspend = false;
48 m_cUsers = 0;
49 m_cbKey = cbKey;
50
51 int rc = RTMemSaferAllocZEx((void **)&this->m_pbKey, cbKey,
52 fKeyBufNonPageable ? RTMEMSAFER_F_REQUIRE_NOT_PAGABLE : 0);
53 if (RT_SUCCESS(rc))
54 {
55 memcpy(this->m_pbKey, pbKey, cbKey);
56
57 /* Scramble content to make retrieving the key more difficult. */
58 rc = RTMemSaferScramble(this->m_pbKey, cbKey);
59 }
60
61 if (RT_FAILURE(rc))
62 throw rc;
63}
64
65SecretKey::~SecretKey()
66{
67 Assert(!m_cRefs);
68
69 RTMemSaferFree(m_pbKey, m_cbKey);
70 m_cRefs = 0;
71 m_pbKey = NULL;
72 m_cbKey = 0;
73 m_fRemoveOnSuspend = false;
74 m_cUsers = 0;
75}
76
77uint32_t SecretKey::retain()
78{
79 uint32_t cRefs = ASMAtomicIncU32(&m_cRefs);
80 if (cRefs == 1)
81 {
82 int rc = RTMemSaferUnscramble(m_pbKey, m_cbKey);
83 AssertRC(rc);
84 }
85
86 return cRefs;
87}
88
89uint32_t SecretKey::release()
90{
91 uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
92 if (!cRefs)
93 {
94 int rc = RTMemSaferScramble(m_pbKey, m_cbKey);
95 AssertRC(rc);
96 }
97
98 return cRefs;
99}
100
101uint32_t SecretKey::refCount()
102{
103 return m_cRefs;
104}
105
106int SecretKey::setUsers(uint32_t cUsers)
107{
108 m_cUsers = cUsers;
109 return VINF_SUCCESS;
110}
111
112uint32_t SecretKey::getUsers()
113{
114 return m_cUsers;
115}
116
117int SecretKey::setRemoveOnSuspend(bool fRemoveOnSuspend)
118{
119 m_fRemoveOnSuspend = fRemoveOnSuspend;
120 return VINF_SUCCESS;
121}
122
123bool SecretKey::getRemoveOnSuspend()
124{
125 return m_fRemoveOnSuspend;
126}
127
128const void *SecretKey::getKeyBuffer()
129{
130 AssertReturn(m_cRefs > 0, NULL);
131 return m_pbKey;
132}
133
134size_t SecretKey::getKeySize()
135{
136 return m_cbKey;
137}
138
139SecretKeyStore::SecretKeyStore(bool fKeyBufNonPageable)
140{
141 m_fKeyBufNonPageable = fKeyBufNonPageable;
142}
143
144SecretKeyStore::~SecretKeyStore()
145{
146 int rc = deleteAllSecretKeys(false /* fSuspend */, true /* fForce */);
147 AssertRC(rc);
148}
149
150int SecretKeyStore::addSecretKey(const com::Utf8Str &strKeyId, const uint8_t *pbKey, size_t cbKey)
151{
152 /* Check that the ID is not existing already. */
153 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
154 if (it != m_mapSecretKeys.end())
155 return VERR_ALREADY_EXISTS;
156
157 SecretKey *pKey = NULL;
158 try
159 {
160 pKey = new SecretKey(pbKey, cbKey, m_fKeyBufNonPageable);
161
162 m_mapSecretKeys.insert(std::make_pair(strKeyId, pKey));
163 }
164 catch (int rc)
165 {
166 return rc;
167 }
168 catch (std::bad_alloc &)
169 {
170 if (pKey)
171 delete pKey;
172 return VERR_NO_MEMORY;
173 }
174
175 return VINF_SUCCESS;
176}
177
178int SecretKeyStore::deleteSecretKey(const com::Utf8Str &strKeyId)
179{
180 SecretKeyMap::iterator it = m_mapSecretKeys.find(strKeyId);
181 if (it == m_mapSecretKeys.end())
182 return VERR_NOT_FOUND;
183
184 SecretKey *pKey = it->second;
185 if (pKey->refCount() != 0)
186 return VERR_RESOURCE_IN_USE;
187
188 m_mapSecretKeys.erase(it);
189 delete pKey;
190
191 return VINF_SUCCESS;
192}
193
194int SecretKeyStore::retainSecretKey(const com::Utf8Str &strKeyId, SecretKey **ppKey)
195{
196 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
197 if (it == m_mapSecretKeys.end())
198 return VERR_NOT_FOUND;
199
200 SecretKey *pKey = it->second;
201 pKey->retain();
202
203 *ppKey = pKey;
204
205 return VINF_SUCCESS;
206}
207
208int SecretKeyStore::releaseSecretKey(const com::Utf8Str &strKeyId)
209{
210 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
211 if (it == m_mapSecretKeys.end())
212 return VERR_NOT_FOUND;
213
214 SecretKey *pKey = it->second;
215 pKey->release();
216 return VINF_SUCCESS;
217}
218
219int SecretKeyStore::deleteAllSecretKeys(bool fSuspend, bool fForce)
220{
221 /* First check whether a key is still in use. */
222 if (!fForce)
223 {
224 for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
225 it != m_mapSecretKeys.end();
226 ++it)
227 {
228 SecretKey *pKey = it->second;
229 if ( pKey->refCount()
230 && ( ( pKey->getRemoveOnSuspend()
231 && fSuspend)
232 || !fSuspend))
233 return VERR_RESOURCE_IN_USE;
234 }
235 }
236
237 SecretKeyMap::iterator it = m_mapSecretKeys.begin();
238 while (it != m_mapSecretKeys.end())
239 {
240 SecretKey *pKey = it->second;
241 if ( pKey->getRemoveOnSuspend()
242 || !fSuspend)
243 {
244 AssertMsg(!pKey->refCount(), ("No one should access the stored key at this point anymore!\n"));
245 delete pKey;
246 SecretKeyMap::iterator itNext = it;
247 ++itNext;
248 m_mapSecretKeys.erase(it);
249 it = itNext;
250 }
251 else
252 ++it;
253 }
254
255 return VINF_SUCCESS;
256}
257
258void vboxImageCryptoSetup(VDISKCRYPTOSETTINGS *pSettings, const char *pszCipher,
259 const char *pszKeyStore, const char *pszPassword,
260 bool fCreateKeyStore)
261{
262 pSettings->pszCipher = pszCipher;
263 pSettings->pszPassword = pszPassword;
264 pSettings->pszKeyStoreLoad = pszKeyStore;
265 pSettings->fCreateKeyStore = fCreateKeyStore;
266 pSettings->pbDek = NULL;
267 pSettings->cbDek = 0;
268 pSettings->vdFilterIfaces = NULL;
269
270 pSettings->vdIfCfg.pfnAreKeysValid = vboximgVdCryptoConfigAreKeysValid;
271 pSettings->vdIfCfg.pfnQuerySize = vboximgVdCryptoConfigQuerySize;
272 pSettings->vdIfCfg.pfnQuery = vboximgVdCryptoConfigQuery;
273 pSettings->vdIfCfg.pfnQueryBytes = NULL;
274
275 pSettings->vdIfCrypto.pfnKeyRetain = vboximgVdCryptoKeyRetain;
276 pSettings->vdIfCrypto.pfnKeyRelease = vboximgVdCryptoKeyRelease;
277 pSettings->vdIfCrypto.pfnKeyStorePasswordRetain = vboximgVdCryptoKeyStorePasswordRetain;
278 pSettings->vdIfCrypto.pfnKeyStorePasswordRelease = vboximgVdCryptoKeyStorePasswordRelease;
279 pSettings->vdIfCrypto.pfnKeyStoreSave = vboximgVdCryptoKeyStoreSave;
280 pSettings->vdIfCrypto.pfnKeyStoreReturnParameters = vboximgVdCryptoKeyStoreReturnParameters;
281
282 int rc = VDInterfaceAdd(&pSettings->vdIfCfg.Core,
283 "vboximgVdInterfaceCfgCrypto",
284 VDINTERFACETYPE_CONFIG, pSettings,
285 sizeof(VDINTERFACECONFIG), &pSettings->vdFilterIfaces);
286 AssertRC(rc);
287
288 rc = VDInterfaceAdd(&pSettings->vdIfCrypto.Core,
289 "vboximgVdInterfaceCrypto",
290 VDINTERFACETYPE_CRYPTO, pSettings,
291 sizeof(VDINTERFACECRYPTO), &pSettings->vdFilterIfaces);
292 AssertRC(rc);
293}
294
295DECLCALLBACK(bool) vboximgVdCryptoConfigAreKeysValid(void *pvUser, const char *pszzValid)
296{
297 /* Just return always true here. */
298 NOREF(pvUser);
299 NOREF(pszzValid);
300 return true;
301}
302
303DECLCALLBACK(int) vboximgVdCryptoConfigQuerySize(void *pvUser, const char *pszName, size_t *pcbValue)
304{
305 VDISKCRYPTOSETTINGS *pSettings = (VDISKCRYPTOSETTINGS *)pvUser;
306 AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
307 AssertPtrReturn(pcbValue, VERR_INVALID_POINTER);
308
309 size_t cbValue = 0;
310 if (!strcmp(pszName, "Algorithm"))
311 cbValue = strlen(pSettings->pszCipher) + 1;
312 else if (!strcmp(pszName, "KeyId"))
313 cbValue = sizeof("irrelevant");
314 else if (!strcmp(pszName, "KeyStore"))
315 {
316 if (!pSettings->pszKeyStoreLoad)
317 return VERR_CFGM_VALUE_NOT_FOUND;
318 cbValue = strlen(pSettings->pszKeyStoreLoad) + 1;
319 }
320 else if (!strcmp(pszName, "CreateKeyStore"))
321 cbValue = 2; /* Single digit + terminator. */
322 else
323 return VERR_CFGM_VALUE_NOT_FOUND;
324
325 *pcbValue = cbValue + 1 /* include terminator */;
326
327 return VINF_SUCCESS;
328}
329
330DECLCALLBACK(int) vboximgVdCryptoConfigQuery(void *pvUser, const char *pszName,
331 char *pszValue, size_t cchValue)
332{
333 VDISKCRYPTOSETTINGS *pSettings = (VDISKCRYPTOSETTINGS *)pvUser;
334 AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
335 AssertPtrReturn(pszValue, VERR_INVALID_POINTER);
336
337 const char *psz = NULL;
338 if (!strcmp(pszName, "Algorithm"))
339 psz = pSettings->pszCipher;
340 else if (!strcmp(pszName, "KeyId"))
341 psz = "irrelevant";
342 else if (!strcmp(pszName, "KeyStore"))
343 psz = pSettings->pszKeyStoreLoad;
344 else if (!strcmp(pszName, "CreateKeyStore"))
345 {
346 if (pSettings->fCreateKeyStore)
347 psz = "1";
348 else
349 psz = "0";
350 }
351 else
352 return VERR_CFGM_VALUE_NOT_FOUND;
353
354 size_t cch = strlen(psz);
355 if (cch >= cchValue)
356 return VERR_CFGM_NOT_ENOUGH_SPACE;
357
358 memcpy(pszValue, psz, cch + 1);
359 return VINF_SUCCESS;
360}
361
362DECLCALLBACK(int) vboximgVdCryptoKeyRetain(void *pvUser, const char *pszId,
363 const uint8_t **ppbKey, size_t *pcbKey)
364{
365 VDISKCRYPTOSETTINGS *pSettings = (VDISKCRYPTOSETTINGS *)pvUser;
366 NOREF(pszId);
367 NOREF(ppbKey);
368 NOREF(pcbKey);
369 AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
370 AssertMsgFailedReturn(("This method should not be called here!\n"), VERR_INVALID_STATE);
371}
372
373DECLCALLBACK(int) vboximgVdCryptoKeyRelease(void *pvUser, const char *pszId)
374{
375 VDISKCRYPTOSETTINGS *pSettings = (VDISKCRYPTOSETTINGS *)pvUser;
376 NOREF(pszId);
377 AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
378 AssertMsgFailedReturn(("This method should not be called here!\n"), VERR_INVALID_STATE);
379}
380
381DECLCALLBACK(int) vboximgVdCryptoKeyStorePasswordRetain(void *pvUser, const char *pszId, const char **ppszPassword)
382{
383 VDISKCRYPTOSETTINGS *pSettings = (VDISKCRYPTOSETTINGS *)pvUser;
384 AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
385
386 NOREF(pszId);
387 *ppszPassword = pSettings->pszPassword;
388 return VINF_SUCCESS;
389}
390
391DECLCALLBACK(int) vboximgVdCryptoKeyStorePasswordRelease(void *pvUser, const char *pszId)
392{
393 VDISKCRYPTOSETTINGS *pSettings = (VDISKCRYPTOSETTINGS *)pvUser;
394 AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
395 NOREF(pszId);
396 return VINF_SUCCESS;
397}
398
399DECLCALLBACK(int) vboximgVdCryptoKeyStoreSave(void *pvUser, const void *pvKeyStore, size_t cbKeyStore)
400{
401 VDISKCRYPTOSETTINGS *pSettings = (VDISKCRYPTOSETTINGS *)pvUser;
402 AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
403
404 pSettings->pszKeyStore = (char *)RTMemAllocZ(cbKeyStore);
405 if (!pSettings->pszKeyStore)
406 return VERR_NO_MEMORY;
407
408 memcpy(pSettings->pszKeyStore, pvKeyStore, cbKeyStore);
409 return VINF_SUCCESS;
410}
411
412DECLCALLBACK(int) vboximgVdCryptoKeyStoreReturnParameters(void *pvUser, const char *pszCipher,
413 const uint8_t *pbDek, size_t cbDek)
414{
415 VDISKCRYPTOSETTINGS *pSettings = (VDISKCRYPTOSETTINGS *)pvUser;
416 AssertPtrReturn(pSettings, VERR_GENERAL_FAILURE);
417
418 pSettings->pszCipherReturned = RTStrDup(pszCipher);
419 pSettings->pbDek = pbDek;
420 pSettings->cbDek = cbDek;
421
422 return pSettings->pszCipherReturned ? VINF_SUCCESS : VERR_NO_MEMORY;
423}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette