VirtualBox

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

Last change on this file since 72168 was 69500, checked in by vboxsync, 7 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.3 KB
Line 
1/* $Id: SecretKeyStore.cpp 69500 2017-10-28 15:14:05Z vboxsync $ */
2/** @file
3 * Main - Secret key interface.
4 */
5
6/*
7 * Copyright (C) 2015-2017 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 try
139 {
140 SecretKey *pKey = new SecretKey(pbKey, cbKey, m_fKeyBufNonPageable);
141
142 m_mapSecretKeys.insert(std::make_pair(strKeyId, pKey));
143 }
144 catch (int rc)
145 {
146 return rc;
147 }
148
149 return VINF_SUCCESS;
150}
151
152int SecretKeyStore::deleteSecretKey(const com::Utf8Str &strKeyId)
153{
154 SecretKeyMap::iterator it = m_mapSecretKeys.find(strKeyId);
155 if (it == m_mapSecretKeys.end())
156 return VERR_NOT_FOUND;
157
158 SecretKey *pKey = it->second;
159 if (pKey->refCount() != 0)
160 return VERR_RESOURCE_IN_USE;
161
162 m_mapSecretKeys.erase(it);
163 delete pKey;
164
165 return VINF_SUCCESS;
166}
167
168int SecretKeyStore::retainSecretKey(const com::Utf8Str &strKeyId, SecretKey **ppKey)
169{
170 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
171 if (it == m_mapSecretKeys.end())
172 return VERR_NOT_FOUND;
173
174 SecretKey *pKey = it->second;
175 pKey->retain();
176
177 *ppKey = pKey;
178
179 return VINF_SUCCESS;
180}
181
182int SecretKeyStore::releaseSecretKey(const com::Utf8Str &strKeyId)
183{
184 SecretKeyMap::const_iterator it = m_mapSecretKeys.find(strKeyId);
185 if (it == m_mapSecretKeys.end())
186 return VERR_NOT_FOUND;
187
188 SecretKey *pKey = it->second;
189 pKey->release();
190 return VINF_SUCCESS;
191}
192
193int SecretKeyStore::deleteAllSecretKeys(bool fSuspend, bool fForce)
194{
195 /* First check whether a key is still in use. */
196 if (!fForce)
197 {
198 for (SecretKeyMap::iterator it = m_mapSecretKeys.begin();
199 it != m_mapSecretKeys.end();
200 ++it)
201 {
202 SecretKey *pKey = it->second;
203 if ( pKey->refCount()
204 && ( ( pKey->getRemoveOnSuspend()
205 && fSuspend)
206 || !fSuspend))
207 return VERR_RESOURCE_IN_USE;
208 }
209 }
210
211 SecretKeyMap::iterator it = m_mapSecretKeys.begin();
212 while (it != m_mapSecretKeys.end())
213 {
214 SecretKey *pKey = it->second;
215 if ( pKey->getRemoveOnSuspend()
216 || !fSuspend)
217 {
218 AssertMsg(!pKey->refCount(), ("No one should access the stored key at this point anymore!\n"));
219 delete pKey;
220 SecretKeyMap::iterator itNext = it;
221 ++itNext;
222 m_mapSecretKeys.erase(it);
223 it = itNext;
224 }
225 else
226 ++it;
227 }
228
229 return VINF_SUCCESS;
230}
231
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