VirtualBox

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

Last change on this file since 80862 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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