VirtualBox

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

Last change on this file since 94777 was 94777, 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 94777 2022-05-02 10:46:02Z 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 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}
117
118
119SsmStream::~SsmStream()
120{
121 close();
122
123 if (m_pCryptoIf)
124 m_pParent->i_releaseCryptoIf(m_pCryptoIf);
125
126 m_pCryptoIf = NULL;
127 m_pKeyStore = NULL;
128}
129
130
131int SsmStream::open(const Utf8Str &strFilename, bool fWrite, PSSMHANDLE *ppSsmHandle)
132{
133 /* Fast path, if the saved state is not encrypted we can skip everything and let SSM handle the file. */
134 if (m_strKeyId.isEmpty())
135 {
136 AssertReturn(!fWrite, VERR_NOT_SUPPORTED);
137
138 int rc = SSMR3Open(strFilename.c_str(), NULL /*pStreamOps*/, NULL /*pvStreamOps*/,
139 0 /*fFlags*/, &m_pSsm);
140 if (RT_SUCCESS(rc))
141 *ppSsmHandle = m_pSsm;
142
143 return rc;
144 }
145
146 int rc = VINF_SUCCESS;
147 if (!m_pCryptoIf)
148 {
149#ifdef VBOX_COM_INPROC
150 rc = m_pParent->i_retainCryptoIf(&m_pCryptoIf);
151 if (RT_FAILURE(rc))
152 return rc;
153#else
154 HRESULT hrc = m_pParent->i_retainCryptoIf(&m_pCryptoIf);
155 if (FAILED(hrc))
156 return VERR_COM_IPRT_ERROR;
157#endif
158 }
159
160 SecretKey *pKey;
161 rc = m_pKeyStore->retainSecretKey(m_strKeyId, &pKey);
162 if (RT_SUCCESS(rc))
163 {
164 RTVFSFILE hVfsFileSsm = NIL_RTVFSFILE;
165 uint32_t fOpen = fWrite
166 ? RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE
167 : RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE;
168
169 rc = RTVfsFileOpenNormal(strFilename.c_str(), fOpen, &hVfsFileSsm);
170 if (RT_SUCCESS(rc))
171 {
172 const char *pszPassword = (const char *)pKey->getKeyBuffer();
173
174 rc = m_pCryptoIf->pfnCryptoFileFromVfsFile(hVfsFileSsm, m_strKeyStore.c_str(), pszPassword, &m_hVfsFile);
175 if (RT_SUCCESS(rc))
176 {
177 rc = SSMR3Open(NULL /*pszFilename*/, &m_StrmOps, this, 0 /*fFlags*/, &m_pSsm);
178 if (RT_SUCCESS(rc))
179 *ppSsmHandle = m_pSsm;
180
181 if (RT_FAILURE(rc))
182 {
183 RTVfsFileRelease(m_hVfsFile);
184 m_hVfsFile = NIL_RTVFSFILE;
185 }
186 }
187
188 /* Also release in success case because the encrypted file handle retained a new reference to it. */
189 RTVfsFileRelease(hVfsFileSsm);
190 }
191
192 pKey->release();
193 }
194
195 return rc;
196}
197
198
199int SsmStream::close(void)
200{
201 if (m_pSsm)
202 {
203 int rc = SSMR3Close(m_pSsm);
204 AssertRCReturn(rc, rc);
205 }
206
207 if (m_hVfsFile != NIL_RTVFSFILE)
208 RTVfsFileRelease(m_hVfsFile);
209
210 m_hVfsFile = NIL_RTVFSFILE;
211 m_pSsm = NULL;
212
213 return VINF_SUCCESS;
214}
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