VirtualBox

Changeset 91005 in vbox for trunk/src


Ignore:
Timestamp:
Aug 30, 2021 4:32:25 PM (3 years ago)
Author:
vboxsync
Message:

Security: The underlying driver specifies the input buffer size of the TPM for the device emulation to use and not the other way around, bugref:10075

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

Legend:

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

    r90996 r91005  
    4848/** Default revision ID. */
    4949#define TPM_RID_DEFAULT                                 0x01
     50/** Maximum size of the data buffer in bytes. */
     51#define TPM_DATA_BUFFER_SIZE_MAX                        3968
    5052
    5153/** The TPM MMIO base default as defined in chapter 5.2. */
     
    418420/** Locality data buffer. */
    419421#define TPM_CRB_LOCALITY_REG_DATA_BUFFER                     0x80
    420 /** Size of the data buffer. */
    421 #define TPM_CRB_LOCALITY_REG_DATA_BUFFER_SIZE                3968
    422422/** @} */
    423423
     
    507507    TPMVERSION                      enmTpmVers;
    508508
     509    /** Size of the command/response buffer. */
     510    uint32_t                        cbCmdResp;
    509511    /** Offset into the Command/Response buffer. */
    510512    uint32_t                        offCmdResp;
    511513    /** Command/Response buffer. */
    512     uint8_t                         abCmdResp[TPM_CRB_LOCALITY_REG_DATA_BUFFER_SIZE];
     514    uint8_t                         abCmdResp[TPM_DATA_BUFFER_SIZE_MAX];
    513515} DEVTPM;
    514516/** Pointer to the shared TPM device state. */
     
    683685        && pThis->enmState == DEVTPMSTATE_CMD_COMPLETION)
    684686    {
    685         if (pThis->offCmdResp <= sizeof(pThis->abCmdResp) - cb)
     687        if (pThis->offCmdResp <= pThis->cbCmdResp - cb)
    686688        {
    687689            memcpy(pu64, &pThis->abCmdResp[pThis->offCmdResp], cb);
     
    810812    {
    811813        pThis->enmState = DEVTPMSTATE_CMD_RECEPTION;
    812         if (pThis->offCmdResp <= sizeof(pThis->abCmdResp) - cb)
     814        if (pThis->offCmdResp <=  pThis->cbCmdResp - cb)
    813815        {
    814816            memcpy(&pThis->abCmdResp[pThis->offCmdResp], &u64, cb);
     
    935937    /* Special path for the data buffer. */
    936938    if (   uReg >= TPM_CRB_LOCALITY_REG_DATA_BUFFER
    937         && uReg < TPM_CRB_LOCALITY_REG_DATA_BUFFER + TPM_CRB_LOCALITY_REG_DATA_BUFFER_SIZE
     939        && uReg < TPM_CRB_LOCALITY_REG_DATA_BUFFER + pThis->cbCmdResp
    938940        && bLoc == pThis->bLoc
    939941        && pThis->enmState == DEVTPMSTATE_CMD_COMPLETION)
     
    10261028        case TPM_CRB_LOCALITY_REG_CTRL_CMD_SZ:
    10271029        case TPM_CRB_LOCALITY_REG_CTRL_RSP_SZ:
    1028             u64 = TPM_CRB_LOCALITY_REG_DATA_BUFFER_SIZE;
     1030            u64 = pThis->cbCmdResp;
    10291031            break;
    10301032        case TPM_CRB_LOCALITY_REG_CTRL_RSP_ADDR:
     
    10641066    /* Special path for the data buffer. */
    10651067    if (   uReg >= TPM_CRB_LOCALITY_REG_DATA_BUFFER
    1066         && uReg < TPM_CRB_LOCALITY_REG_DATA_BUFFER + TPM_CRB_LOCALITY_REG_DATA_BUFFER_SIZE
     1068        && uReg < TPM_CRB_LOCALITY_REG_DATA_BUFFER + pThis->cbCmdResp
    10671069        && bLoc == pThis->bLoc
    10681070        && (   pThis->enmState == DEVTPMSTATE_READY
     
    15101512        AssertLogRelMsgReturn(pThisCC->pDrvTpm, ("TPM#%d: Driver is missing the TPM interface.\n", iInstance), VERR_PDM_MISSING_INTERFACE);
    15111513
     1514        pThis->fLocChangeSup = pThisCC->pDrvTpm->pfnGetLocalityMax(pThisCC->pDrvTpm) > 0;
     1515        pThis->cbCmdResp     = RT_MIN(pThisCC->pDrvTpm->pfnGetBufferSize(pThisCC->pDrvTpm), TPM_DATA_BUFFER_SIZE_MAX);
     1516
    15121517        /* Startup the TPM here instead of in the power on callback as we can convey errors here to the upper layer. */
    1513         rc = pThisCC->pDrvTpm->pfnStartup(pThisCC->pDrvTpm, sizeof(pThis->abCmdResp));
     1518        rc = pThisCC->pDrvTpm->pfnStartup(pThisCC->pDrvTpm);
    15141519        if (RT_FAILURE(rc))
    15151520            return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to startup the TPM"));
     
    15181523        if (pThis->enmTpmVers == TPMVERSION_UNKNOWN)
    15191524            return PDMDEV_SET_ERROR(pDevIns, VERR_NOT_SUPPORTED, N_("The emulated TPM version is not supported"));
    1520 
    1521         pThis->fLocChangeSup = pThisCC->pDrvTpm->pfnGetLocalityMax(pThisCC->pDrvTpm) > 0;
    15221525    }
    15231526    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
  • trunk/src/VBox/Devices/Security/DrvTpmEmu.cpp

    r90996 r91005  
    235235{
    236236    /** The locality resetting trying to reset the established bit. */
    237     uint8_t                    bLoc;
     237    uint8_t                     bLoc;
    238238} SWTPMCMDRSTEST;
    239239/** Pointer to a response data struct for SWTPMCMD_GET_TPMESTABLISHED. */
     
    241241/** Pointer to a const response data struct for SWTPMCMD_GET_TPMESTABLISHED. */
    242242typedef const SWTPMCMDRSTEST *PCSWTPMCMDRSTEST;
     243
     244
     245/**
     246 * Additional command data for SWTPMCMD_SET_BUFFERSIZE.
     247 */
     248typedef struct SWTPMCMDSETBUFSZ
     249{
     250    /** The buffer size to set, 0 to query for the currently used buffer size. */
     251    uint32_t                    cbBuffer;
     252} SWTPMCMDSETBUFSZ;
     253/** Pointer to a command data struct for SWTPMCMD_SET_BUFFERSIZE. */
     254typedef SWTPMCMDSETBUFSZ *PSWTPMCMDSETBUFSZ;
     255/** Pointer to a const command data struct for SWTPMCMD_SET_BUFFERSIZE. */
     256typedef const SWTPMCMDSETBUFSZ *PCSWTPMCMDSETBUFSZ;
     257
     258
     259/**
     260 * Response data for a SWTPMCMD_SET_BUFFERSIZE command.
     261 */
     262typedef struct SWTPMRESPSETBUFSZ
     263{
     264    /** Buffer size in use. */
     265    uint32_t                    cbBuffer;
     266    /** Minimum supported buffer size. */
     267    uint32_t                    cbBufferMin;
     268    /** Maximum supported buffer size. */
     269    uint32_t                    cbBufferMax;
     270} SWTPMRESPSETBUFSZ;
     271/** Pointer to a response data struct for SWTPMCMD_SET_BUFFERSIZE. */
     272typedef SWTPMRESPSETBUFSZ *PSWTPMRESPSETBUFSZ;
     273/** Pointer to a const response data struct for SWTPMCMD_SET_BUFFERSIZE. */
     274typedef const SWTPMRESPSETBUFSZ *PCSWTPMRESPSETBUFSZ;
    243275
    244276
     
    281313    /** Capabilities offered by the TPM emulator. */
    282314    uint32_t            fCaps;
     315    /** Buffer size for the emulated TPM. */
     316    uint32_t            cbBuffer;
    283317} DRVTPMEMU;
    284318/** Pointer to the TPM emulator instance data. */
     
    537571
    538572/**
     573 * Queries the maximum supported buffer size by the emulation.
     574 *
     575 * @returns VBox status code.
     576 * @param   pThis               Pointer to the TPM emulator driver instance data.
     577 * @param   pcbBufferMax        Where to store the maximum supported buffer size on success.
     578 */
     579static int drvTpmEmuQueryBufferSzMax(PDRVTPMEMU pThis, uint32_t *pcbBufferMax)
     580{
     581    SWTPMCMDSETBUFSZ Cmd;
     582    SWTPMRESPSETBUFSZ Resp;
     583    uint32_t u32Resp = 0;
     584
     585    RT_ZERO(Cmd); RT_ZERO(Resp);
     586    Cmd.cbBuffer = RT_H2BE_U32(0);
     587    int rc = drvTpmEmuExecCtrlCmdEx(pThis, SWTPMCMD_SET_BUFFERSIZE, &Cmd, sizeof(Cmd), &u32Resp,
     588                                    &Resp, sizeof(Resp), RT_MS_10SEC);
     589    if (RT_SUCCESS(rc))
     590    {
     591        if (u32Resp == 0)
     592            *pcbBufferMax = RT_BE2H_U32(Resp.cbBufferMax);
     593        else
     594            rc = VERR_NET_IO_ERROR;
     595    }
     596
     597    return rc;
     598}
     599
     600
     601/**
     602 * Queries the maximum supported buffer size by the emulation.
     603 *
     604 * @returns VBox status code.
     605 * @param   pThis               Pointer to the TPM emulator driver instance data.
     606 * @param   cbBuffer            The buffer size to set.
     607 */
     608static int drvTpmEmuSetBufferSz(PDRVTPMEMU pThis, uint32_t cbBuffer)
     609{
     610    SWTPMCMDSETBUFSZ Cmd;
     611    SWTPMRESPSETBUFSZ Resp;
     612    uint32_t u32Resp = 0;
     613
     614    RT_ZERO(Cmd); RT_ZERO(Resp);
     615    Cmd.cbBuffer = RT_H2BE_U32(cbBuffer);
     616    int rc = drvTpmEmuExecCtrlCmdEx(pThis, SWTPMCMD_SET_BUFFERSIZE, &Cmd, sizeof(Cmd), &u32Resp,
     617                                    &Resp, sizeof(Resp), RT_MS_10SEC);
     618    if (   RT_SUCCESS(rc)
     619        && u32Resp != 0)
     620        rc = VERR_NET_IO_ERROR;
     621
     622    return rc;
     623}
     624
     625
     626/**
    539627 * Sets the given locality for the emulated TPM.
    540628 *
     
    562650
    563651/** @interface_method_impl{PDMITPMCONNECTOR,pfnStartup} */
    564 static DECLCALLBACK(int) drvTpmEmuStartup(PPDMITPMCONNECTOR pInterface, size_t cbCmdResp)
    565 {
    566     RT_NOREF(cbCmdResp);
     652static DECLCALLBACK(int) drvTpmEmuStartup(PPDMITPMCONNECTOR pInterface)
     653{
    567654    PDRVTPMEMU pThis = RT_FROM_MEMBER(pInterface, DRVTPMEMU, ITpmConnector);
    568655
     
    607694    RT_NOREF(pInterface);
    608695    return 4;
     696}
     697
     698
     699/** @interface_method_impl{PDMITPMCONNECTOR,pfnGetBufferSize} */
     700static DECLCALLBACK(uint32_t) drvTpmEmuGetBufferSize(PPDMITPMCONNECTOR pInterface)
     701{
     702    PDRVTPMEMU pThis = RT_FROM_MEMBER(pInterface, DRVTPMEMU, ITpmConnector);
     703    return pThis->cbBuffer;
    609704}
    610705
     
    804899    pThis->ITpmConnector.pfnGetVersion              = drvTpmEmuGetVersion;
    805900    pThis->ITpmConnector.pfnGetLocalityMax          = drvTpmEmuGetLocalityMax;
     901    pThis->ITpmConnector.pfnGetBufferSize           = drvTpmEmuGetBufferSize;
    806902    pThis->ITpmConnector.pfnGetEstablishedFlag      = drvTpmEmuGetEstablishedFlag;
    807903    pThis->ITpmConnector.pfnResetEstablishedFlag    = drvTpmEmuResetEstablishedFlag;
     
    812908     * Validate and read the configuration.
    813909     */
    814     PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "Location", "");
     910    PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "Location|BufferSize", "");
    815911
    816912    char szLocation[_1K];
     
    9191015                                   N_("DrvTpmEmu#%d Emulated TPM version of %s does not offer required set of capabilities (%#x requested vs. %#x offered)"),
    9201016                                   pDrvIns->iInstance, szLocation, fCapsReq, pThis->fCaps);
     1017
     1018    uint32_t cbBufferMax = 0;
     1019    rc = drvTpmEmuQueryBufferSzMax(pThis, &cbBufferMax);
     1020    if (RT_FAILURE(rc))
     1021        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     1022                                   N_("DrvTpmEmu#%d failed to query maximum buffer size from %s"),
     1023                                   pDrvIns->iInstance, szLocation);
     1024
     1025    /* Configure the buffer size. */
     1026    rc = CFGMR3QueryU32Def(pCfg, "BufferSize", &pThis->cbBuffer, cbBufferMax);
     1027    if (RT_FAILURE(rc))
     1028        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     1029                                   N_("Configuration error: querying \"BufferSize\" resulted in %Rrc"), rc);
     1030
     1031    /* Set the buffer size. */
     1032    rc = drvTpmEmuSetBufferSz(pThis, pThis->cbBuffer);
     1033    if (RT_FAILURE(rc))
     1034        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     1035                                   N_("DrvTpmEmu#%d failed to set buffer size to %u for %s"),
     1036                                   pDrvIns->iInstance, pThis->cbBuffer, szLocation);
    9211037
    9221038    /* Connect the data channel now. */
  • trunk/src/VBox/Devices/Security/DrvTpmHost.cpp

    r90996 r91005  
    4545
    4646/**
     47 * TPM 1.2 buffer size capability response.
     48 */
     49#pragma pack(1)
     50typedef struct TPMRESPGETBUFSZ
     51{
     52    TPMRESPHDR                  Hdr;
     53    uint32_t                    u32Length;
     54    uint32_t                    cbBuf;
     55} TPMRESPGETBUFSZ;
     56#pragma pack()
     57typedef TPMRESPGETBUFSZ *PTPMRESPGETBUFSZ;
     58typedef const TPMRESPGETBUFSZ *PCTPMRESPGETBUFSZ;
     59
     60
     61/**
     62 * TPM 2.0 buffer size capability response.
     63 */
     64#pragma pack(1)
     65typedef struct TPM2RESPGETBUFSZ
     66{
     67    TPMRESPHDR                  Hdr;
     68    uint8_t                     fMore;
     69    uint32_t                    u32Cap;
     70    uint32_t                    u32Count;
     71    uint32_t                    u32Prop;
     72    uint32_t                    u32Value;
     73} TPM2RESPGETBUFSZ;
     74#pragma pack()
     75typedef TPM2RESPGETBUFSZ *PTPM2RESPGETBUFSZ;
     76typedef const TPM2RESPGETBUFSZ *PCTPM2RESPGETBUFSZ;
     77
     78
     79/**
    4780 * TPM Host driver instance data.
    4881 *
     
    5891    /** Handle to the host TPM. */
    5992    RTTPM               hTpm;
    60 
     93    /** Cached TPM version. */
     94    TPMVERSION          enmTpmVersion;
     95    /** Cached buffer size of the host TPM. */
     96    uint32_t            cbBuffer;
    6197} DRVTPMHOST;
    6298/** Pointer to the TPM emulator instance data. */
     
    68104*********************************************************************************************************************************/
    69105
     106/**
     107 * Queries the buffer size of the host TPM.
     108 *
     109 * @returns VBox status code.
     110 * @param   pThis               The host TPM driver instance data.
     111 */
     112static int drvTpmHostQueryBufferSize(PDRVTPMHOST pThis)
     113{
     114    uint8_t abResp[_1K];
     115    int rc = VINF_SUCCESS;
     116
     117    switch (pThis->enmTpmVersion)
     118    {
     119        case TPMVERSION_1_2:
     120        {
     121            TPMREQGETCAPABILITY Req;
     122
     123            Req.Hdr.u16Tag     = RT_H2BE_U16(TPM_TAG_RQU_COMMAND);
     124            Req.Hdr.cbReq      = RT_H2BE_U32(sizeof(Req));
     125            Req.Hdr.u32Ordinal = RT_H2BE_U32(TPM_ORD_GETCAPABILITY);
     126            Req.u32Cap         = RT_H2BE_U32(TPM_CAP_PROPERTY);
     127            Req.u32Length      = RT_H2BE_U32(sizeof(uint32_t));
     128            Req.u32SubCap      = RT_H2BE_U32(TPM_CAP_PROP_INPUT_BUFFER);
     129            rc = RTTpmReqExec(pThis->hTpm, 0 /*bLoc*/, &Req, sizeof(Req), &abResp[0], sizeof(abResp), NULL /*pcbResp*/);
     130            break;
     131        }
     132        case TPMVERSION_2_0:
     133        {
     134            TPM2REQGETCAPABILITY Req;
     135
     136            Req.Hdr.u16Tag     = RT_H2BE_U16(TPM2_ST_NO_SESSIONS);
     137            Req.Hdr.cbReq      = RT_H2BE_U32(sizeof(Req));
     138            Req.Hdr.u32Ordinal = RT_H2BE_U32(TPM2_CC_GET_CAPABILITY);
     139            Req.u32Cap         = RT_H2BE_U32(TPM2_CAP_TPM_PROPERTIES);
     140            Req.u32Property    = RT_H2BE_U32(TPM2_PT_INPUT_BUFFER);
     141            Req.u32Count       = RT_H2BE_U32(1);
     142            rc = RTTpmReqExec(pThis->hTpm, 0 /*bLoc*/, &Req, sizeof(Req), &abResp[0], sizeof(abResp), NULL /*pcbResp*/);
     143            break;
     144        }
     145        default:
     146            AssertFailed();
     147    }
     148
     149    if (RT_SUCCESS(rc))
     150    {
     151        switch (pThis->enmTpmVersion)
     152        {
     153            case TPMVERSION_1_2:
     154            {
     155                PCTPMRESPGETBUFSZ pResp = (PCTPMRESPGETBUFSZ)&abResp[0];
     156
     157                if (   RTTpmRespGetSz(&pResp->Hdr) == sizeof(*pResp)
     158                    && RT_BE2H_U32(pResp->u32Length) == sizeof(uint32_t))
     159                    pThis->cbBuffer = RT_BE2H_U32(pResp->cbBuf);
     160                else
     161                    rc = VERR_INVALID_PARAMETER;
     162                break;
     163            }
     164            case TPMVERSION_2_0:
     165            {
     166                PCTPM2RESPGETBUFSZ pResp = (PCTPM2RESPGETBUFSZ)&abResp[0];
     167
     168                if (   RTTpmRespGetSz(&pResp->Hdr) == sizeof(*pResp)
     169                    && RT_BE2H_U32(pResp->u32Count) == 1)
     170                    pThis->cbBuffer = RT_BE2H_U32(pResp->u32Value);
     171                else
     172                    rc = VERR_INVALID_PARAMETER;
     173                break;
     174            }
     175            default:
     176                AssertFailed();
     177        }
     178    }
     179
     180    return rc;
     181}
     182
     183
    70184/** @interface_method_impl{PDMITPMCONNECTOR,pfnStartup} */
    71 static DECLCALLBACK(int) drvTpmHostStartup(PPDMITPMCONNECTOR pInterface, size_t cbCmdResp)
    72 {
    73     RT_NOREF(pInterface, cbCmdResp);
     185static DECLCALLBACK(int) drvTpmHostStartup(PPDMITPMCONNECTOR pInterface)
     186{
     187    RT_NOREF(pInterface);
    74188    return VINF_SUCCESS;
    75189}
     
    96210{
    97211    PDRVTPMHOST pThis = RT_FROM_MEMBER(pInterface, DRVTPMHOST, ITpmConnector);
    98     RTTPMVERSION enmVersion = RTTpmGetVersion(pThis->hTpm);
    99 
    100     switch (enmVersion)
    101     {
    102         case RTTPMVERSION_1_2:
    103             return TPMVERSION_1_2;
    104         case RTTPMVERSION_2_0:
    105             return TPMVERSION_2_0;
    106         case RTTPMVERSION_UNKNOWN:
    107         default:
    108             return TPMVERSION_UNKNOWN;
    109     }
    110 
    111     AssertFailed(); /* Shouldn't get here. */
    112     return TPMVERSION_UNKNOWN;
     212    return pThis->enmTpmVersion;
    113213}
    114214
     
    119219    PDRVTPMHOST pThis = RT_FROM_MEMBER(pInterface, DRVTPMHOST, ITpmConnector);
    120220    return RTTpmGetLocalityMax(pThis->hTpm);
     221}
     222
     223
     224/** @interface_method_impl{PDMITPMCONNECTOR,pfnGetBufferSize} */
     225static DECLCALLBACK(uint32_t) drvTpmHostGetBufferSize(PPDMITPMCONNECTOR pInterface)
     226{
     227    PDRVTPMHOST pThis = RT_FROM_MEMBER(pInterface, DRVTPMHOST, ITpmConnector);
     228    return pThis->cbBuffer;
    121229}
    122230
     
    209317    pThis->ITpmConnector.pfnGetVersion              = drvTpmHostGetVersion;
    210318    pThis->ITpmConnector.pfnGetLocalityMax          = drvTpmHostGetLocalityMax;
     319    pThis->ITpmConnector.pfnGetBufferSize           = drvTpmHostGetBufferSize;
    211320    pThis->ITpmConnector.pfnGetEstablishedFlag      = drvTpmHostGetEstablishedFlag;
    212321    pThis->ITpmConnector.pfnResetEstablishedFlag    = drvTpmHostResetEstablishedFlag;
     
    228337    if (RT_FAILURE(rc))
    229338        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
    230                                    N_("DrvTpmHost%d: Opening TPM with id %u failed with %Rrc"), idTpm, rc);
     339                                   N_("DrvTpmHost%d: Opening TPM with id %u failed with %Rrc"), pDrvIns->iInstance, idTpm, rc);
     340
     341    RTTPMVERSION enmVersion = RTTpmGetVersion(pThis->hTpm);
     342
     343    switch (enmVersion)
     344    {
     345        case RTTPMVERSION_1_2:
     346            pThis->enmTpmVersion = TPMVERSION_1_2;
     347            break;
     348        case RTTPMVERSION_2_0:
     349            pThis->enmTpmVersion = TPMVERSION_2_0;
     350            break;
     351        case RTTPMVERSION_UNKNOWN:
     352        default:
     353            return PDMDrvHlpVMSetError(pDrvIns, VERR_NOT_SUPPORTED, RT_SRC_POS,
     354                                       N_("DrvTpmHost%d: TPM version %u of TPM id %u is not supported"),
     355                                       pDrvIns->iInstance, enmVersion, idTpm);
     356    }
     357
     358    rc = drvTpmHostQueryBufferSize(pThis);
     359    if (RT_FAILURE(rc))
     360        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     361                                   N_("DrvTpmHost%d: Querying input buffer size of TPM with id %u failed with %Rrc"), idTpm, rc);
    231362
    232363    LogRel(("DrvTpmHost#%d: Connected to TPM %u.\n", pDrvIns->iInstance, idTpm));
Note: See TracChangeset for help on using the changeset viewer.

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