/** @file
Implement TPM2 Object related command.
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#pragma pack(1)
typedef struct {
TPM2_COMMAND_HEADER Header;
TPMI_DH_OBJECT ObjectHandle;
} TPM2_READ_PUBLIC_COMMAND;
typedef struct {
TPM2_RESPONSE_HEADER Header;
TPM2B_PUBLIC OutPublic;
TPM2B_NAME Name;
TPM2B_NAME QualifiedName;
} TPM2_READ_PUBLIC_RESPONSE;
#pragma pack()
/**
This command allows access to the public area of a loaded object.
@param[in] ObjectHandle TPM handle of an object
@param[out] OutPublic Structure containing the public area of an object
@param[out] Name Name of the object
@param[out] QualifiedName The Qualified Name of the object
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_DEVICE_ERROR Unexpected device behavior.
**/
EFI_STATUS
EFIAPI
Tpm2ReadPublic (
IN TPMI_DH_OBJECT ObjectHandle,
OUT TPM2B_PUBLIC *OutPublic,
OUT TPM2B_NAME *Name,
OUT TPM2B_NAME *QualifiedName
)
{
EFI_STATUS Status;
TPM2_READ_PUBLIC_COMMAND SendBuffer;
TPM2_READ_PUBLIC_RESPONSE RecvBuffer;
UINT32 SendBufferSize;
UINT32 RecvBufferSize;
TPM_RC ResponseCode;
UINT8 *Buffer;
UINT16 OutPublicSize;
UINT16 NameSize;
UINT16 QualifiedNameSize;
//
// Construct command
//
SendBuffer.Header.tag = SwapBytes16 (TPM_ST_NO_SESSIONS);
SendBuffer.Header.commandCode = SwapBytes32 (TPM_CC_ReadPublic);
SendBuffer.ObjectHandle = SwapBytes32 (ObjectHandle);
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 ((DEBUG_ERROR, "Tpm2ReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize));
return EFI_DEVICE_ERROR;
}
ResponseCode = SwapBytes32 (RecvBuffer.Header.responseCode);
if (ResponseCode != TPM_RC_SUCCESS) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - responseCode - %x\n", SwapBytes32 (RecvBuffer.Header.responseCode)));
}
switch (ResponseCode) {
case TPM_RC_SUCCESS:
// return data
break;
case TPM_RC_SEQUENCE:
// objectHandle references a sequence object
return EFI_INVALID_PARAMETER;
default:
return EFI_DEVICE_ERROR;
}
//
// Basic check
//
OutPublicSize = SwapBytes16 (RecvBuffer.OutPublic.size);
if (OutPublicSize > sizeof (TPMT_PUBLIC)) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - OutPublicSize error %x\n", OutPublicSize));
return EFI_DEVICE_ERROR;
}
NameSize = SwapBytes16 (
ReadUnaligned16 (
(UINT16 *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) +
sizeof (UINT16) + OutPublicSize)
)
);
if (NameSize > sizeof (TPMU_NAME)) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - NameSize error %x\n", NameSize));
return EFI_DEVICE_ERROR;
}
QualifiedNameSize = SwapBytes16 (
ReadUnaligned16 (
(UINT16 *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) +
sizeof (UINT16) + OutPublicSize +
sizeof (UINT16) + NameSize)
)
);
if (QualifiedNameSize > sizeof (TPMU_NAME)) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - QualifiedNameSize error %x\n", QualifiedNameSize));
return EFI_DEVICE_ERROR;
}
if (RecvBufferSize != sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + OutPublicSize + sizeof (UINT16) + NameSize + sizeof (UINT16) + QualifiedNameSize) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - RecvBufferSize %x Error - OutPublicSize %x, NameSize %x, QualifiedNameSize %x\n", RecvBufferSize, OutPublicSize, NameSize, QualifiedNameSize));
return EFI_DEVICE_ERROR;
}
//
// Return the response
//
Buffer = (UINT8 *)&RecvBuffer.OutPublic;
CopyMem (OutPublic, &RecvBuffer.OutPublic, sizeof (UINT16) + OutPublicSize);
OutPublic->size = OutPublicSize;
OutPublic->publicArea.type = SwapBytes16 (OutPublic->publicArea.type);
OutPublic->publicArea.nameAlg = SwapBytes16 (OutPublic->publicArea.nameAlg);
WriteUnaligned32 ((UINT32 *)&OutPublic->publicArea.objectAttributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&OutPublic->publicArea.objectAttributes)));
Buffer = (UINT8 *)&RecvBuffer.OutPublic.publicArea.authPolicy;
OutPublic->publicArea.authPolicy.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
if (OutPublic->publicArea.authPolicy.size > sizeof (TPMU_HA)) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - authPolicy.size error %x\n", OutPublic->publicArea.authPolicy.size));
return EFI_DEVICE_ERROR;
}
CopyMem (OutPublic->publicArea.authPolicy.buffer, Buffer, OutPublic->publicArea.authPolicy.size);
Buffer += OutPublic->publicArea.authPolicy.size;
// TPMU_PUBLIC_PARMS
switch (OutPublic->publicArea.type) {
case TPM_ALG_KEYEDHASH:
OutPublic->publicArea.parameters.keyedHashDetail.scheme.scheme = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
switch (OutPublic->publicArea.parameters.keyedHashDetail.scheme.scheme) {
case TPM_ALG_HMAC:
OutPublic->publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_XOR:
OutPublic->publicArea.parameters.keyedHashDetail.scheme.details.xor.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.keyedHashDetail.scheme.details.xor.kdf = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
default:
return EFI_UNSUPPORTED;
}
case TPM_ALG_SYMCIPHER:
OutPublic->publicArea.parameters.symDetail.algorithm = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
switch (OutPublic->publicArea.parameters.symDetail.algorithm) {
case TPM_ALG_AES:
OutPublic->publicArea.parameters.symDetail.keyBits.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.symDetail.mode.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_SM4:
OutPublic->publicArea.parameters.symDetail.keyBits.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.symDetail.mode.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_XOR:
OutPublic->publicArea.parameters.symDetail.keyBits.xor = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_NULL:
break;
default:
return EFI_UNSUPPORTED;
}
break;
case TPM_ALG_RSA:
OutPublic->publicArea.parameters.rsaDetail.symmetric.algorithm = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
switch (OutPublic->publicArea.parameters.rsaDetail.symmetric.algorithm) {
case TPM_ALG_AES:
OutPublic->publicArea.parameters.rsaDetail.symmetric.keyBits.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.rsaDetail.symmetric.mode.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_SM4:
OutPublic->publicArea.parameters.rsaDetail.symmetric.keyBits.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.rsaDetail.symmetric.mode.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_NULL:
break;
default:
return EFI_UNSUPPORTED;
}
OutPublic->publicArea.parameters.rsaDetail.scheme.scheme = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
switch (OutPublic->publicArea.parameters.rsaDetail.scheme.scheme) {
case TPM_ALG_RSASSA:
OutPublic->publicArea.parameters.rsaDetail.scheme.details.rsassa.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_RSAPSS:
OutPublic->publicArea.parameters.rsaDetail.scheme.details.rsapss.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_RSAES:
break;
case TPM_ALG_OAEP:
OutPublic->publicArea.parameters.rsaDetail.scheme.details.oaep.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_NULL:
break;
default:
return EFI_UNSUPPORTED;
}
OutPublic->publicArea.parameters.rsaDetail.keyBits = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.rsaDetail.exponent = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT32);
break;
case TPM_ALG_ECC:
OutPublic->publicArea.parameters.eccDetail.symmetric.algorithm = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
switch (OutPublic->publicArea.parameters.eccDetail.symmetric.algorithm) {
case TPM_ALG_AES:
OutPublic->publicArea.parameters.eccDetail.symmetric.keyBits.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.eccDetail.symmetric.mode.aes = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_SM4:
OutPublic->publicArea.parameters.eccDetail.symmetric.keyBits.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.eccDetail.symmetric.mode.SM4 = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_NULL:
break;
default:
return EFI_UNSUPPORTED;
}
OutPublic->publicArea.parameters.eccDetail.scheme.scheme = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
switch (OutPublic->publicArea.parameters.eccDetail.scheme.scheme) {
case TPM_ALG_ECDSA:
OutPublic->publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_ECDAA:
OutPublic->publicArea.parameters.eccDetail.scheme.details.ecdaa.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_ECSCHNORR:
OutPublic->publicArea.parameters.eccDetail.scheme.details.ecSchnorr.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_ECDH:
break;
case TPM_ALG_NULL:
break;
default:
return EFI_UNSUPPORTED;
}
OutPublic->publicArea.parameters.eccDetail.curveID = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
OutPublic->publicArea.parameters.eccDetail.kdf.scheme = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
switch (OutPublic->publicArea.parameters.eccDetail.kdf.scheme) {
case TPM_ALG_MGF1:
OutPublic->publicArea.parameters.eccDetail.kdf.details.mgf1.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_KDF1_SP800_108:
OutPublic->publicArea.parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_KDF1_SP800_56a:
OutPublic->publicArea.parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_KDF2:
OutPublic->publicArea.parameters.eccDetail.kdf.details.kdf2.hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
break;
case TPM_ALG_NULL:
break;
default:
return EFI_UNSUPPORTED;
}
break;
default:
return EFI_UNSUPPORTED;
}
// TPMU_PUBLIC_ID
switch (OutPublic->publicArea.type) {
case TPM_ALG_KEYEDHASH:
OutPublic->publicArea.unique.keyedHash.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
if (OutPublic->publicArea.unique.keyedHash.size > sizeof (TPMU_HA)) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - keyedHash.size error %x\n", OutPublic->publicArea.unique.keyedHash.size));
return EFI_DEVICE_ERROR;
}
CopyMem (OutPublic->publicArea.unique.keyedHash.buffer, Buffer, OutPublic->publicArea.unique.keyedHash.size);
Buffer += OutPublic->publicArea.unique.keyedHash.size;
break;
case TPM_ALG_SYMCIPHER:
OutPublic->publicArea.unique.sym.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
if (OutPublic->publicArea.unique.sym.size > sizeof (TPMU_HA)) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - sym.size error %x\n", OutPublic->publicArea.unique.sym.size));
return EFI_DEVICE_ERROR;
}
CopyMem (OutPublic->publicArea.unique.sym.buffer, Buffer, OutPublic->publicArea.unique.sym.size);
Buffer += OutPublic->publicArea.unique.sym.size;
break;
case TPM_ALG_RSA:
OutPublic->publicArea.unique.rsa.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
if (OutPublic->publicArea.unique.rsa.size > MAX_RSA_KEY_BYTES) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - rsa.size error %x\n", OutPublic->publicArea.unique.rsa.size));
return EFI_DEVICE_ERROR;
}
CopyMem (OutPublic->publicArea.unique.rsa.buffer, Buffer, OutPublic->publicArea.unique.rsa.size);
Buffer += OutPublic->publicArea.unique.rsa.size;
break;
case TPM_ALG_ECC:
OutPublic->publicArea.unique.ecc.x.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
if (OutPublic->publicArea.unique.ecc.x.size > MAX_ECC_KEY_BYTES) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - ecc.x.size error %x\n", OutPublic->publicArea.unique.ecc.x.size));
return EFI_DEVICE_ERROR;
}
CopyMem (OutPublic->publicArea.unique.ecc.x.buffer, Buffer, OutPublic->publicArea.unique.ecc.x.size);
Buffer += OutPublic->publicArea.unique.ecc.x.size;
OutPublic->publicArea.unique.ecc.y.size = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
Buffer += sizeof (UINT16);
if (OutPublic->publicArea.unique.ecc.y.size > MAX_ECC_KEY_BYTES) {
DEBUG ((DEBUG_ERROR, "Tpm2ReadPublic - ecc.y.size error %x\n", OutPublic->publicArea.unique.ecc.y.size));
return EFI_DEVICE_ERROR;
}
CopyMem (OutPublic->publicArea.unique.ecc.y.buffer, Buffer, OutPublic->publicArea.unique.ecc.y.size);
Buffer += OutPublic->publicArea.unique.ecc.y.size;
break;
default:
return EFI_UNSUPPORTED;
}
CopyMem (Name->name, (UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + OutPublicSize + sizeof (UINT16), NameSize);
Name->size = NameSize;
CopyMem (QualifiedName->name, (UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + OutPublicSize + sizeof (UINT16) + NameSize + sizeof (UINT16), QualifiedNameSize);
QualifiedName->size = QualifiedNameSize;
return EFI_SUCCESS;
}