/** Send Shutdown command to TPM2. @param[in] ShutdownType TPM_SU_CLEAR or TPM_SU_STATE. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2Shutdown ( IN TPM_SU ShutdownType ) { EFI_STATUS Status; TPM2_SHUTDOWN_COMMAND Cmd; TPM2_SHUTDOWN_RESPONSE Res; UINT32 ResultBufSize; Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd)); Cmd.Header.commandCode = SwapBytes32(TPM_CC_Shutdown); Cmd.ShutdownType = SwapBytes16(ShutdownType); ResultBufSize = sizeof(Res); Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res); if (EFI_ERROR(Status)) { return Status; } if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2Shutdown: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** This command allows options in authorizations without requiring that the TPM evaluate all of the options. If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that satisfies the policy. This command will indicate that one of the required sets of conditions has been satisfied. @param[in] PolicySession Handle for the policy session being extended. @param[in] HashList the list of hashes to check for a match. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PolicyOR ( IN TPMI_SH_POLICY PolicySession, IN TPML_DIGEST *HashList ) { EFI_STATUS Status; TPM2_POLICY_OR_COMMAND SendBuffer; TPM2_POLICY_OR_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; UINTN Index; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyOR); SendBuffer.PolicySession = SwapBytes32 (PolicySession); Buffer = (UINT8 *)&SendBuffer.HashList; WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (HashList->count)); Buffer += sizeof(UINT32); for (Index = 0; Index < HashList->count; Index++) { WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (HashList->digests[Index].size)); Buffer += sizeof(UINT16); CopyMem (Buffer, HashList->digests[Index].buffer, HashList->digests[Index].size); Buffer += HashList->digests[Index].size; } SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** This command returns the current policyDigest of the session. This command allows the TPM to be used to perform the actions required to precompute the authPolicy for an object. @param[in] PolicySession Handle for the policy session. @param[out] PolicyHash the current value of the policyHash of policySession. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PolicyGetDigest ( IN TPMI_SH_POLICY PolicySession, OUT TPM2B_DIGEST *PolicyHash ) { EFI_STATUS Status; TPM2_POLICY_GET_DIGEST_COMMAND SendBuffer; TPM2_POLICY_GET_DIGEST_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyGetDigest); SendBuffer.PolicySession = SwapBytes32 (PolicySession); SendBufferSize = (UINT32) sizeof (SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PolicyGetDigest - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } // // Return the response // PolicyHash->size = SwapBytes16 (RecvBuffer.PolicyHash.size); if (PolicyHash->size > sizeof(TPMU_HA)) { DEBUG ((DEBUG_ERROR, "Tpm2PolicyGetDigest - PolicyHash->size error %x\n", PolicyHash->size)); return EFI_DEVICE_ERROR; } CopyMem (PolicyHash->buffer, &RecvBuffer.PolicyHash.buffer, PolicyHash->size); return EFI_SUCCESS; }
/** This command returns various information regarding the TPM and its current state. The capability parameter determines the category of data returned. The property parameter selects the first value of the selected category to be returned. If there is no property that corresponds to the value of property, the next higher value is returned, if it exists. The moreData parameter will have a value of YES if there are more values of the requested type that were not returned. If no next capability exists, the TPM will return a zero-length list and moreData will have a value of NO. NOTE: To simplify this function, leave returned CapabilityData for caller to unpack since there are many capability categories and only few categories will be used in firmware. It means the caller need swap the byte order for the feilds in CapabilityData. @param[in] Capability Group selection; determines the format of the response. @param[in] Property Further definition of information. @param[in] PropertyCount Number of properties of the indicated type to return. @param[out] MoreData Flag to indicate if there are more values of this type. @param[out] CapabilityData The capability data. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2GetCapability ( IN TPM_CAP Capability, IN UINT32 Property, IN UINT32 PropertyCount, OUT TPMI_YES_NO *MoreData, OUT TPMS_CAPABILITY_DATA *CapabilityData ) { EFI_STATUS Status; TPM2_GET_CAPABILITY_COMMAND SendBuffer; TPM2_GET_CAPABILITY_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_GetCapability); SendBuffer.Capability = SwapBytes32 (Capability); SendBuffer.Property = SwapBytes32 (Property); SendBuffer.PropertyCount = SwapBytes32 (PropertyCount); SendBufferSize = (UINT32) sizeof (SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer ); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT8)) { return EFI_DEVICE_ERROR; } // // Return the response // *MoreData = RecvBuffer.MoreData; // // Does not unpack all possiable property here, the caller should unpack it and note the byte order. // CopyMem (CapabilityData, &RecvBuffer.CapabilityData, RecvBufferSize - sizeof (TPM2_RESPONSE_HEADER) - sizeof (UINT8)); return EFI_SUCCESS; }
/** This command indicates that the authorization will be limited to a specific command code. @param[in] PolicySession Handle for the policy session being extended. @param[in] Code The allowed commandCode. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PolicyCommandCode ( IN TPMI_SH_POLICY PolicySession, IN TPM_CC Code ) { EFI_STATUS Status; TPM2_POLICY_COMMAND_CODE_COMMAND SendBuffer; TPM2_POLICY_COMMAND_CODE_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyCommandCode); SendBuffer.PolicySession = SwapBytes32 (PolicySession); SendBuffer.Code = SwapBytes32 (Code); SendBufferSize = (UINT32) sizeof (SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PolicyCommandCode - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** This command causes all context associated with a loaded object or session to be removed from TPM memory. @param[in] FlushHandle The handle of the item to flush. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2FlushContext ( IN TPMI_DH_CONTEXT FlushHandle ) { EFI_STATUS Status; TPM2_FLUSH_CONTEXT_COMMAND SendBuffer; TPM2_FLUSH_CONTEXT_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_FlushContext); SendBuffer.FlushHandle = SwapBytes32 (FlushHandle); SendBufferSize = (UINT32) sizeof (SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2FlushContext - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2FlushContext - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** This command causes the TPM to perform a test of its capabilities. If the fullTest is YES, the TPM will test all functions. If fullTest = NO, the TPM will only test those functions that have not previously been tested. @param[in] FullTest YES if full test to be performed NO if only test of untested functions required @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2SelfTest ( IN TPMI_YES_NO FullTest ) { EFI_STATUS Status; TPM2_SELF_TEST_COMMAND Cmd; TPM2_SELF_TEST_RESPONSE Res; UINT32 ResultBufSize; Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd)); Cmd.Header.commandCode = SwapBytes32(TPM_CC_SelfTest); Cmd.FullTest = FullTest; ResultBufSize = sizeof(Res); Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res); return Status; }
/** Send Startup command to TPM2. @param[in] StartupType TPM_SU_CLEAR or TPM_SU_STATE @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2Startup ( IN TPM_SU StartupType ) { EFI_STATUS Status; TPM2_STARTUP_COMMAND Cmd; TPM2_STARTUP_RESPONSE Res; UINT32 ResultBufSize; TPM_RC ResponseCode; Cmd.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd)); Cmd.Header.commandCode = SwapBytes32(TPM_CC_Startup); Cmd.StartupType = SwapBytes16(StartupType); ResultBufSize = sizeof(Res); Status = Tpm2SubmitCommand (sizeof(Cmd), (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res); if (EFI_ERROR(Status)) { return Status; } ResponseCode = SwapBytes32(Res.Header.responseCode); switch (ResponseCode) { case TPM_RC_SUCCESS: DEBUG ((DEBUG_INFO, "TPM2Startup: TPM_RC_SUCCESS\n")); return EFI_SUCCESS; case TPM_RC_INITIALIZE: // TPM_RC_INITIALIZE can be returned if Tpm2Startup is not required. DEBUG ((DEBUG_INFO, "TPM2Startup: TPM_RC_INITIALIZE\n")); return EFI_SUCCESS; default: DEBUG ((EFI_D_ERROR, "Tpm2Startup: Response Code error! 0x%08x\r\n", ResponseCode)); return EFI_DEVICE_ERROR; } }
/** This command defines the attributes of an NV Index and causes the TPM to reserve space to hold the data associated with the index. If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED. @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. @param[in] AuthSession Auth Session context @param[in] Auth The authorization data. @param[in] NvPublic The public area of the index. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. @retval EFI_ALREADY_STARTED The command was returned successfully, but NvIndex is already defined. **/ EFI_STATUS EFIAPI Tpm2NvDefineSpace ( IN TPMI_RH_PROVISION AuthHandle, IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL IN TPM2B_AUTH *Auth, IN TPM2B_NV_PUBLIC *NvPublic ) { EFI_STATUS Status; TPM2_NV_DEFINESPACE_COMMAND SendBuffer; TPM2_NV_DEFINESPACE_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT16 NvPublicSize; UINT8 *Buffer; UINT32 SessionInfoSize; TPM_RC ResponseCode; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_DefineSpace); SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); // // Add in Auth session // Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); // // IndexAuth // WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Auth->size)); Buffer += sizeof(UINT16); CopyMem(Buffer, Auth->buffer, Auth->size); Buffer += Auth->size; // // NvPublic // NvPublicSize = NvPublic->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublicSize)); Buffer += sizeof(UINT16); WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (NvPublic->nvPublic.nvIndex)); Buffer += sizeof(UINT32); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.nameAlg)); Buffer += sizeof(UINT16); WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); Buffer += sizeof(UINT32); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.authPolicy.size)); Buffer += sizeof(UINT16); CopyMem (Buffer, NvPublic->nvPublic.authPolicy.buffer, NvPublic->nvPublic.authPolicy.size); Buffer += NvPublic->nvPublic.authPolicy.size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.dataSize)); Buffer += sizeof(UINT16); SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { goto Done; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); Status = EFI_DEVICE_ERROR; goto Done; } ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); if (ResponseCode != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); } switch (ResponseCode) { case TPM_RC_SUCCESS: // return data break; case TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo: case TPM_RC_SIZE + RC_NV_DefineSpace_auth: Status = EFI_BAD_BUFFER_SIZE; break; case TPM_RC_ATTRIBUTES: case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo: Status = EFI_UNSUPPORTED; break; case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle: Status = EFI_INVALID_PARAMETER; break; case TPM_RC_NV_DEFINED: Status = EFI_ALREADY_STARTED; break; case TPM_RC_VALUE + RC_NV_DefineSpace_publicInfo: case TPM_RC_VALUE + RC_NV_DefineSpace_authHandle: Status = EFI_INVALID_PARAMETER; break; case TPM_RC_NV_SPACE: Status = EFI_OUT_OF_RESOURCES; break; default: Status = EFI_DEVICE_ERROR; break; } Done: // // Clear AuthSession Content // ZeroMem (&SendBuffer, sizeof(SendBuffer)); ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); return Status; }
/** This command is used to read the public area and Name of an NV Index. @param[in] NvIndex The NV Index. @param[out] NvPublic The public area of the index. @param[out] NvName The Name of the nvIndex. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. **/ EFI_STATUS EFIAPI Tpm2NvReadPublic ( IN TPMI_RH_NV_INDEX NvIndex, OUT TPM2B_NV_PUBLIC *NvPublic, OUT TPM2B_NAME *NvName ) { EFI_STATUS Status; TPM2_NV_READPUBLIC_COMMAND SendBuffer; TPM2_NV_READPUBLIC_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT16 NvPublicSize; UINT16 NvNameSize; UINT8 *Buffer; TPM_RC ResponseCode; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadPublic); SendBuffer.NvIndex = SwapBytes32 (NvIndex); SendBufferSize = (UINT32) sizeof (SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); if (ResponseCode != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); } switch (ResponseCode) { case TPM_RC_SUCCESS: // return data break; case TPM_RC_HANDLE + RC_NV_ReadPublic_nvIndex: // TPM_RC_NV_DEFINED: return EFI_NOT_FOUND; case TPM_RC_VALUE + RC_NV_ReadPublic_nvIndex: return EFI_INVALID_PARAMETER; default: return EFI_DEVICE_ERROR; } if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + sizeof(UINT16)) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_NOT_FOUND; } // // Basic check // NvPublicSize = SwapBytes16 (RecvBuffer.NvPublic.size); if (NvPublicSize > sizeof(TPMS_NV_PUBLIC)) { DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvPublic.size error %x\n", NvPublicSize)); return EFI_DEVICE_ERROR; } NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize))); if (NvNameSize > sizeof(TPMU_NAME)){ DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvNameSize error %x\n", NvNameSize)); return EFI_DEVICE_ERROR; } if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x\n", RecvBufferSize)); return EFI_NOT_FOUND; } // // Return the response // CopyMem (NvPublic, &RecvBuffer.NvPublic, sizeof(UINT16) + NvPublicSize); NvPublic->size = NvPublicSize; NvPublic->nvPublic.nvIndex = SwapBytes32 (NvPublic->nvPublic.nvIndex); NvPublic->nvPublic.nameAlg = SwapBytes16 (NvPublic->nvPublic.nameAlg); WriteUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); NvPublic->nvPublic.authPolicy.size = SwapBytes16 (NvPublic->nvPublic.authPolicy.size); Buffer = (UINT8 *)&RecvBuffer.NvPublic.nvPublic.authPolicy; Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size; NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer)); CopyMem (NvName->name, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16), NvNameSize); NvName->size = NvNameSize; return EFI_SUCCESS; }
// Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { goto Done; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); Status = EFI_DEVICE_ERROR; goto Done; } ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); if (ResponseCode != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2NvUndefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); } switch (ResponseCode) {
/** This command is used to start an authorization session using alternative methods of establishing the session key (sessionKey) that is used for authorization and encrypting value. @param[in] TpmKey Handle of a loaded decrypt key used to encrypt salt. @param[in] Bind Entity providing the authValue. @param[in] NonceCaller Initial nonceCaller, sets nonce size for the session. @param[in] Salt Value encrypted according to the type of tpmKey. @param[in] SessionType Indicates the type of the session. @param[in] Symmetric The algorithm and key size for parameter encryption. @param[in] AuthHash Hash algorithm to use for the session. @param[out] SessionHandle Handle for the newly created session. @param[out] NonceTPM The initial nonce from the TPM, used in the computation of the sessionKey. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2StartAuthSession ( IN TPMI_DH_OBJECT TpmKey, IN TPMI_DH_ENTITY Bind, IN TPM2B_NONCE *NonceCaller, IN TPM2B_ENCRYPTED_SECRET *Salt, IN TPM_SE SessionType, IN TPMT_SYM_DEF *Symmetric, IN TPMI_ALG_HASH AuthHash, OUT TPMI_SH_AUTH_SESSION *SessionHandle, OUT TPM2B_NONCE *NonceTPM ) { EFI_STATUS Status; TPM2_START_AUTH_SESSION_COMMAND SendBuffer; TPM2_START_AUTH_SESSION_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_StartAuthSession); SendBuffer.TpmKey = SwapBytes32 (TpmKey); SendBuffer.Bind = SwapBytes32 (Bind); Buffer = (UINT8 *)&SendBuffer.NonceCaller; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NonceCaller->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, NonceCaller->buffer, NonceCaller->size); Buffer += NonceCaller->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Salt->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, Salt->secret, Salt->size); Buffer += Salt->size; *(TPM_SE *)Buffer = SessionType; Buffer++; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->algorithm)); Buffer += sizeof(UINT16); switch (Symmetric->algorithm) { case TPM_ALG_NULL: break; case TPM_ALG_AES: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.aes)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.aes)); Buffer += sizeof(UINT16); break; case TPM_ALG_SM4: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.SM4)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.SM4)); Buffer += sizeof(UINT16); break; case TPM_ALG_SYMCIPHER: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.sym)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.sym)); Buffer += sizeof(UINT16); break; case TPM_ALG_XOR: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.xor)); Buffer += sizeof(UINT16); break; default: ASSERT (FALSE); DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - Symmetric->algorithm - %x\n", Symmetric->algorithm)); return EFI_UNSUPPORTED; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthHash)); Buffer += sizeof(UINT16); SendBufferSize = (UINT32) ((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } // // Return the response // *SessionHandle = SwapBytes32 (RecvBuffer.SessionHandle); NonceTPM->size = SwapBytes16 (RecvBuffer.NonceTPM.size); if (NonceTPM->size > sizeof(TPMU_HA)) { DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - NonceTPM->size error %x\n", NonceTPM->size)); return EFI_DEVICE_ERROR; } CopyMem (NonceTPM->buffer, &RecvBuffer.NonceTPM.buffer, NonceTPM->size); return EFI_SUCCESS; }
/** This command returns the values of all PCR specified in pcrSelect. @param[in] PcrSelectionIn The selection of PCR to read. @param[out] PcrUpdateCounter The current value of the PCR update counter. @param[out] PcrSelectionOut The PCR in the returned list. @param[out] PcrValues The contents of the PCR indicated in pcrSelect. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PcrRead ( IN TPML_PCR_SELECTION *PcrSelectionIn, OUT UINT32 *PcrUpdateCounter, OUT TPML_PCR_SELECTION *PcrSelectionOut, OUT TPML_DIGEST *PcrValues ) { EFI_STATUS Status; TPM2_PCR_READ_COMMAND SendBuffer; TPM2_PCR_READ_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINTN Index; TPML_DIGEST *PcrValuesOut; TPM2B_DIGEST *Digests; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PCR_Read); SendBuffer.PcrSelectionIn.count = SwapBytes32(PcrSelectionIn->count); for (Index = 0; Index < PcrSelectionIn->count; Index++) { SendBuffer.PcrSelectionIn.pcrSelections[Index].hash = SwapBytes16(PcrSelectionIn->pcrSelections[Index].hash); SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect = PcrSelectionIn->pcrSelections[Index].sizeofSelect; CopyMem (&SendBuffer.PcrSelectionIn.pcrSelections[Index].pcrSelect, &PcrSelectionIn->pcrSelections[Index].pcrSelect, SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect); } SendBufferSize = sizeof(SendBuffer.Header) + sizeof(SendBuffer.PcrSelectionIn.count) + sizeof(SendBuffer.PcrSelectionIn.pcrSelections[0]) * PcrSelectionIn->count; SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_NOT_FOUND; } // // Return the response // // // PcrUpdateCounter // if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } *PcrUpdateCounter = SwapBytes32(RecvBuffer.PcrUpdateCounter); // // PcrSelectionOut // if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } PcrSelectionOut->count = SwapBytes32(RecvBuffer.PcrSelectionOut.count); if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) { DEBUG ((EFI_D_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } for (Index = 0; Index < PcrSelectionOut->count; Index++) { PcrSelectionOut->pcrSelections[Index].hash = SwapBytes16(RecvBuffer.PcrSelectionOut.pcrSelections[Index].hash); PcrSelectionOut->pcrSelections[Index].sizeofSelect = RecvBuffer.PcrSelectionOut.pcrSelections[Index].sizeofSelect; CopyMem (&PcrSelectionOut->pcrSelections[Index].pcrSelect, &RecvBuffer.PcrSelectionOut.pcrSelections[Index].pcrSelect, PcrSelectionOut->pcrSelections[Index].sizeofSelect); } // // PcrValues // PcrValuesOut = (TPML_DIGEST *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof(RecvBuffer.PcrUpdateCounter) + sizeof(RecvBuffer.PcrSelectionOut.count) + sizeof(RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count); PcrValues->count = SwapBytes32(PcrValuesOut->count); Digests = PcrValuesOut->digests; for (Index = 0; Index < PcrValues->count; Index++) { PcrValues->digests[Index].size = SwapBytes16(Digests->size); CopyMem (&PcrValues->digests[Index].buffer, &Digests->buffer, PcrValues->digests[Index].size); Digests = (TPM2B_DIGEST *)((UINT8 *)Digests + sizeof(Digests->size) + PcrValues->digests[Index].size); } return EFI_SUCCESS; }
// // Add in Auth session // Buffer = (UINT8 *)&Cmd.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize); CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd); Cmd.Header.paramSize = SwapBytes32(CmdSize); ResultBufSize = sizeof(Res); Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res); if (EFI_ERROR(Status)) { return Status; } if (ResultBufSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Clear: Failed ExecuteCommand: Buffer Too Small\r\n")); return EFI_BUFFER_TOO_SMALL; } // // Validate response headers // RespSize = SwapBytes32(Res.Header.paramSize); if (RespSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Clear: Response size too large! %d\r\n", RespSize));
/** This command allows setting of the authorization policy for the platform hierarchy (platformPolicy), the storage hierarchy (ownerPolicy), and and the endorsement hierarchy (endorsementPolicy). @param[in] AuthHandle TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} parameters to be validated @param[in] AuthSession Auth Session context @param[in] AuthPolicy An authorization policy hash @param[in] HashAlg The hash algorithm to use for the policy @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2SetPrimaryPolicy ( IN TPMI_RH_HIERARCHY_AUTH AuthHandle, IN TPMS_AUTH_COMMAND *AuthSession, IN TPM2B_DIGEST *AuthPolicy, IN TPMI_ALG_HASH HashAlg ) { EFI_STATUS Status; TPM2_SET_PRIMARY_POLICY_COMMAND SendBuffer; TPM2_SET_PRIMARY_POLICY_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; UINT32 SessionInfoSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_SetPrimaryPolicy); SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); // // Add in Auth session // Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); // // Real data // WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(AuthPolicy->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, AuthPolicy->buffer, AuthPolicy->size); Buffer += AuthPolicy->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg)); Buffer += sizeof(UINT16); SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** This command includes a secret-based authorization to a policy. The caller proves knowledge of the secret value using an authorization session using the authValue associated with authHandle. @param[in] AuthHandle Handle for an entity providing the authorization @param[in] PolicySession Handle for the policy session being extended. @param[in] AuthSession Auth Session context @param[in] NonceTPM The policy nonce for the session. @param[in] CpHashA Digest of the command parameters to which this authorization is limited. @param[in] PolicyRef A reference to a policy relating to the authorization. @param[in] Expiration Time when authorization will expire, measured in seconds from the time that nonceTPM was generated. @param[out] Timeout Time value used to indicate to the TPM when the ticket expires. @param[out] PolicyTicket A ticket that includes a value indicating when the authorization expires. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PolicySecret ( IN TPMI_DH_ENTITY AuthHandle, IN TPMI_SH_POLICY PolicySession, IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL IN TPM2B_NONCE *NonceTPM, IN TPM2B_DIGEST *CpHashA, IN TPM2B_NONCE *PolicyRef, IN INT32 Expiration, OUT TPM2B_TIMEOUT *Timeout, OUT TPMT_TK_AUTH *PolicyTicket ) { EFI_STATUS Status; TPM2_POLICY_SECRET_COMMAND SendBuffer; TPM2_POLICY_SECRET_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; UINT32 SessionInfoSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicySecret); SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); SendBuffer.PolicySession = SwapBytes32 (PolicySession); // // Add in Auth session // Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); // // Real data // WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NonceTPM->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, NonceTPM->buffer, NonceTPM->size); Buffer += NonceTPM->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(CpHashA->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, CpHashA->buffer, CpHashA->size); Buffer += CpHashA->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PolicyRef->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, PolicyRef->buffer, PolicyRef->size); Buffer += PolicyRef->size; WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32((UINT32)Expiration)); Buffer += sizeof(UINT32); SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { goto Done; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize)); Status = EFI_DEVICE_ERROR; goto Done; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); Status = EFI_DEVICE_ERROR; goto Done; } // // Return the response // Buffer = (UINT8 *)&RecvBuffer.Timeout; Timeout->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); if (Timeout->size > sizeof(UINT64)) { DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - Timeout->size error %x\n", Timeout->size)); Status = EFI_DEVICE_ERROR; goto Done; } Buffer += sizeof(UINT16); CopyMem (Timeout->buffer, Buffer, Timeout->size); PolicyTicket->tag = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); Buffer += sizeof(UINT16); PolicyTicket->hierarchy = SwapBytes32(ReadUnaligned32 ((UINT32 *)Buffer)); Buffer += sizeof(UINT32); PolicyTicket->digest.size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); Buffer += sizeof(UINT16); if (PolicyTicket->digest.size > sizeof(TPMU_HA)) { DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - digest.size error %x\n", PolicyTicket->digest.size)); Status = EFI_DEVICE_ERROR; goto Done; } CopyMem (PolicyTicket->digest.buffer, Buffer, PolicyTicket->digest.size); Done: // // Clear AuthSession Content // ZeroMem (&SendBuffer, sizeof(SendBuffer)); ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); return Status; }
/** This command allows the platform to change the set of algorithms that are used by the TPM. The algorithmSet setting is a vendor-dependent value. @param[in] AuthHandle TPM_RH_PLATFORM @param[in] AuthSession Auth Session context @param[in] AlgorithmSet A TPM vendor-dependent value indicating the algorithm set selection @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2SetAlgorithmSet ( IN TPMI_RH_PLATFORM AuthHandle, IN TPMS_AUTH_COMMAND *AuthSession, IN UINT32 AlgorithmSet ) { EFI_STATUS Status; TPM2_SET_ALGORITHM_SET_COMMAND SendBuffer; TPM2_SET_ALGORITHM_SET_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; UINT32 SessionInfoSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_SetAlgorithmSet); SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); // // Add in Auth session // Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); // // Real data // WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AlgorithmSet)); Buffer += sizeof(UINT32); SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2SetAlgorithmSet - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2SetAlgorithmSet - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** This command is used to set the desired PCR allocation of PCR and algorithms. @param[in] AuthHandle TPM_RH_PLATFORM+{PP} @param[in] AuthSession Auth Session context @param[in] PcrAllocation The requested allocation @param[out] AllocationSuccess YES if the allocation succeeded @param[out] MaxPCR maximum number of PCR that may be in a bank @param[out] SizeNeeded number of octets required to satisfy the request @param[out] SizeAvailable Number of octets available. Computed before the allocation @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PcrAllocate ( IN TPMI_RH_PLATFORM AuthHandle, IN TPMS_AUTH_COMMAND *AuthSession, IN TPML_PCR_SELECTION *PcrAllocation, OUT TPMI_YES_NO *AllocationSuccess, OUT UINT32 *MaxPCR, OUT UINT32 *SizeNeeded, OUT UINT32 *SizeAvailable ) { EFI_STATUS Status; TPM2_PCR_ALLOCATE_COMMAND Cmd; TPM2_PCR_ALLOCATE_RESPONSE Res; UINT32 CmdSize; UINT32 RespSize; UINT8 *Buffer; UINT32 SessionInfoSize; UINT8 *ResultBuf; UINT32 ResultBufSize; UINTN Index; // // Construct command // Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS); Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd)); Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Allocate); Cmd.AuthHandle = SwapBytes32(AuthHandle); // // Add in Auth session // Buffer = (UINT8 *)&Cmd.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; Cmd.AuthSessionSize = SwapBytes32(SessionInfoSize); // Count WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(PcrAllocation->count)); Buffer += sizeof(UINT32); for (Index = 0; Index < PcrAllocation->count; Index++) { WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PcrAllocation->pcrSelections[Index].hash)); Buffer += sizeof(UINT16); *(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect; Buffer++; CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect); Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect; } CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd); Cmd.Header.paramSize = SwapBytes32(CmdSize); ResultBuf = (UINT8 *) &Res; ResultBufSize = sizeof(Res); // // Call the TPM // Status = Tpm2SubmitCommand ( CmdSize, (UINT8 *)&Cmd, &ResultBufSize, ResultBuf ); if (EFI_ERROR(Status)) { goto Done; } if (ResultBufSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n")); Status = EFI_BUFFER_TOO_SMALL; goto Done; } // // Validate response headers // RespSize = SwapBytes32(Res.Header.paramSize); if (RespSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize)); Status = EFI_BUFFER_TOO_SMALL; goto Done; } // // Fail if command failed // if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); Status = EFI_DEVICE_ERROR; goto Done; } // // Return the response // *AllocationSuccess = Res.AllocationSuccess; *MaxPCR = SwapBytes32(Res.MaxPCR); *SizeNeeded = SwapBytes32(Res.SizeNeeded); *SizeAvailable = SwapBytes32(Res.SizeAvailable); Done: // // Clear AuthSession Content // ZeroMem (&Cmd, sizeof(Cmd)); ZeroMem (&Res, sizeof(Res)); return Status; }
/** This command is used to cause an update to the indicated PCR. The digests parameter contains one or more tagged digest value identified by an algorithm ID. For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg). @param[in] PcrHandle Handle of the PCR @param[in] Digests List of tagged digest values to be extended @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2PcrExtend ( IN TPMI_DH_PCR PcrHandle, IN TPML_DIGEST_VALUES *Digests ) { EFI_STATUS Status; TPM2_PCR_EXTEND_COMMAND Cmd; TPM2_PCR_EXTEND_RESPONSE Res; UINT32 CmdSize; UINT32 RespSize; UINT32 ResultBufSize; UINT8 *Buffer; UINTN Index; UINT32 SessionInfoSize; UINT16 DigestSize; Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS); Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Extend); Cmd.PcrHandle = SwapBytes32(PcrHandle); // // Add in Auth session // Buffer = (UINT8 *)&Cmd.AuthSessionPcr; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer); Buffer += SessionInfoSize; Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize); //Digest Count WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Digests->count)); Buffer += sizeof(UINT32); //Digest for (Index = 0; Index < Digests->count; Index++) { WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Digests->digests[Index].hashAlg)); Buffer += sizeof(UINT16); DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg); if (DigestSize == 0) { DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg)); return EFI_DEVICE_ERROR; } CopyMem( Buffer, &Digests->digests[Index].digest, DigestSize ); Buffer += DigestSize; } CmdSize = (UINT32)((UINTN)Buffer - (UINTN)&Cmd); Cmd.Header.paramSize = SwapBytes32(CmdSize); ResultBufSize = sizeof(Res); Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res); if (EFI_ERROR(Status)) { return Status; } if (ResultBufSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n")); return EFI_BUFFER_TOO_SMALL; } // // Validate response headers // RespSize = SwapBytes32(Res.Header.paramSize); if (RespSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize)); return EFI_BUFFER_TOO_SMALL; } // // Fail if command failed // if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); return EFI_DEVICE_ERROR; } // // Unmarshal the response // // None return EFI_SUCCESS; }
/** This command is used to check to see if specific combinations of algorithm parameters are supported. @param[in] Parameters Algorithm parameters to be validated @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2TestParms ( IN TPMT_PUBLIC_PARMS *Parameters ) { EFI_STATUS Status; TPM2_TEST_PARMS_COMMAND SendBuffer; TPM2_TEST_PARMS_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_TestParms); Buffer = (UINT8 *)&SendBuffer.Parameters; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->type)); Buffer += sizeof(UINT16); switch (Parameters->type) { case TPM_ALG_KEYEDHASH: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.scheme)); Buffer += sizeof(UINT16); switch (Parameters->parameters.keyedHashDetail.scheme.scheme) { case TPM_ALG_HMAC: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.hmac.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_XOR: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.hashAlg)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.kdf)); Buffer += sizeof(UINT16); break; default: return EFI_INVALID_PARAMETER; } case TPM_ALG_SYMCIPHER: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.algorithm)); Buffer += sizeof(UINT16); switch (Parameters->parameters.symDetail.algorithm) { case TPM_ALG_AES: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.aes)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.aes)); Buffer += sizeof(UINT16); break; case TPM_ALG_SM4: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.SM4)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.SM4)); Buffer += sizeof(UINT16); break; case TPM_ALG_XOR: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.xor)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } break; case TPM_ALG_RSA: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.algorithm)); Buffer += sizeof(UINT16); switch (Parameters->parameters.rsaDetail.symmetric.algorithm) { case TPM_ALG_AES: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.aes)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.aes)); Buffer += sizeof(UINT16); break; case TPM_ALG_SM4: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.SM4)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.SM4)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.scheme)); Buffer += sizeof(UINT16); switch (Parameters->parameters.rsaDetail.scheme.scheme) { case TPM_ALG_RSASSA: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsassa.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_RSAPSS: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsapss.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_RSAES: break; case TPM_ALG_OAEP: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.oaep.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.keyBits)); Buffer += sizeof(UINT16); WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Parameters->parameters.rsaDetail.exponent)); Buffer += sizeof(UINT32); break; case TPM_ALG_ECC: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.algorithm)); Buffer += sizeof(UINT16); switch (Parameters->parameters.eccDetail.symmetric.algorithm) { case TPM_ALG_AES: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.aes)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.aes)); Buffer += sizeof(UINT16); break; case TPM_ALG_SM4: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.SM4)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.SM4)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.scheme)); Buffer += sizeof(UINT16); switch (Parameters->parameters.eccDetail.scheme.scheme) { case TPM_ALG_ECDSA: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdsa.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_ECDAA: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdaa.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_ECSCHNORR: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecSchnorr.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_ECDH: break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.curveID)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.scheme)); Buffer += sizeof(UINT16); switch (Parameters->parameters.eccDetail.kdf.scheme) { case TPM_ALG_MGF1: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.mgf1.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_KDF1_SP800_108: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_KDF1_SP800_56a: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_KDF2: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf2.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } break; default: return EFI_INVALID_PARAMETER; } SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2TestParms - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2TestParms - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_UNSUPPORTED; } return EFI_SUCCESS; }