VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/CryptoUtils.cpp@ 94779

Last change on this file since 94779 was 94779, checked in by vboxsync, 3 years ago

Main: Introduce crypto utilities for handling SSM files, bugref:9955 [build fix]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.0 KB
Line 
1/* $Id: CryptoUtils.cpp 94779 2022-05-02 10:54:39Z vboxsync $ */
2/** @file
3 * Main - Cryptographic utility functions used by both VBoxSVC and VBoxC.
4 */
5
6/*
7 * Copyright (C) 2022 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/file.h>
22#include <iprt/vfs.h>
23
24#include "CryptoUtils.h"
25
26
27/*static*/
28DECLCALLBACK(int) SsmStream::i_ssmCryptoWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite)
29{
30 SsmStream *pThis = static_cast<SsmStream *>(pvUser);
31
32 return RTVfsFileWriteAt(pThis->m_hVfsFile, (RTFOFF)offStream, pvBuf, cbToWrite, NULL /*pcbWritten*/);
33}
34
35
36/*static*/
37DECLCALLBACK(int) SsmStream::i_ssmCryptoRead(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead)
38{
39 SsmStream *pThis = static_cast<SsmStream *>(pvUser);
40
41 return RTVfsFileReadAt(pThis->m_hVfsFile, (RTFOFF)offStream, pvBuf, cbToRead, pcbRead);
42}
43
44
45/*static*/
46DECLCALLBACK(int) SsmStream::i_ssmCryptoSeek(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
47{
48 SsmStream *pThis = static_cast<SsmStream *>(pvUser);
49
50 return RTVfsFileSeek(pThis->m_hVfsFile, (RTFOFF)offSeek, uMethod, poffActual);
51}
52
53
54/*static*/
55DECLCALLBACK(uint64_t) SsmStream::i_ssmCryptoTell(void *pvUser)
56{
57 SsmStream *pThis = static_cast<SsmStream *>(pvUser);
58
59 return (uint64_t)RTVfsFileTell(pThis->m_hVfsFile);
60}
61
62
63/*static*/
64DECLCALLBACK(int) SsmStream::i_ssmCryptoSize(void *pvUser, uint64_t *pcb)
65{
66 SsmStream *pThis = static_cast<SsmStream *>(pvUser);
67
68 return RTVfsFileQuerySize(pThis->m_hVfsFile, pcb);
69}
70
71
72/*static*/
73DECLCALLBACK(int) SsmStream::i_ssmCryptoIsOk(void *pvUser)
74{
75 RT_NOREF(pvUser);
76
77 /** @todo */
78 return VINF_SUCCESS;
79}
80
81
82/*static*/
83DECLCALLBACK(int) SsmStream::i_ssmCryptoClose(void *pvUser, bool fCancelled)
84{
85 SsmStream *pThis = static_cast<SsmStream *>(pvUser);
86
87 RT_NOREF(fCancelled); /** @todo */
88 RTVfsFileRelease(pThis->m_hVfsFile);
89 pThis->m_hVfsFile = NIL_RTVFSFILE;
90 return VINF_SUCCESS;
91}
92
93
94#ifdef VBOX_COM_INPROC
95SsmStream::SsmStream(Console *pParent, SecretKeyStore *pKeyStore, const Utf8Str &strKeyId, const Utf8Str &strKeyStore)
96#else
97SsmStream::SsmStream(VirtualBox *pParent, SecretKeyStore *pKeyStore, const Utf8Str &strKeyId, const Utf8Str &strKeyStore)
98#endif
99{
100 m_StrmOps.u32Version = SSMSTRMOPS_VERSION;
101 m_StrmOps.pfnWrite = SsmStream::i_ssmCryptoWrite;
102 m_StrmOps.pfnRead = SsmStream::i_ssmCryptoRead;
103 m_StrmOps.pfnSeek = SsmStream::i_ssmCryptoSeek;
104 m_StrmOps.pfnTell = SsmStream::i_ssmCryptoTell;
105 m_StrmOps.pfnSize = SsmStream::i_ssmCryptoSize;
106 m_StrmOps.pfnIsOk = SsmStream::i_ssmCryptoIsOk;
107 m_StrmOps.pfnClose = SsmStream::i_ssmCryptoClose;
108 m_StrmOps.u32EndVersion = SSMSTRMOPS_VERSION;
109
110 m_pKeyStore = pKeyStore;
111 m_strKeyId = strKeyId;
112 m_strKeyStore = strKeyStore;
113 m_pParent = pParent;
114 m_hVfsFile = NIL_RTVFSFILE;
115 m_pSsm = NULL;
116 m_pCryptoIf = NULL;
117}
118
119
120SsmStream::~SsmStream()
121{
122 close();
123
124 if (m_pCryptoIf)
125 m_pParent->i_releaseCryptoIf(m_pCryptoIf);
126
127 m_pCryptoIf = NULL;
128 m_pKeyStore = NULL;
129}
130
131
132int SsmStream::open(const Utf8Str &strFilename, bool fWrite, PSSMHANDLE *ppSsmHandle)
133{
134 /* Fast path, if the saved state is not encrypted we can skip everything and let SSM handle the file. */
135 if (m_strKeyId.isEmpty())
136 {
137 AssertReturn(!fWrite, VERR_NOT_SUPPORTED);
138
139 int rc = SSMR3Open(strFilename.c_str(), NULL /*pStreamOps*/, NULL /*pvStreamOps*/,
140 0 /*fFlags*/, &m_pSsm);
141 if (RT_SUCCESS(rc))
142 *ppSsmHandle = m_pSsm;
143
144 return rc;
145 }
146
147 int rc = VINF_SUCCESS;
148 if (!m_pCryptoIf)
149 {
150#ifdef VBOX_COM_INPROC
151 rc = m_pParent->i_retainCryptoIf(&m_pCryptoIf);
152 if (RT_FAILURE(rc))
153 return rc;
154#else
155 HRESULT hrc = m_pParent->i_retainCryptoIf(&m_pCryptoIf);
156 if (FAILED(hrc))
157 return VERR_COM_IPRT_ERROR;
158#endif
159 }
160
161 SecretKey *pKey;
162 rc = m_pKeyStore->retainSecretKey(m_strKeyId, &pKey);
163 if (RT_SUCCESS(rc))
164 {
165 RTVFSFILE hVfsFileSsm = NIL_RTVFSFILE;
166 uint32_t fOpen = fWrite
167 ? RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE
168 : RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE;
169
170 rc = RTVfsFileOpenNormal(strFilename.c_str(), fOpen, &hVfsFileSsm);
171 if (RT_SUCCESS(rc))
172 {
173 const char *pszPassword = (const char *)pKey->getKeyBuffer();
174
175 rc = m_pCryptoIf->pfnCryptoFileFromVfsFile(hVfsFileSsm, m_strKeyStore.c_str(), pszPassword, &m_hVfsFile);
176 if (RT_SUCCESS(rc))
177 {
178 rc = SSMR3Open(NULL /*pszFilename*/, &m_StrmOps, this, 0 /*fFlags*/, &m_pSsm);
179 if (RT_SUCCESS(rc))
180 *ppSsmHandle = m_pSsm;
181
182 if (RT_FAILURE(rc))
183 {
184 RTVfsFileRelease(m_hVfsFile);
185 m_hVfsFile = NIL_RTVFSFILE;
186 }
187 }
188
189 /* Also release in success case because the encrypted file handle retained a new reference to it. */
190 RTVfsFileRelease(hVfsFileSsm);
191 }
192
193 pKey->release();
194 }
195
196 return rc;
197}
198
199
200int SsmStream::close(void)
201{
202 if (m_pSsm)
203 {
204 int rc = SSMR3Close(m_pSsm);
205 AssertRCReturn(rc, rc);
206 }
207
208 if (m_hVfsFile != NIL_RTVFSFILE)
209 RTVfsFileRelease(m_hVfsFile);
210
211 m_hVfsFile = NIL_RTVFSFILE;
212 m_pSsm = NULL;
213
214 return VINF_SUCCESS;
215}
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