alder_lake_bios/Insyde/InsydeModulePkg/Library/Tpm2ExtCommandLib/Tpm2Rsa.c

274 lines
9.4 KiB
C

/** @file
RSA encryption and decryption by Tpm2.
;******************************************************************************
;* Copyright (c) 2021, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include <IndustryStandard/UefiTcgPlatform.h>
#include <Library/Tpm2CommandLib.h>
#include <Library/Tpm2DeviceLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/Tpm2ExtCommandLib.h>
#pragma pack(1)
typedef struct {
TPM2_COMMAND_HEADER Header;
TPMI_DH_OBJECT KeyHandle;
TPM2B_PUBLIC_KEY_RSA Message;
TPMT_RSA_DECRYPT Scheme;
TPM2B_DATA Label;
} TPM2_RSA_EMCRYPT_COMMAND;
typedef struct {
TPM2_RESPONSE_HEADER Header;
TPM2B_PUBLIC_KEY_RSA Message;
} TPM2_RSA_EMCRYPT_RESPONSE;
typedef struct {
TPM2_COMMAND_HEADER Header;
TPMI_DH_OBJECT KeyHandle;
UINT32 AuthSessionSize;
TPMS_AUTH_COMMAND AuthSession;
TPM2B_PUBLIC_KEY_RSA CipherText;
TPMT_RSA_DECRYPT Scheme;
TPM2B_DATA Label;
} TPM2_RSA_DECRYPT_COMMAND;
typedef struct {
TPM2_RESPONSE_HEADER Header;
UINT32 AuthSessionSize;
TPM2B_PUBLIC_KEY_RSA Message;
TPMS_AUTH_RESPONSE AuthSession;
} TPM2_RSA_DECRYPT_RESPONSE;
#pragma pack()
/**
This command is used to RSA encryption
@param[in] KeyHandle Reference to public portion of RSA key for encryption.
@param[in] Message Message to encrypted.
@param[in] Scheme Padding scheme to use.
@param[in] SchemeWidthInBytes Use width in bytes in Scheme.
@param[in] Label Lable.
@param[in, out] OutData Encrypted output.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_DEVICE_ERROR Unexpected device behavior.
@retval EFI_UNSUPPORTED
**/
EFI_STATUS
EFIAPI
Tpm2RsaEncrypt (
IN TPMI_DH_OBJECT KeyHandle,
IN TPM2B_PUBLIC_KEY_RSA *Message,
IN TPMT_RSA_DECRYPT *Scheme,
IN UINT8 SchemeWidthInBytes,
IN TPM2B_DATA *Label,
IN OUT TPM2B_PUBLIC_KEY_RSA *OutData
)
{
EFI_STATUS Status;
TPM2_RSA_EMCRYPT_COMMAND SendBuffer;
TPM2_RSA_EMCRYPT_RESPONSE RecvBuffer;
UINT8 *Buffer;
UINT8 *SchemPtr;
UINT32 SendBufferSize;
UINT32 RecvBufferSize;
UINTN Index;
if ((Message == NULL) || (Scheme == NULL) || (SchemeWidthInBytes == 0) || (Label == NULL) || (OutData == NULL)) {
return EFI_UNSUPPORTED;
}
SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS);
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_RSA_Encrypt);
SendBuffer.KeyHandle = SwapBytes32(KeyHandle);
Buffer = (UINT8 *)&SendBuffer.Message;
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Message->size));
Buffer += sizeof(UINT16);
if (Message->size > sizeof (SendBuffer.Message.buffer)) {
Status = EFI_UNSUPPORTED;
goto Done;
}
CopyMem (Buffer, Message->buffer, Message->size);
Buffer += Message->size;
if ((SchemeWidthInBytes > sizeof (TPMT_RSA_DECRYPT)) || ((SchemeWidthInBytes % sizeof (UINT16)) != 0)) {
Status = EFI_UNSUPPORTED;
goto Done;
}
SchemPtr = (UINT8 *) Scheme;
for (Index = 0; Index < (SchemeWidthInBytes / sizeof (UINT16)); Index++) {
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (ReadUnaligned16 ((UINT16 *)SchemPtr)));
SchemPtr+= sizeof(UINT16);
Buffer += sizeof(UINT16);
}
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Label->size));
Buffer += sizeof(UINT16);
if (Label->size > sizeof (SendBuffer.Label.buffer)) {
Status = EFI_UNSUPPORTED;
goto Done;
}
CopyMem (Buffer, Label->buffer, Label->size);
Buffer += Label->size;
SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
RecvBufferSize = sizeof (RecvBuffer);
Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
if (EFI_ERROR (Status)) {
goto Done;
}
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
DEBUG ((DEBUG_ERROR, "Tpm2RsaEncrypt - RecvBufferSize Error - %x\n", RecvBufferSize));
Status = EFI_DEVICE_ERROR;
goto Done;
}
if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
DEBUG ((DEBUG_ERROR, "Tpm2RsaEncrypt - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
Status = EFI_DEVICE_ERROR;
goto Done;
}
OutData->size = SwapBytes16 (RecvBuffer.Message.size);
if (OutData->size > MAX_RSA_KEY_BYTES) {
DEBUG ((DEBUG_ERROR, "Tpm2RsaEncrypt - OutData->size error %x\n", OutData->size));
Status = EFI_DEVICE_ERROR;
goto Done;
}
CopyMem (OutData->buffer, &RecvBuffer.Message.buffer, OutData->size);
Done:
ZeroMem (&SendBuffer, sizeof(SendBuffer));
ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
return Status;
}
/**
This command is used to RSA decryption
@param[in] KeyHandle RSA key for decryption.
@param[in] AuthSession Auth Session
@param[in] CipherText Cipher text to decrypted.
@param[in] Scheme Padding scheme to use.
@param[in] SchemeWidthInBytes Use width in bytes in Scheme.
@param[in] Label Lable.
@param[in, out] Message Decrypted output.
@retval EFI_SUCCESS Operation completed successfully.
@retval EFI_DEVICE_ERROR Unexpected device behavior.
@retval EFI_UNSUPPORTED
**/
EFI_STATUS
EFIAPI
Tpm2RsaDecrypt (
IN TPMI_DH_OBJECT KeyHandle,
IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL
IN TPM2B_PUBLIC_KEY_RSA *CipherText,
IN TPMT_RSA_DECRYPT *Scheme,
IN UINT8 SchemeWidthInBytes,
IN TPM2B_DATA *Label,
IN OUT TPM2B_PUBLIC_KEY_RSA *Message
)
{
EFI_STATUS Status;
TPM2_RSA_DECRYPT_COMMAND SendBuffer;
TPM2_RSA_DECRYPT_RESPONSE RecvBuffer;
UINT8 *Buffer;
UINT8 *SchemPtr;
UINT32 SendBufferSize;
UINT32 RecvBufferSize;
UINT32 SessionInfoSize;
UINTN Index;
if ((CipherText == NULL) || (SchemeWidthInBytes == 0) ||(Scheme == NULL) || (Label == NULL) || (Message == NULL)) {
return EFI_UNSUPPORTED;
}
SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS);
SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_RSA_Decrypt);
SendBuffer.KeyHandle = SwapBytes32(KeyHandle);
Buffer = (UINT8 *)&SendBuffer.AuthSession;
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
Buffer += SessionInfoSize;
SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize);
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (CipherText->size));
Buffer += sizeof(UINT16);
if (CipherText->size > sizeof (SendBuffer.CipherText.buffer)) {
Status = EFI_UNSUPPORTED;
goto Done;
}
CopyMem (Buffer, CipherText->buffer, CipherText->size);
Buffer += CipherText->size;
if ((SchemeWidthInBytes > sizeof (TPMT_RSA_DECRYPT)) || ((SchemeWidthInBytes % sizeof (UINT16)) != 0)) {
Status = EFI_UNSUPPORTED;
goto Done;
}
SchemPtr = (UINT8 *) Scheme;
for (Index = 0; Index < (SchemeWidthInBytes / sizeof (UINT16)); Index++) {
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (ReadUnaligned16 ((UINT16 *)SchemPtr)));
SchemPtr+= sizeof(UINT16);
Buffer += sizeof(UINT16);
}
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Label->size));
Buffer += sizeof(UINT16);
if (Label->size > sizeof (SendBuffer.Label.buffer)) {
Status = EFI_UNSUPPORTED;
goto Done;
}
CopyMem (Buffer, Label->buffer, Label->size);
Buffer += Label->size;
SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer);
SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
RecvBufferSize = sizeof (RecvBuffer);
Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
if (EFI_ERROR (Status)) {
goto Done;
}
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
DEBUG ((DEBUG_ERROR, "Tpm2RsaDecrypt - RecvBufferSize Error - %x\n", RecvBufferSize));
Status = EFI_DEVICE_ERROR;
goto Done;
}
if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
DEBUG ((DEBUG_ERROR, "Tpm2RsaDecrypt - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode)));
Status = EFI_DEVICE_ERROR;
goto Done;
}
Message->size = SwapBytes16 (RecvBuffer.Message.size);
if (Message->size > MAX_RSA_KEY_BYTES) {
DEBUG ((DEBUG_ERROR, "Tpm2RsaDecrypt - OutData->size error %x\n", Message->size));
Status = EFI_DEVICE_ERROR;
goto Done;
}
CopyMem (Message->buffer, &RecvBuffer.Message.buffer, Message->size);
Done:
ZeroMem (&SendBuffer, sizeof(SendBuffer));
ZeroMem (&RecvBuffer, sizeof(RecvBuffer));
return Status;
}