VirtualBox

Changeset 90587 in vbox for trunk/src/VBox/Devices/Security


Ignore:
Timestamp:
Aug 10, 2021 9:39:57 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
146198
Message:

Devices/Security: EFI can communicate with the external TPM emulator over our own TPM interface emulation, bugref:10075

Location:
trunk/src/VBox/Devices/Security
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Security/DevTpm.cpp

    r90580 r90587  
    2929#include <iprt/string.h>
    3030#include <iprt/uuid.h>
     31
     32#include <iprt/formats/tpm.h>
    3133
    3234#include "VBoxDD.h"
     
    348350/** Locality response buffer size register. */
    349351#define TPM_CRB_LOCALITY_REG_CTRL_RSP_SZ                     0x64
    350 /** Locality response buffer size register. */
     352/** Locality response buffer address register. */
    351353#define TPM_CRB_LOCALITY_REG_CTRL_RSP_ADDR                   0x68
    352354/** Locality data buffer. */
     
    452454typedef struct DEVTPMR3
    453455{
     456    /** Pointer to the device instance. */
     457    PPDMDEVINS                      pDevIns;
    454458    /** The base interface for LUN\#0. */
    455459    PDMIBASE                        IBase;
     
    936940                break;
    937941            if (   (u32 & TPM_CRB_LOCALITY_REG_CTRL_REQ_CMD_RDY)
    938                 && pThis->enmState == DEVTPMSTATE_IDLE)
     942                && (   pThis->enmState == DEVTPMSTATE_IDLE
     943                    || pThis->enmState == DEVTPMSTATE_CMD_COMPLETION))
    939944            {
    940945                pThis->enmState = DEVTPMSTATE_READY;
     
    967972                && u32 == 0x1)
    968973            {
    969                 pThis->enmState == DEVTPMSTATE_CMD_EXEC;
     974                pThis->enmState = DEVTPMSTATE_CMD_EXEC;
    970975                rc = PDMDevHlpTaskTrigger(pDevIns, pThis->hTpmCmdTask);
    971976            }
     
    10081013    Assert(!(off & (cb - 1)));
    10091014
    1010     LogFlowFunc((": %RGp %#x\n", off, cb));
    10111015    VBOXSTRICTRC rc = VINF_SUCCESS;
    10121016    uint32_t uReg = tpmGetRegisterFromOffset(off);
    10131017    uint8_t bLoc = tpmGetLocalityFromOffset(off);
    10141018    PDEVTPMLOCALITY pLoc = &pThis->aLoc[bLoc];
    1015 
    10161019
    10171020    uint64_t u64;
     
    10201023    else
    10211024        rc = tpmMmioFifoRead(pDevIns, pThis, pLoc, bLoc, uReg, &u64);
     1025
     1026    LogFlowFunc((": %RGp %#x %#llx\n", off, cb, u64));
    10221027
    10231028    if (rc == VINF_SUCCESS)
     
    10851090    LogFlowFunc(("\n"));
    10861091
    1087     /** @todo */
    1088     RT_NOREF(pThis, pThisCC);
    1089     pThis->enmState = DEVTPMSTATE_CMD_COMPLETION;
     1092    int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED);
     1093    PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, pDevIns->pCritSectRoR3, rcLock);
     1094
     1095    if (pThisCC->pDrvTpm)
     1096    {
     1097        size_t cbCmd = RTTpmReqGetSz((PCTPMREQHDR)&pThis->abCmdResp[0]);
     1098        int rc = pThisCC->pDrvTpm->pfnCmdExec(pThisCC->pDrvTpm, pThis->bLoc, &pThis->abCmdResp[0], cbCmd,
     1099                                              &pThis->abCmdResp[0], sizeof(pThis->abCmdResp));
     1100        if (RT_SUCCESS(rc))
     1101        {
     1102            pThis->enmState = DEVTPMSTATE_CMD_COMPLETION;
     1103            tpmLocSetIntSts(pThisCC->pDevIns, pThis, &pThis->aLoc[pThis->bLoc], TPM_CRB_LOCALITY_REG_INT_STS_START);
     1104        }
     1105        else
     1106        {
     1107            /* Set fatal error. */
     1108            pThis->enmState = DEVTPMSTATE_FATAL_ERROR;
     1109        }
     1110    }
     1111
     1112    PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3);
    10901113}
    10911114
     
    11711194
    11721195/**
     1196 * @interface_method_impl{PDMDEVREG,pfnPowerOff}
     1197 */
     1198static DECLCALLBACK(void) tpmR3PowerOff(PPDMDEVINS pDevIns)
     1199{
     1200    PDEVTPMCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVTPMCC);
     1201
     1202    if (pThisCC->pDrvTpm)
     1203    {
     1204        int rc = pThisCC->pDrvTpm->pfnShutdown(pThisCC->pDrvTpm);
     1205        AssertRC(rc);
     1206    }
     1207}
     1208
     1209
     1210/**
    11731211 * @interface_method_impl{PDMDEVREG,pfnReset}
    11741212 */
     
    12181256
    12191257    pThis->hTpmCmdTask = NIL_PDMTASKHANDLE;
     1258
     1259    pThisCC->pDevIns   = pDevIns;
    12201260
    12211261    /* IBase */
     
    12751315        pThisCC->pDrvTpm = PDMIBASE_QUERY_INTERFACE(pThisCC->pDrvBase, PDMITPMCONNECTOR);
    12761316        AssertLogRelMsgReturn(pThisCC->pDrvTpm, ("TPM#%d: Driver is missing the TPM interface.\n", iInstance), VERR_PDM_MISSING_INTERFACE);
     1317
     1318        /* Startup the TPM here instead of in the power on callback as we can convey errors here to the upper layer. */
     1319        rc = pThisCC->pDrvTpm->pfnStartup(pThisCC->pDrvTpm, sizeof(pThis->abCmdResp));
     1320        if (RT_FAILURE(rc))
     1321            return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to startup the TPM"));
    12771322    }
    12781323    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
     
    13531398    /* .pfnQueryInterface = */      NULL,
    13541399    /* .pfnInitComplete = */        NULL,
    1355     /* .pfnPowerOff = */            NULL,
     1400    /* .pfnPowerOff = */            tpmR3PowerOff,
    13561401    /* .pfnSoftReset = */           NULL,
    13571402    /* .pfnReserved0 = */           NULL,
  • trunk/src/VBox/Devices/Security/DrvTpmEmu.cpp

    r90580 r90587  
    3535#include <iprt/uuid.h>
    3636#include <iprt/json.h>
     37
     38#include <iprt/formats/tpm.h>
    3739
    3840#include "VBoxDD.h"
     
    258260    RTSOCKET            hSockData;
    259261
     262#if 0
    260263    /** Poll set used to wait for I/O events. */
    261264    RTPOLLSET           hPollSet;
     
    269272    /** Flag to signal whether the thread was woken up from external. */
    270273    bool volatile       fWokenUp;
     274#endif
     275
    271276    /** Currently set locality. */
    272277    uint8_t             bLoc;
     
    411416    return drvTpmEmuExecCtrlCmdEx(pThis, enmCmd, pvCmd, cbCmd, pu32Resp,
    412417                                  NULL /*pvResp*/, 0 /*cbResp*/, cMillies);
     418}
     419
     420
     421/**
     422 * Executes the given command over the control connection to the TPM emulator - variant with no command payload.
     423 *
     424 * @returns VBox status code.
     425 * @retval  VERR_NET_IO_ERROR if the executed command returned an error in the response status field.
     426 * @param   pThis               Pointer to the TPM emulator driver instance data.
     427 * @param   enmCmd              The command to execute.
     428 * @param   pvResp              Where to store additional resposne data.
     429 * @param   cbResp              Size of the Response data in bytes (excluding the response status code which is implicit).
     430 * @param   cMillies            Number of milliseconds to wait before aborting the command with a timeout error.
     431 */
     432static int drvTpmEmuExecCtrlCmdNoPayloadAndResp(PDRVTPMEMU pThis, SWTPMCMD enmCmd, RTMSINTERVAL cMillies)
     433{
     434    uint32_t u32Resp = 0;
     435    int rc = drvTpmEmuExecCtrlCmdEx(pThis, enmCmd, NULL /*pvCmd*/, 0 /*cbCmd*/, &u32Resp,
     436                                    NULL /*pvResp*/, 0 /*cbResp*/, cMillies);
     437    if (RT_SUCCESS(rc))
     438    {
     439        if (u32Resp != 0)
     440            rc = VERR_NET_IO_ERROR;
     441    }
     442
     443    return rc;
    413444}
    414445
     
    523554        rc = VERR_NET_IO_ERROR;
    524555
     556    if (RT_SUCCESS(rc))
     557        pThis->bLoc = bLoc;
     558
    525559    return rc;
    526560}
     
    612646    if (RT_SUCCESS(rc))
    613647    {
    614         RT_NOREF(pInterface, bLoc, pvCmd, cbCmd, pvResp, cbResp);
     648        rc = RTSocketWrite(pThis->hSockData, pvCmd, cbCmd);
     649        if (RT_SUCCESS(rc))
     650        {
     651            rc = RTSocketSelectOne(pThis->hSockData, RT_MS_10SEC);
     652            if (RT_SUCCESS(rc))
     653            {
     654                /* Read the response header in first. */
     655                TPMRESPHDR RespHdr;
     656                rc = RTSocketRead(pThis->hSockData, &RespHdr, sizeof(RespHdr), NULL /*pcbRead*/);
     657                if (RT_SUCCESS(rc))
     658                {
     659                    size_t cbHdrResp = RTTpmRespGetSz(&RespHdr);
     660                    if (cbHdrResp <= cbResp - sizeof(RespHdr))
     661                    {
     662                        memcpy(pvResp, &RespHdr, sizeof(RespHdr));
     663
     664                        if (cbHdrResp > sizeof(RespHdr))
     665                            rc = RTSocketRead(pThis->hSockData, (uint8_t *)pvResp + sizeof(RespHdr), cbHdrResp - sizeof(RespHdr),
     666                                              NULL /*pcbRead*/);
     667                    }
     668                    else
     669                        rc = VERR_BUFFER_OVERFLOW;
     670                }
     671            }
     672        }
    615673    }
    616674
     
    622680static DECLCALLBACK(int) drvTpmEmuCmdCancel(PPDMITPMCONNECTOR pInterface)
    623681{
    624     RT_NOREF(pInterface);
    625     return VERR_NOT_IMPLEMENTED;
     682    PDRVTPMEMU pThis = RT_FROM_MEMBER(pInterface, DRVTPMEMU, ITpmConnector);
     683
     684    return drvTpmEmuExecCtrlCmdNoPayloadAndResp(pThis, SWTPMCMD_CANCEL_TPM_CMD, RT_MS_10SEC);
    626685}
    627686
     
    649708    if (pThis->hSockCtrl != NIL_RTSOCKET)
    650709    {
     710#if 0
    651711        int rc = RTPollSetRemove(pThis->hPollSet, DRVTPMEMU_POLLSET_ID_SOCKET_CTRL);
    652712        AssertRC(rc);
    653 
    654         rc = RTSocketShutdown(pThis->hSockCtrl, true /* fRead */, true /* fWrite */);
     713#endif
     714
     715        int rc = RTSocketShutdown(pThis->hSockCtrl, true /* fRead */, true /* fWrite */);
    655716        AssertRC(rc);
    656717
     
    663724    if (pThis->hSockData != NIL_RTSOCKET)
    664725    {
     726#if 0
    665727        int rc = RTPollSetRemove(pThis->hPollSet, DRVTPMEMU_POLLSET_ID_SOCKET_DATA);
    666728        AssertRC(rc);
    667 
    668         rc = RTSocketShutdown(pThis->hSockData, true /* fRead */, true /* fWrite */);
     729#endif
     730
     731        int rc = RTSocketShutdown(pThis->hSockData, true /* fRead */, true /* fWrite */);
    669732        AssertRC(rc);
    670733
     
    675738    }
    676739
     740#if 0
    677741    if (pThis->hPipeWakeR != NIL_RTPIPE)
    678742    {
     
    698762        pThis->hPollSet = NIL_RTPOLLSET;
    699763    }
     764#endif
    700765}
    701766
     
    717782    pThis->bLoc                                     = TPM_NO_LOCALITY_SELECTED;
    718783
     784#if 0
    719785    pThis->hPollSet                                 = NIL_RTPOLLSET;
    720786    pThis->hPipeWakeR                               = NIL_RTPIPE;
    721787    pThis->hPipeWakeW                               = NIL_RTPIPE;
     788#endif
    722789
    723790    /* IBase */
     
    744811                                   N_("Configuration error: querying \"Location\" resulted in %Rrc"), rc);
    745812
     813#if 0
    746814    rc = RTPipeCreate(&pThis->hPipeWakeR, &pThis->hPipeWakeW, 0 /* fFlags */);
    747815    if (RT_FAILURE(rc))
     
    761829                                   N_("DrvTpmEmu#%d failed to add wakeup pipe for %s to poll set"),
    762830                                   pDrvIns->iInstance, szLocation);
     831#endif
    763832
    764833    /*
     
    783852    if (RT_FAILURE(rc))
    784853        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
    785                                    N_("DrvTpmEmu#%d failed to connect to socket %s"),
     854                                   N_("DrvTpmEmu#%d failed to connect to control socket %s"),
    786855                                   pDrvIns->iInstance, szLocation);
    787856
     857#if 0
    788858    rc = RTPollSetAddSocket(pThis->hPollSet, pThis->hSockCtrl,
    789859                            RTPOLL_EVT_READ | RTPOLL_EVT_WRITE | RTPOLL_EVT_ERROR,
     
    793863                                   N_("DrvTpmEmu#%d failed to add socket for %s to poll set"),
    794864                                   pDrvIns->iInstance, szLocation);
     865#endif
    795866
    796867    rc = drvTpmEmuQueryCaps(pThis);
     
    839910                                   N_("DrvTpmEmu#%d Emulated TPM version of %s does not offer required set of capabilities (%#x requested vs. %#x offered)"),
    840911                                   pDrvIns->iInstance, szLocation, fCapsReq, pThis->fCaps);
     912
     913    /* Connect the data channel now. */
     914    /** @todo Allow configuring a different port. */
     915    *pszPort = '\0'; /* Overwrite temporarily to avoid copying the hostname into a temporary buffer. */
     916    rc = RTTcpClientConnect(szLocation, uPort + 1, &pThis->hSockData);
     917    *pszPort = ':'; /* Restore delimiter before checking the status. */
     918    if (RT_FAILURE(rc))
     919        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     920                                   N_("DrvTpmEmu#%d failed to connect to data socket %s"),
     921                                   pDrvIns->iInstance, szLocation);
    841922
    842923    LogRel(("DrvTpmEmu#%d: Connected to %s, emulating TPM version %s\n", pDrvIns->iInstance, szLocation, pszTpmVers));
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette