VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/tpm-win.cpp

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: tpm-win.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT - Trusted Platform Module (TPM) access, Windows variant.
4 */
5
6/*
7 * Copyright (C) 2021-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_DEFAULT
42#include <iprt/tpm.h>
43
44#include <iprt/assertcompile.h>
45#include <iprt/asm.h>
46#include <iprt/err.h>
47#include <iprt/ldr.h>
48#include <iprt/mem.h>
49#include <iprt/once.h>
50
51#include "internal-r3-win.h"
52
53#include <iprt/win/windows.h>
54
55
56/*********************************************************************************************************************************
57* Defined Constants And Macros *
58*********************************************************************************************************************************/
59/* tbs.dll: */
60typedef struct TBS_CONTEXT_PARAMS2
61{
62 UINT32 version;
63 union
64 {
65 struct
66 {
67 UINT32 requestRaw: 1;
68 UINT32 includeTpm12: 1;
69 UINT32 includeTpm20: 1;
70 } Fields;
71
72 UINT32 asUINT32;
73 } u;
74} TBS_CONTEXT_PARAMS2;
75
76typedef struct TBS_DEVICE_INFO
77{
78 UINT32 structVersion;
79 UINT32 tpmVersion;
80 UINT32 tpmInterfaceType;
81 UINT32 tpmImpRevision;
82} TBS_DEVICE_INFO;
83
84#define TPM_VERSION_12 1
85#define TPM_VERSION_20 2
86
87#define TBS_SUCCESS S_OK
88#define TBS_COMMAND_PRIORITY_NORMAL 200
89
90typedef UINT32 TBS_RESULT;
91typedef void *TBS_HCONTEXT;
92typedef TBS_RESULT (WINAPI *PFNTBSI_CONTEXT_CREATE)(const TBS_CONTEXT_PARAMS2 *, TBS_HCONTEXT *);
93typedef TBS_RESULT (WINAPI *PFNTBSI_CONTEXT_CLOSE)(TBS_HCONTEXT);
94typedef TBS_RESULT (WINAPI *PFNTBSI_GET_DEVICE_INFO)(UINT32, TBS_DEVICE_INFO *);
95typedef TBS_RESULT (WINAPI *PFNTBSI_CANCEL_COMMANDS)(TBS_HCONTEXT);
96typedef TBS_RESULT (WINAPI *PFNTBSI_SUBMIT_COMMANDS)(TBS_HCONTEXT, UINT32, UINT32, const BYTE *, UINT32, PBYTE, PUINT32);
97
98
99/*********************************************************************************************************************************
100* Structures and Typedefs *
101*********************************************************************************************************************************/
102
103/**
104 * Internal TPM instance data.
105 */
106typedef struct RTTPMINT
107{
108 /** Handle to the TPM context. */
109 TBS_HCONTEXT hCtx;
110 /** The deduced TPM version. */
111 RTTPMVERSION enmTpmVers;
112} RTTPMINT;
113/** Pointer to the internal TPM instance data. */
114typedef RTTPMINT *PRTTPMINT;
115
116
117/*********************************************************************************************************************************
118* Global Variables *
119*********************************************************************************************************************************/
120/** Init once structure. */
121static RTONCE g_rtTpmWinInitOnce = RTONCE_INITIALIZER;
122/* tbs.dll: */
123static PFNTBSI_CONTEXT_CREATE g_pfnTbsiContextCreate = NULL;
124static PFNTBSI_CONTEXT_CLOSE g_pfnTbsiContextClose = NULL;
125static PFNTBSI_GET_DEVICE_INFO g_pfnTbsiGetDeviceInfo = NULL;
126static PFNTBSI_CANCEL_COMMANDS g_pfnTbsiCancelCommands = NULL;
127static PFNTBSI_SUBMIT_COMMANDS g_pfnTbsiSubmitCommands = NULL;
128
129
130/*********************************************************************************************************************************
131* Internal Functions *
132*********************************************************************************************************************************/
133
134/**
135 * Initialize the globals.
136 *
137 * @returns IPRT status code.
138 * @param pvUser Ignored.
139 */
140static DECLCALLBACK(int32_t) rtTpmWinInitOnce(void *pvUser)
141{
142 RT_NOREF(pvUser);
143 RTLDRMOD hMod;
144
145 int rc = RTLdrLoadSystem("tbs.dll", true /*fNoUnload*/, &hMod);
146 if (RT_SUCCESS(rc))
147 {
148 rc = RTLdrGetSymbol(hMod, "Tbsi_Context_Create", (void **)&g_pfnTbsiContextCreate);
149 if (RT_FAILURE(rc)) return rc;
150
151 rc = RTLdrGetSymbol(hMod, "Tbsip_Context_Close", (void **)&g_pfnTbsiContextClose);
152 if (RT_FAILURE(rc)) return rc;
153
154 rc = RTLdrGetSymbol(hMod, "Tbsip_Cancel_Commands", (void **)&g_pfnTbsiCancelCommands);
155 if (RT_FAILURE(rc)) return rc;
156
157 rc = RTLdrGetSymbol(hMod, "Tbsip_Submit_Command", (void **)&g_pfnTbsiSubmitCommands);
158 if (RT_FAILURE(rc)) return rc;
159
160 rc = RTLdrGetSymbol(hMod, "Tbsi_GetDeviceInfo", (void **)&g_pfnTbsiGetDeviceInfo);
161 if (RT_FAILURE(rc)) { g_pfnTbsiGetDeviceInfo = NULL; Assert(g_enmWinVer < kRTWinOSType_8); }
162
163 RTLdrClose(hMod);
164 }
165
166 return rc;
167}
168
169
170RTDECL(int) RTTpmOpen(PRTTPM phTpm, uint32_t idTpm)
171{
172 AssertPtrReturn(phTpm, VERR_INVALID_POINTER);
173 if (idTpm == RTTPM_ID_DEFAULT)
174 idTpm = 0;
175
176 AssertReturn(idTpm == 0, VERR_NOT_SUPPORTED);
177
178 /*
179 * Initialize the globals.
180 */
181 int rc = RTOnce(&g_rtTpmWinInitOnce, rtTpmWinInitOnce, NULL);
182 AssertRCReturn(rc, rc);
183
184 PRTTPMINT pThis = (PRTTPMINT)RTMemAllocZ(sizeof(*pThis));
185 if (pThis)
186 {
187 TBS_CONTEXT_PARAMS2 CtxParams; RT_ZERO(CtxParams);
188
189 CtxParams.version = TPM_VERSION_12;
190 if (g_pfnTbsiGetDeviceInfo)
191 {
192 /* TPM2 support is available starting with Win8 which has Tbsi_GetDeviceInfo available. */
193 TBS_DEVICE_INFO DevInfo; RT_ZERO(DevInfo);
194
195 DevInfo.structVersion = TPM_VERSION_20;
196 TBS_RESULT rcTbs = g_pfnTbsiGetDeviceInfo(sizeof(DevInfo), &DevInfo);
197 if (rcTbs == TBS_SUCCESS)
198 {
199 CtxParams.version = TPM_VERSION_20;
200 if (DevInfo.tpmVersion == TPM_VERSION_20)
201 {
202 pThis->enmTpmVers = RTTPMVERSION_2_0;
203 CtxParams.u.Fields.includeTpm20 = 1;
204 }
205 else
206 {
207 Assert(DevInfo.tpmVersion == TPM_VERSION_12);
208 pThis->enmTpmVers = RTTPMVERSION_1_2;
209 CtxParams.u.Fields.includeTpm12 = 1;
210 }
211 }
212 else
213 rc = VERR_NOT_FOUND;
214 }
215 else
216 pThis->enmTpmVers = RTTPMVERSION_1_2;
217
218 if (RT_SUCCESS(rc))
219 {
220 TBS_RESULT rcTbs = g_pfnTbsiContextCreate(&CtxParams, &pThis->hCtx);
221 if (rcTbs == TBS_SUCCESS)
222 {
223 *phTpm = pThis;
224 return VINF_SUCCESS;
225 }
226 else
227 rc = VERR_NOT_FOUND;
228 }
229
230 RTMemFree(pThis);
231 }
232 else
233 rc = VERR_NO_MEMORY;
234
235 return rc;
236}
237
238
239RTDECL(int) RTTpmClose(RTTPM hTpm)
240{
241 PRTTPMINT pThis = hTpm;
242
243 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
244
245 TBS_RESULT rcTbs = g_pfnTbsiContextClose(pThis->hCtx);
246 Assert(rcTbs == TBS_SUCCESS); RT_NOREF(rcTbs);
247
248 RTMemFree(pThis);
249 return VINF_SUCCESS;
250}
251
252
253RTDECL(RTTPMVERSION) RTTpmGetVersion(RTTPM hTpm)
254{
255 PRTTPMINT pThis = hTpm;
256
257 AssertPtrReturn(pThis, RTTPMVERSION_INVALID);
258 return pThis->enmTpmVers;
259}
260
261
262RTDECL(uint32_t) RTTpmGetLocalityMax(RTTPM hTpm)
263{
264 RT_NOREF(hTpm);
265 return 0; /* Only TPM locality 0 is supported. */
266}
267
268
269RTDECL(int) RTTpmReqCancel(RTTPM hTpm)
270{
271 PRTTPMINT pThis = hTpm;
272
273 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
274
275 TBS_RESULT rcTbs = g_pfnTbsiCancelCommands(pThis->hCtx);
276 if (rcTbs != TBS_SUCCESS)
277 return VERR_DEV_IO_ERROR;
278
279 return VINF_SUCCESS;
280}
281
282
283RTDECL(int) RTTpmReqExec(RTTPM hTpm, uint8_t bLoc, const void *pvReq, size_t cbReq,
284 void *pvResp, size_t cbRespMax, size_t *pcbResp)
285{
286 PRTTPMINT pThis = hTpm;
287
288 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
289 AssertPtrReturn(pvReq, VERR_INVALID_POINTER);
290 AssertPtrReturn(pvResp, VERR_INVALID_POINTER);
291 AssertReturn(cbReq && cbRespMax, VERR_INVALID_PARAMETER);
292 AssertReturn(cbReq == (UINT32)cbReq && cbRespMax == (UINT32)cbRespMax, VERR_BUFFER_OVERFLOW);
293 AssertReturn(bLoc == 0, VERR_NOT_SUPPORTED); /* TBS doesn't support another locality than 0. */
294
295 UINT32 cbResult = (UINT32)cbRespMax;
296 TBS_RESULT rcTbs = g_pfnTbsiSubmitCommands(pThis->hCtx, 0 /*Locality*/, TBS_COMMAND_PRIORITY_NORMAL,
297 (const BYTE *)pvReq, (UINT32)cbReq, (BYTE *)pvResp, &cbResult);
298 if (rcTbs == TBS_SUCCESS)
299 {
300 if (pcbResp)
301 *pcbResp = cbResult;
302 return VINF_SUCCESS;
303 }
304
305 return VERR_DEV_IO_ERROR;
306}
307
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