From db1d0ec256941b1fc8c399a114c11e487fdd244a Mon Sep 17 00:00:00 2001 From: huangzq6 Date: Fri, 17 Mar 2023 08:23:29 +0000 Subject: [PATCH] fix the bug for fb and mok, do some clean code --- ...e-add-tpcm-support-with-ipmi-channel.patch | 10 +- ...ug-for-fb-and-mok-do-some-clean-code.patch | 879 ++++++++++++++++++ shim.spec | 6 +- 3 files changed, 889 insertions(+), 6 deletions(-) create mode 100644 fix-the-bug-for-fb-and-mok-do-some-clean-code.patch diff --git a/Feature-add-tpcm-support-with-ipmi-channel.patch b/Feature-add-tpcm-support-with-ipmi-channel.patch index e90d459..ba9aa2b 100644 --- a/Feature-add-tpcm-support-with-ipmi-channel.patch +++ b/Feature-add-tpcm-support-with-ipmi-channel.patch @@ -106,7 +106,7 @@ index 0000000..358fe6d + EFI_SERVICE_BINDING *service; + EFI_STATUS efi_status; + EFI_HANDLE child_dev = NULL; -+ ++ + efi_status = LibLocateProtocol(service_binding_guid, (VOID **) &service); + if (EFI_ERROR(efi_status)) { + console_print(L"LibLocateProtocol failed\n"); @@ -168,7 +168,7 @@ index 0000000..358fe6d + } + httc_util_dump_hex (L"tpcm BIOS hash output: ", output, DEFAULT_HASH_SIZE); + memcpy (content, output, DEFAULT_HASH_SIZE); -+ return EFI_SUCCESS; ++ return EFI_SUCCESS; +} + +static BOOLEAN @@ -195,7 +195,7 @@ index 0000000..358fe6d + efi_status = tpcm_ipmi->excute_ipmi_cmd(tpcm_ipmi, request, &get_tpcm_request_value, + sizeof(get_tpcm_request_value), &get_tpcm_response_value, + &response_length, NULL); -+ ++ + if (efi_status != EFI_SUCCESS) { + console_print(L"ipmi get tpcm switch failed.\n"); + return FALSE; @@ -322,7 +322,7 @@ index 0000000..358fe6d + console_print(L"Error: the tpcm measurement result does not pass, and the startup is rejected"); + } + -+out: ++out: + if(request_data){ + free(request_data); + request_data = NULL; @@ -411,7 +411,7 @@ index 0000000..8e23a84 +#define DEFAULT_HASH_SIZE 32 +#define MEASURE_DATA_MEM_SIZE 0x100000 + -+#define TPCM_TAG_REQ_COMMAND 0x000000C1 ++#define TPCM_TAG_REQ_COMMAND 0x000000C1 +#define TPCM_ORD_ExternSimpleBootMeasure 0x00001053 + +typedef struct{ diff --git a/fix-the-bug-for-fb-and-mok-do-some-clean-code.patch b/fix-the-bug-for-fb-and-mok-do-some-clean-code.patch new file mode 100644 index 0000000..90e8c51 --- /dev/null +++ b/fix-the-bug-for-fb-and-mok-do-some-clean-code.patch @@ -0,0 +1,879 @@ +From a44b48678c30e0291d5a61683a697a41918f5c47 Mon Sep 17 00:00:00 2001 +From: huangzq6 +Date: Wed, 15 Mar 2023 10:22:36 +0800 +Subject: [PATCH] fix the bug for fb and mok, do some clean code + +Signed-off-by: huangzq6 +--- + shim.c | 8 +- + tpcm.c | 494 +++++++++++++++++++++++++++++++++------------------------ + tpcm.h | 186 +++++++++++----------- + 3 files changed, 394 insertions(+), 294 deletions(-) + +diff --git a/shim.c b/shim.c +index 0119a69..2c3dbf3 100644 +--- a/shim.c ++++ b/shim.c +@@ -1899,12 +1899,18 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + efi_status = EFI_INVALID_PARAMETER; + goto done; + } +- efi_status = tpcm_ipmi_write(ImagePath, data, datasize,image_handle); ++ ++ /* ++ * measure the grub binary by the tpcm ++ */ ++ efi_status = tpcm_measure_grub(ImagePath, data, datasize, image_handle); + if (EFI_ERROR(efi_status)) { ++ perror(L"Failed to measure the grub by tpcm: %r\n", efi_status); + PrintErrors(); + ClearErrors(); + goto done; + } ++ + /* + * We need to modify the loaded image protocol entry before running + * the new binary, so back it up +diff --git a/tpcm.c b/tpcm.c +index 55f939c..24beac1 100644 +--- a/tpcm.c ++++ b/tpcm.c +@@ -1,299 +1,387 @@ ++/* ++ tpcm -- The main function file that implements the tpcm measurement. ++*/ ++ + #include "tpcm.h" + #include "shim.h" + +-#define TRANS(value) ((((UINT32)value <<24 )&0xFF000000)|(((UINT32)value<<8)&0x00FF0000)|(((UINT32)value>>8)&0x0000FF00)|(((UINT32)value>>24)&0x000000FF)) ++#define TRANS(value) \ ++ ((((UINT32)(value) << 24) & 0xFF000000) | (((UINT32)(value) << 8) & 0x00FF0000) | \ ++ (((UINT32)(value) >> 8) & 0x0000FF00) | (((UINT32)(value) >> 24) & 0x000000FF)) ++ ++#define WAIT_TIME_UNIT 200 + + static EFI_GUID hash2_service_binding_guid = SHIM_EFI_HASH2_SERVICE_BINDING_PROTOCOL_GUID; + static EFI_GUID hash2_guid = SHIM_EFI_HASH2_PROTOCOL_GUID; + static EFI_GUID sm3_guid = SHIM_HASH_ALGORITHM_SM3_GUID; + static EFI_GUID gIpmiInterfaceProtocolGuid = EFI_TPCM_GUID; + ++static UINT8 oemSignature[OEM_SIG_SIZE] = {0xDB, 0x07, 0x00}; ++ + static shim_efi_ipmi_interface_protocol_t *tpcm_ipmi; + static UINT32 bm_stage_base = 1500; + +-static void httc_util_dump_hex (const CHAR16 *name, void *p, int bytes) ++static void tpcm_dump_hex(const CHAR16 *name, void *p, int bytes) + { +- +- int i = 0; +- char *data = p; +- int add_newline = 1; +- console_print(L"%s length=%d:\n", name, bytes); +- if (bytes != 0) { +- console_print(L"%02x ", (unsigned char)data[i]); +- i++; ++ int i = 0; ++ unsigned char *data = p; ++ int add_newline = 1; ++ ++ console_print(L"%s length=%d:\n", name, bytes); ++ while (i < bytes) { ++ console_print(L"%02x ", (unsigned char)data[i]); ++ i++; ++ if (i % 16 == 0) { ++ console_print(L"\n"); ++ add_newline = 0; ++ } else { ++ add_newline = 1; + } +- while (i < bytes) { +- console_print(L"%02x ", (unsigned char)data[i]); +- i++; +- if (i % 16 == 0) { +- console_print(L"\n"); +- add_newline = 0; +- } else { +- add_newline = 1; +- } ++ } ++ if (add_newline) { ++ console_print(L"\n"); ++ } ++} ++ ++static EFI_STATUS tpcm_get_response_blocked(void) ++{ ++ shim_ipmi_cmd_header request = {IPMI_BMC_LUN, IPMI_NETFN_OEM, IPMI_CMD_GET_MEASURE_PARM}; ++ OEM_BMC_GET_RESULT_REQUSET get_result_request_data; ++ OEM_BMC_GET_RESULT_RESPONSE get_result_response_data; ++ UINT16 timeout_ms = SHIM_IPMI_TIMEOUT_MS; ++ UINT8 response_length; ++ EFI_STATUS efi_status; ++ ++ memset(&get_result_request_data, 0, sizeof(get_result_request_data)); ++ memset(&get_result_response_data, 0, sizeof(get_result_response_data)); ++ ++ get_result_request_data.OemSignature[0] = oemSignature[0]; ++ get_result_request_data.OemSignature[1] = oemSignature[1]; ++ get_result_request_data.OemSignature[OEM_SIG_SIZE - 1] = oemSignature[OEM_SIG_SIZE - 1]; ++ get_result_request_data.SubCmd = IPMI_SUB_CMD_CONTROL_REQ; ++ get_result_request_data.FirmwareType = IPMI_FW_SHIM_GRUB; ++ get_result_request_data.FirmwareDetailType = IPMI_FW_DETAIL_GRUB; ++ ++ response_length = sizeof(OEM_BMC_GET_RESULT_RESPONSE); ++ ++ while (timeout_ms > 0) { ++ msleep(WAIT_TIME_UNIT); ++ timeout_ms -= WAIT_TIME_UNIT; ++ ++ console_print(L"get result request: request_size[%d], response_length[%d]\n", ++ sizeof(get_result_request_data), response_length); ++ efi_status = tpcm_ipmi->excute_ipmi_cmd(tpcm_ipmi, request, &get_result_request_data, ++ sizeof(get_result_request_data), &get_result_response_data, &response_length, NULL); ++ console_print(L"OemSignature iana = [ 0x%X %X %X ], ControlResult = %d\n", ++ get_result_response_data.OemSignature[0], ++ get_result_response_data.OemSignature[1], ++ get_result_response_data.OemSignature[OEM_SIG_SIZE - 1], ++ get_result_response_data.ControlResult); ++ if (efi_status != EFI_SUCCESS) { ++ console_print(L"EFI : attempt to get measurement result failed, ret=%d\n", efi_status); ++ continue; + } +- if (add_newline) { +- console_print(L"\n"); ++ if (response_length == sizeof(OEM_BMC_GET_RESULT_RESPONSE) && ++ get_result_response_data.ControlResult != IPMI_MEASURE_UNKNOW) { ++ console_print(L"ipmi protocol: get tpcm measurement result success\n"); ++ break; + } ++ } ++ ++ if (get_result_response_data.ControlResult == IPMI_MEASURE_SUCCESS) { ++ efi_status = EFI_SUCCESS; ++ } else { ++ efi_status = EFI_INVALID_PARAMETER; ++ console_print(L"Error: the tpcm measurement result does not pass, and the startup is rejected"); ++ } ++ ++ return efi_status; + } + +-static EFI_HANDLE +-shim_efi_service_binding (EFI_GUID *service_binding_guid, EFI_HANDLE image_handle) ++static EFI_STATUS tpcm_fillup_hash_content(OEM_BMC_MEASURE_REQUSET *request_data, unsigned char *content, ++ CHAR16 *description) ++{ ++ UINT32 filename_len = StrLen(description) * 2 + 1; ++ UINT32 stage_base = bm_stage_base++; ++ ++ if (filename_len > FIRMWARE_NAME_SIZE) { ++ console_print(L"the path strings is pass the size of FirmwareHashContent.uaObj!\n"); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ console_print(L"start filling the hash content.\n"); ++ request_data->FirmwareHashContent.uiCmdTag = TRANS(TPCM_TAG_REQ_COMMAND); ++ request_data->FirmwareHashContent.uiCmdLength = TRANS(sizeof(extern_simple_bmeasure_req_st)); ++ request_data->FirmwareHashContent.uiCmdCode = TRANS(TPCM_ORD_ExternSimpleBootMeasure); ++ request_data->FirmwareHashContent.uiPcr = TRANS(0); ++ ++ request_data->FirmwareHashContent.uiStage = TRANS(stage_base); ++ ++ memcpy((UINT8 *)(request_data->FirmwareHashContent.uaDigest), content, DEFAULT_HASH_SIZE); ++ request_data->FirmwareHashContent.uiObjLen = TRANS(filename_len); ++ ++ memcpy((UINT8 *)(request_data->FirmwareHashContent.uaObj), description, filename_len); ++ request_data->FirmwareHashContent.uaObj[filename_len - 1] = '\0'; ++ ++ return EFI_SUCCESS; ++} ++ ++static EFI_STATUS tpcm_send_request(unsigned char *content, CHAR16 *description) ++{ ++ EFI_STATUS efi_status = EFI_SUCCESS; ++ shim_ipmi_cmd_header request = {IPMI_BMC_LUN, IPMI_NETFN_OEM, IPMI_CMD_GET_MEASURE_PARM}; ++ OEM_BMC_MEASURE_REQUSET request_data; ++ OEM_BMC_MEASURE_RESPONSE response_data; ++ UINT8 response_length = sizeof(OEM_BMC_MEASURE_RESPONSE); ++ UINT32 cmd_len = sizeof(extern_simple_bmeasure_req_st); ++ ++ memset(&request_data, 0, sizeof(request_data)); ++ memset(&response_data, 0, sizeof(response_data)); ++ ++ request_data.OemSignature[0] = oemSignature[0]; ++ request_data.OemSignature[1] = oemSignature[1]; ++ request_data.OemSignature[OEM_SIG_SIZE - 1] = oemSignature[OEM_SIG_SIZE - 1]; ++ request_data.SubCmd = IPMI_SUB_CMD_MEASURE_REQ; ++ request_data.FirmwareType = IPMI_FW_SHIM_GRUB; ++ request_data.FirmwareDetailType = IPMI_FW_DETAIL_GRUB; ++ request_data.FirmwareHashAlgorithmType = SM3_HASH; ++ request_data.FirmwareHashLen = cmd_len; ++ ++ /* filling the hash content of request data */ ++ efi_status = tpcm_fillup_hash_content(&request_data, content, description); ++ if (efi_status != EFI_SUCCESS) { ++ goto out; ++ } ++ console_print(L"sizeof(request_data)=%d\n", sizeof(request_data)); ++ ++ /* send the hash request to tpcm chips by ipmi */ ++ efi_status = tpcm_ipmi->excute_ipmi_cmd(tpcm_ipmi, request, &request_data, (UINT8)sizeof(OEM_BMC_MEASURE_REQUSET), ++ &response_data, &response_length, NULL); ++ if (efi_status != EFI_SUCCESS) { ++ console_print(L"ipmi protocol: excute_ipmi_cmd send request failed.\n"); ++ goto out; ++ } ++ console_print(L"ipmi protocol: send tpcm measure request success\n"); ++ ++out: ++ return efi_status; ++} ++ ++static EFI_HANDLE tpcm_efi_service_binding(EFI_GUID *service_binding_guid, EFI_HANDLE image_handle) + { +- EFI_SERVICE_BINDING *service; + EFI_STATUS efi_status; ++ EFI_SERVICE_BINDING *service = NULL; + EFI_HANDLE child_dev = NULL; +- +- efi_status = LibLocateProtocol(service_binding_guid, (VOID **) &service); ++ ++ efi_status = LibLocateProtocol(service_binding_guid, (VOID **)&service); + if (EFI_ERROR(efi_status)) { + console_print(L"LibLocateProtocol failed\n"); +- return NULL; ++ return NULL; + } + if (!service) { + console_print(L"couldn't open efi service binding protocol\n"); + return NULL; + } +- efi_status = service->CreateChild(service, &child_dev); +- if (EFI_ERROR(efi_status)) { ++ efi_status = service->CreateChild(service, &child_dev); ++ if (EFI_ERROR(efi_status)) { + console_print(L"Failed to create child device of http service %x\n", efi_status); + return NULL; +- } ++ } ++ + return child_dev; + } + +-static EFI_STATUS +-shim_efi_hash (unsigned char *buf, size_t size, EFI_HANDLE image_handle, unsigned char *content) ++static EFI_STATUS tpcm_efi_hash2(shim_efi_hash2_protocol_t *hash2, unsigned char *buf, size_t size, ++ unsigned char *output) + { +- EFI_STATUS efi_status = EFI_SUCCESS; +- shim_efi_hash2_protocol_t *hash2; +- EFI_HANDLE hash_handle = NULL; +- unsigned char output[DEFAULT_HASH_SIZE] = {0}; +- console_print(L"shim_efi_hash binding service.\n"); +- hash_handle = shim_efi_service_binding (&hash2_service_binding_guid, image_handle); +- if (!hash_handle) { +- console_print(L"hash2 service binding failed.\n"); +- return EFI_INVALID_PARAMETER; +- } +- console_print(L"shim_efi_hash binding service success.\n"); +- +- efi_status = gBS->OpenProtocol(hash_handle, &hash2_guid, +- (VOID **) &hash2, image_handle, NULL, +- EFI_OPEN_PROTOCOL_GET_PROTOCOL); +- if (EFI_ERROR(efi_status)) { +- console_print(L"shim_efi_hash: gBS->OpenProtocol fail\n"); +- return efi_status; +- } +- if (!hash2) { +- console_print(L"hash2 protocol open failed.\n"); +- return EFI_INVALID_PARAMETER; ++ EFI_STATUS efi_status; ++ ++ if (!hash2->hash_init || !hash2->hash_update || !hash2->hash_final) { ++ efi_status = EFI_INVALID_PARAMETER; ++ console_print(L"the functions of hash2 has NULL!\n"); ++ goto out; + } +- console_print(L"shim_efi_hash get protocol success.\n"); + efi_status = hash2->hash_init(hash2, &sm3_guid); + if (efi_status != EFI_SUCCESS) { + console_print(L"hash_init failed.\n"); +- return efi_status; ++ goto out; + } + efi_status = hash2->hash_update(hash2, buf, size); + if (efi_status != EFI_SUCCESS) { + console_print(L"hash_update failed.\n"); +- return efi_status; ++ goto out; + } + efi_status = hash2->hash_final(hash2, (shim_efi_hash2_output *)output); + if (efi_status != EFI_SUCCESS) { + console_print(L"hash_final failed.\n"); +- return efi_status; ++ goto out; + } +- httc_util_dump_hex (L"tpcm BIOS hash output: ", output, DEFAULT_HASH_SIZE); +- memcpy (content, output, DEFAULT_HASH_SIZE); +- return EFI_SUCCESS; ++ ++out: ++ return efi_status; + } + +-static BOOLEAN +-shim_tpcm_measure_switch () ++static EFI_STATUS tpcm_get_hash(unsigned char *buf, size_t size, EFI_HANDLE image_handle, unsigned char *content) + { + EFI_STATUS efi_status = EFI_SUCCESS; +- shim_ipmi_cmd_header request = {IPMI_BMC_LUN, +- IPMI_NETFN_OEM, +- IPMI_CMD_GET_MEASURE_PARM}; +- OEM_BMC_GET_RESULT_REQUSET get_tpcm_request_value; +- OEM_BMC_GET_RESULT_RESPONSE get_tpcm_response_value; +- UINT8 response_length; ++ shim_efi_hash2_protocol_t *hash2 = NULL; ++ EFI_HANDLE hash_handle = NULL; ++ unsigned char output[DEFAULT_HASH_SIZE] = {0}; + +- memset(&get_tpcm_request_value, 0, sizeof(get_tpcm_request_value)); +- memset(&get_tpcm_response_value, 0, sizeof(get_tpcm_response_value)); +- get_tpcm_request_value.OemSignature[0] = 0xDB; +- get_tpcm_request_value.OemSignature[1] = 0x07; +- get_tpcm_request_value.OemSignature[2] = 0x00; +- get_tpcm_request_value.SubCmd = IPMI_SUB_CMD_SWITCH_REQ; +- get_tpcm_request_value.FirmwareType = IPMI_FW_OS; +- get_tpcm_request_value.FirmwareDetailType = IPMI_FW_DETAIL_GRUB; +- response_length = sizeof(OEM_BMC_GET_RESULT_RESPONSE); ++ console_print(L"tpcm_get_hash start binding service.\n"); ++ hash_handle = tpcm_efi_service_binding(&hash2_service_binding_guid, image_handle); ++ if (!hash_handle) { ++ console_print(L"hash2 service binding failed.\n"); ++ efi_status = EFI_INVALID_PARAMETER; ++ goto out; ++ } ++ console_print(L"tpcm_get_hash binding service success.\n"); + +- efi_status = tpcm_ipmi->excute_ipmi_cmd(tpcm_ipmi, request, &get_tpcm_request_value, +- sizeof(get_tpcm_request_value), &get_tpcm_response_value, +- &response_length, NULL); +- +- if (efi_status != EFI_SUCCESS) { +- console_print(L"ipmi get tpcm switch failed.\n"); +- return FALSE; ++ efi_status = gBS->OpenProtocol( ++ hash_handle, &hash2_guid, (VOID **)&hash2, image_handle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (EFI_ERROR(efi_status)) { ++ console_print(L"tpcm_get_hash: gBS->OpenProtocol fail\n"); ++ goto out; ++ } ++ if (!hash2) { ++ console_print(L"hash2 protocol open failed.\n"); ++ efi_status = EFI_INVALID_PARAMETER; ++ goto out; + } ++ console_print(L"tpcm_get_hash get protocol success.\n"); + +- if (get_tpcm_response_value.ControlResult != IPMI_SWITCH_OPEN) { +- console_print(L"tpcm switch close, skip measure.\n"); +- return FALSE; ++ efi_status = tpcm_efi_hash2(hash2, buf, size, output); ++ if (efi_status != EFI_SUCCESS) { ++ console_print(L"tpcm_efi_hash2 failed.\n"); ++ goto out; + } + +- return TRUE; +-} ++ tpcm_dump_hex(L"tpcm BIOS hash output: ", output, DEFAULT_HASH_SIZE); ++ memcpy(content, output, DEFAULT_HASH_SIZE); + +-static void +-shim_tpcm_fillup_content (OEM_BMC_MEASURE_REQUSET *request_data, unsigned char *output, CHAR16 *description) +-{ +- UINT32 filename_len = StrLen (description) * 2 + 1; +- request_data->FirmwareHashContent.uiCmdTag = TRANS (TPCM_TAG_REQ_COMMAND); +- request_data->FirmwareHashContent.uiCmdLength = TRANS (sizeof (extern_simple_bmeasure_req_st)); +- request_data->FirmwareHashContent.uiCmdCode = TRANS (TPCM_ORD_ExternSimpleBootMeasure); +- request_data->FirmwareHashContent.uiPcr = TRANS (0); +- +- UINT32 stage_base = bm_stage_base++; +- request_data->FirmwareHashContent.uiStage = TRANS (stage_base); +- +- memcpy ((UINT8 *)(request_data->FirmwareHashContent.uaDigest), +- output, DEFAULT_HASH_SIZE); +- request_data->FirmwareHashContent.uiObjLen = TRANS (filename_len); +- +- memcpy ((UINT8 *)(request_data->FirmwareHashContent.uaObj), +- description, filename_len); +- request_data->FirmwareHashContent.uaObj[filename_len - 1] = '\0'; ++out: ++ return efi_status; + } + +-static EFI_STATUS +-shim_tpcm_log_event (unsigned char *buf, size_t size, CHAR16 *description, EFI_HANDLE image_handle) ++static EFI_STATUS tpcm_do_measure(unsigned char *buf, size_t size, CHAR16 *description, EFI_HANDLE image_handle) + { +- EFI_STATUS efi_status = EFI_SUCCESS; +- shim_ipmi_cmd_header request = {IPMI_BMC_LUN, +- IPMI_NETFN_OEM, +- IPMI_CMD_GET_MEASURE_PARM}; +- OEM_BMC_MEASURE_REQUSET *request_data = NULL; +- OEM_BMC_MEASURE_RESPONSE response_data; +- OEM_BMC_GET_RESULT_REQUSET get_result_request_data; +- OEM_BMC_GET_RESULT_RESPONSE get_result_response_data; +- +- unsigned char output[DEFAULT_HASH_SIZE] = {0}; +- UINT8 response_length; +- UINT16 timeout_ms = SHIM_IPMI_TIMEOUT_MS; +- UINT32 cmd_len = sizeof(extern_simple_bmeasure_req_st); ++ EFI_STATUS efi_status; ++ unsigned char content[DEFAULT_HASH_SIZE] = {0}; + +- request_data = (OEM_BMC_MEASURE_REQUSET *)malloc(sizeof(OEM_BMC_MEASURE_REQUSET)); +- memset(request_data, 0, sizeof(OEM_BMC_MEASURE_REQUSET)); +- memset(&response_data, 0, sizeof(response_data)); +- memset(&get_result_request_data, 0, sizeof(get_result_request_data)); +- memset(&get_result_response_data, 0, sizeof(get_result_response_data)); +-console_print(L"shim start\n"); +- request_data->OemSignature[0] = 0xDB; +- request_data->OemSignature[1] = 0x07; +- request_data->OemSignature[2] = 0x00; +- request_data->SubCmd = IPMI_SUB_CMD_MEASURE_REQ; +- request_data->FirmwareType = IPMI_FW_SHIM_GRUB; +- request_data->FirmwareDetailType = IPMI_FW_DETAIL_GRUB; +- request_data->FirmwareHashAlgorithmType = SM3_HASH; +- get_result_request_data.FirmwareDetailType = IPMI_FW_DETAIL_GRUB; +- response_length = sizeof(OEM_BMC_MEASURE_RESPONSE); +-//计算grub度量 +-// 是否需要判断 +- //efi_status = get_firmware_hash_content(buf, size, output, image_handle); +- efi_status = shim_efi_hash (buf, size, image_handle, output); ++ /* step1: get the hash of grub */ ++ efi_status = tpcm_get_hash(buf, size, image_handle, content); + if (efi_status != EFI_SUCCESS) { + console_print(L"get firmware hash content failed\n"); + goto out; + } +- request_data->FirmwareHashLen = cmd_len; +- shim_tpcm_fillup_content (request_data, output, description); + +- console_print(L"get_firmware_hash_content\n"); +- console_print(L"sizeof(request_data)=%d\n", sizeof(request_data)); +- console_print(L"sizeof(OEM_BMC_MEASURE_REQUSET)=%d\n", sizeof(OEM_BMC_MEASURE_REQUSET)); ++ /* step2: send the measure request to tpcm */ ++ efi_status = tpcm_send_request(content, description); ++ if (efi_status != EFI_SUCCESS) { ++ console_print(L"tpcm_send_request send request failed\n"); ++ goto out; ++ } + +-//发送度量请求 +- efi_status = tpcm_ipmi->excute_ipmi_cmd(tpcm_ipmi, request, request_data, +- (UINT8) sizeof(OEM_BMC_MEASURE_REQUSET), &response_data, +- &response_length, NULL); ++ /* step3: get the result of measure request */ ++ efi_status = tpcm_get_response_blocked(); + if (efi_status != EFI_SUCCESS) { +- console_print(L"ipmi protocol open failed\n"); ++ console_print(L"tpcm_get_response_blocked get result failed\n"); + goto out; + } +- console_print(L"ipmi protocol: send tpcm measure request success\n"); + +-//获取度量结果 +- get_result_request_data.OemSignature[0] = 0xDB; +- get_result_request_data.OemSignature[1] = 0x07; +- get_result_request_data.OemSignature[2] = 0x00; +- get_result_request_data.SubCmd = IPMI_SUB_CMD_CONTROL_REQ; +- get_result_request_data.FirmwareType = IPMI_FW_SHIM_GRUB; ++out: ++ return efi_status; ++} + ++static BOOLEAN tpcm_get_switch(void) ++{ ++ UINT8 response_length; ++ EFI_STATUS efi_status = EFI_SUCCESS; ++ shim_ipmi_cmd_header request = {IPMI_BMC_LUN, IPMI_NETFN_OEM, IPMI_CMD_GET_MEASURE_PARM}; ++ OEM_BMC_GET_RESULT_REQUSET get_tpcm_request_value; ++ OEM_BMC_GET_RESULT_RESPONSE get_tpcm_response_value; ++ ++ memset(&get_tpcm_request_value, 0, sizeof(get_tpcm_request_value)); ++ memset(&get_tpcm_response_value, 0, sizeof(get_tpcm_response_value)); ++ ++ get_tpcm_request_value.OemSignature[0] = oemSignature[0]; ++ get_tpcm_request_value.OemSignature[1] = oemSignature[1]; ++ get_tpcm_request_value.OemSignature[OEM_SIG_SIZE - 1] = oemSignature[OEM_SIG_SIZE - 1]; ++ get_tpcm_request_value.SubCmd = IPMI_SUB_CMD_SWITCH_REQ; ++ get_tpcm_request_value.FirmwareType = IPMI_FW_OS; ++ get_tpcm_request_value.FirmwareDetailType = IPMI_FW_DETAIL_GRUB; + response_length = sizeof(OEM_BMC_GET_RESULT_RESPONSE); + +- while (timeout_ms > 0) { +- msleep(200); +- timeout_ms -= 200; +- console_print(L"get result request: request_size[%d], response_length[%d]\n", sizeof(get_result_request_data), response_length); +- efi_status = tpcm_ipmi->excute_ipmi_cmd(tpcm_ipmi, request, &get_result_request_data, +- sizeof(get_result_request_data), &get_result_response_data, +- &response_length, NULL); +- console_print(L"huawe iana = [ 0x%X %X %X ], ControlResult = %d\n", get_result_response_data.OemSignature[0], get_result_response_data.OemSignature[1], get_result_response_data.OemSignature[2], get_result_response_data.ControlResult); +- if (efi_status != EFI_SUCCESS) { +- console_print(L"EFI : attempt to get measurement result failed, ret=%d\n", efi_status); +- continue; +- } +- if (response_length == sizeof(OEM_BMC_GET_RESULT_RESPONSE) && get_result_response_data.ControlResult != IPMI_MEASURE_UNKNOW) { +- console_print(L"ipmi protocol: get tpcm measurement result success\n"); +- break; +- } ++ if (!tpcm_ipmi->excute_ipmi_cmd) { ++ console_print(L"tpcm_ipmi->excute_ipmi_cmd is NULL, some error may occur below shim!\n"); ++ return FALSE; + } +- +-// 决定是否启动grub +- if (get_result_response_data.ControlResult == IPMI_MEASURE_SUCCESS) { +- efi_status = EFI_SUCCESS; +- } else { +- efi_status = EFI_INVALID_PARAMETER; +- console_print(L"Error: the tpcm measurement result does not pass, and the startup is rejected"); ++ efi_status = tpcm_ipmi->excute_ipmi_cmd(tpcm_ipmi, request, &get_tpcm_request_value, sizeof(get_tpcm_request_value), ++ &get_tpcm_response_value, &response_length, NULL); ++ if (efi_status != EFI_SUCCESS) { ++ console_print(L"ipmi get tpcm switch failed.\n"); ++ return FALSE; + } + +-out: +- if(request_data){ +- free(request_data); +- request_data = NULL; ++ if (get_tpcm_response_value.ControlResult != IPMI_SWITCH_OPEN) { ++ console_print(L"tpcm switch close, skip measure.\n"); ++ return FALSE; + } +- return efi_status; ++ ++ return TRUE; + } + +-static EFI_STATUS +-tpcm_ipmi_measure (unsigned char *buf, size_t size, void *description, EFI_HANDLE image_handle) ++static EFI_STATUS tpcm_check_ipmi(void) + { + EFI_STATUS efi_status; +- BOOLEAN switch_flag = TRUE; +- efi_status = LibLocateProtocol(&gIpmiInterfaceProtocolGuid, +- (VOID **) &tpcm_ipmi); +- if (EFI_ERROR(efi_status)) +- return EFI_SUCCESS; // support no tpcm scenes ++ ++ efi_status = LibLocateProtocol(&gIpmiInterfaceProtocolGuid, (VOID **)&tpcm_ipmi); ++ if (EFI_ERROR(efi_status)) { ++ console_print(L"tpcm is not support."); ++ return EFI_INVALID_PARAMETER; ++ } + if (!tpcm_ipmi) { + console_print(L"Error: tpcm_ipmi is NULL"); + return EFI_INVALID_PARAMETER; + } + +- switch_flag = shim_tpcm_measure_switch(); +- if (switch_flag == TRUE) { +- return shim_tpcm_log_event(buf, size, description, image_handle); +- } + return EFI_SUCCESS; + } + +-EFI_STATUS +-tpcm_ipmi_write (void *context __attribute__ ((unused)), unsigned char *buf, size_t size, EFI_HANDLE image_handle) ++static EFI_STATUS tpcm_ipmi_measure(unsigned char *buf, size_t size, void *description, EFI_HANDLE image_handle) + { + EFI_STATUS efi_status; +- efi_status = tpcm_ipmi_measure (buf, size, context, image_handle); +- return efi_status; ++ BOOLEAN switch_flag = FALSE; ++ ++ /* step1: check if the tpcm chips is existed. */ ++ efi_status = tpcm_check_ipmi(); ++ if (EFI_ERROR(efi_status)) { ++ return EFI_SUCCESS; ++ } ++ ++ /* step2: check if the tpcm switch is on. */ ++ switch_flag = tpcm_get_switch(); ++ ++ /* step3: do measure if the tpcm switch is on. */ ++ if (switch_flag == TRUE) { ++ return tpcm_do_measure(buf, size, description, image_handle); ++ } ++ ++ return EFI_SUCCESS; + } + ++EFI_STATUS ++tpcm_measure_grub(void *context, unsigned char *buf, size_t size, EFI_HANDLE image_handle) ++{ ++ if (context == NULL || buf == NULL || size <= 0) { ++ perror(L"the parameter passed to tpcm_measure_grub is error!\n"); ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (StrCmp((CHAR16 *)context, DEFAULT_LOADER)) { ++ console_print(L"only grub is measured by tpcm, not for FALLBACK and MOK_MANAGER.\n"); ++ return EFI_SUCCESS; ++ } + ++ return tpcm_ipmi_measure(buf, size, context, image_handle); ++} +\ No newline at end of file +diff --git a/tpcm.h b/tpcm.h +index 8e23a84..60e1979 100644 +--- a/tpcm.h ++++ b/tpcm.h +@@ -16,87 +16,106 @@ + + #include + +-#define EFI_TPCM_GUID {0xa37e200e, 0xda90, 0x473b, {0x8b, 0xb5, 0x1d, 0x7b, 0x11, 0xba, 0x32, 0x33}} +-#define SHIM_EFI_HASH2_SERVICE_BINDING_PROTOCOL_GUID {0xda836f8d, 0x217f, 0x4ca0, { 0x99, 0xc2, 0x1c, 0xa4, 0xe1, 0x60, 0x77, 0xea}} +-#define SHIM_EFI_HASH2_PROTOCOL_GUID {0x55b1d734, 0xc5e1, 0x49db, { 0x96, 0x47, 0xb1, 0x6a, 0xfb, 0xe, 0x30, 0x5b}} +-#define SHIM_HASH_ALGORITHM_SM3_GUID {0x9DCD754B, 0x3479, 0x27AD, { 0x56, 0x4C, 0x68, 0x7C, 0x68, 0xEC, 0xF9, 0xB9}} +- +-#define OEM_SIG_SIZE 3 +-#define FIRMWARE_VERSION_SIZE 32 +-#define FIRMWARE_HASH_CONYENT_SIZE 32 +-#define FIRMWARE_NAME_SIZE 32 +-#define SHIM_IPMI_TIMEOUT_MS 7000 +-// +-// LUN +-// +-#define IPMI_BMC_LUN 0x00 +-// Net Function Definition +-#define IPMI_NETFN_OEM 0x30 +- +-#define IPMI_CMD_GET_MEASURE_PARM 0x92 //change a name +- +-#define IPMI_SUB_CMD_MEASURE_REQ 0x57 //change a name +-#define IPMI_SUB_CMD_CONTROL_REQ 0x58 +-#define IPMI_SUB_CMD_SWITCH_REQ 0x59 +- +-//bmeasure ++#define EFI_TPCM_GUID \ ++ { \ ++ 0xa37e200e, 0xda90, 0x473b, \ ++ { \ ++ 0x8b, 0xb5, 0x1d, 0x7b, 0x11, 0xba, 0x32, 0x33 \ ++ } \ ++ } ++#define SHIM_EFI_HASH2_SERVICE_BINDING_PROTOCOL_GUID \ ++ { \ ++ 0xda836f8d, 0x217f, 0x4ca0, \ ++ { \ ++ 0x99, 0xc2, 0x1c, 0xa4, 0xe1, 0x60, 0x77, 0xea \ ++ } \ ++ } ++#define SHIM_EFI_HASH2_PROTOCOL_GUID \ ++ { \ ++ 0x55b1d734, 0xc5e1, 0x49db, \ ++ { \ ++ 0x96, 0x47, 0xb1, 0x6a, 0xfb, 0xe, 0x30, 0x5b \ ++ } \ ++ } ++#define SHIM_HASH_ALGORITHM_SM3_GUID \ ++ { \ ++ 0x9DCD754B, 0x3479, 0x27AD, \ ++ { \ ++ 0x56, 0x4C, 0x68, 0x7C, 0x68, 0xEC, 0xF9, 0xB9 \ ++ } \ ++ } ++ ++#define OEM_SIG_SIZE 3 ++#define FIRMWARE_VERSION_SIZE 32 ++#define FIRMWARE_HASH_CONYENT_SIZE 32 ++#define FIRMWARE_NAME_SIZE 32 ++#define SHIM_IPMI_TIMEOUT_MS 7000 ++ ++#define IPMI_BMC_LUN 0x00 ++/* Net Function Definition */ ++#define IPMI_NETFN_OEM 0x30 ++ ++#define IPMI_CMD_GET_MEASURE_PARM 0x92 // change a name ++ ++#define IPMI_SUB_CMD_MEASURE_REQ 0x57 // change a name ++#define IPMI_SUB_CMD_CONTROL_REQ 0x58 ++#define IPMI_SUB_CMD_SWITCH_REQ 0x59 ++ + #define DEFAULT_HASH_SIZE 32 +-#define MEASURE_DATA_MEM_SIZE 0x100000 +- +-#define TPCM_TAG_REQ_COMMAND 0x000000C1 +-#define TPCM_ORD_ExternSimpleBootMeasure 0x00001053 +- +-typedef struct{ +- UINT32 uiCmdTag; +- UINT32 uiCmdLength; +- UINT32 uiCmdCode; +- UINT32 uiPcr; +- UINT32 uiStage; +- UINT8 uaDigest[DEFAULT_HASH_SIZE]; +- UINT32 uiObjLen; +- UINT8 uaObj[FIRMWARE_NAME_SIZE]; +-}extern_simple_bmeasure_req_st; ++#define MEASURE_DATA_MEM_SIZE 0x100000 ++ ++#define TPCM_TAG_REQ_COMMAND 0x000000C1 ++#define TPCM_ORD_ExternSimpleBootMeasure 0x00001053 + + typedef struct { +- UINT8 OemSignature[OEM_SIG_SIZE]; +- UINT8 SubCmd; +- UINT8 FirmwareType; +- UINT8 FirmwareDetailType; +- UINT8 FirmwareHashAlgorithmType; +- UINT8 FirmwareHashLen; +- extern_simple_bmeasure_req_st FirmwareHashContent; +- UINT8 FirmwareVerionLen; +- UINT8 FirmwareVerion[FIRMWARE_VERSION_SIZE]; ++ UINT32 uiCmdTag; ++ UINT32 uiCmdLength; ++ UINT32 uiCmdCode; ++ UINT32 uiPcr; ++ UINT32 uiStage; ++ UINT8 uaDigest[DEFAULT_HASH_SIZE]; ++ UINT32 uiObjLen; ++ UINT8 uaObj[FIRMWARE_NAME_SIZE]; ++} extern_simple_bmeasure_req_st; ++ ++typedef struct { ++ UINT8 OemSignature[OEM_SIG_SIZE]; ++ UINT8 SubCmd; ++ UINT8 FirmwareType; ++ UINT8 FirmwareDetailType; ++ UINT8 FirmwareHashAlgorithmType; ++ UINT8 FirmwareHashLen; ++ extern_simple_bmeasure_req_st FirmwareHashContent; ++ UINT8 FirmwareVerionLen; ++ UINT8 FirmwareVerion[FIRMWARE_VERSION_SIZE]; + } OEM_BMC_MEASURE_REQUSET; + + typedef struct { +- UINT8 CompletionCode; +- UINT8 OemSignature[OEM_SIG_SIZE]; ++ UINT8 CompletionCode; ++ UINT8 OemSignature[OEM_SIG_SIZE]; + } OEM_BMC_MEASURE_RESPONSE; + + typedef struct { +- UINT8 OemSignature[OEM_SIG_SIZE]; +- UINT8 SubCmd; +- UINT8 FirmwareType; +- UINT8 FirmwareDetailType; ++ UINT8 OemSignature[OEM_SIG_SIZE]; ++ UINT8 SubCmd; ++ UINT8 FirmwareType; ++ UINT8 FirmwareDetailType; + } OEM_BMC_GET_RESULT_REQUSET; + + typedef struct { +-// UINT8 CompletionCode; +- UINT8 OemSignature[OEM_SIG_SIZE]; +- UINT8 ControlResult; ++ UINT8 OemSignature[OEM_SIG_SIZE]; ++ UINT8 ControlResult; + } OEM_BMC_GET_RESULT_RESPONSE; + + typedef enum { + IPMI_SYSTEM_INTERFACE_UNKNOWN, // IPMI_SYSTEM_INTERFACE_TYPE->UNKNOWN + IPMI_SYSTEM_INTERFACE_KCS, + IPMI_SYSTEM_INTERFACE_SMIC, +- IPMI_SYSTEM_INTERFACE_BT, // IPMI_SYSTEM_INTERFACE_TYPE->BT ++ IPMI_SYSTEM_INTERFACE_BT, // IPMI_SYSTEM_INTERFACE_TYPE->BT + IPMI_SYSTEM_INTERFACE_SSIF, +- IPMI_SYSTEM_INTERFACE_MAX_TYPE // IPMI_SYSTEM_INTERFACE_TYPE->MAX_TYPE ++ IPMI_SYSTEM_INTERFACE_MAX_TYPE // IPMI_SYSTEM_INTERFACE_TYPE->MAX_TYPE + } shim_ipmi_system_interface_type; + +- + typedef struct { + UINT8 lun : 2; + UINT8 net_fn : 6; +@@ -105,7 +124,7 @@ typedef struct { + + typedef enum { + IPMI_MEMORY, +- IPMI_IO, // IPMI_IO ++ IPMI_IO, + IPMI_MAX_INTERFACE_ADDRESS_TYPE + } shim_ipmi_interface_address_type; + +@@ -150,46 +169,33 @@ typedef union { + } shim_efi_hash2_output; + + struct shim_efi_hash2_protocol { +- EFI_STATUS (*get_hash_size) (struct shim_efi_hash2_protocol *this, +- EFI_GUID *hash_algorithm, +- UINT64 hash_size); ++ EFI_STATUS (*get_hash_size)(struct shim_efi_hash2_protocol *this, EFI_GUID *hash_algorithm, UINT64 hash_size); + +- EFI_STATUS (*hash) (struct shim_efi_hash2_protocol *this, +- EFI_GUID *hash_algorithm, +- UINT8 *message, +- UINT64 message_size, +- shim_efi_hash2_output *hash); ++ EFI_STATUS (*hash) ++ (struct shim_efi_hash2_protocol *this, EFI_GUID *hash_algorithm, UINT8 *message, UINT64 message_size, ++ shim_efi_hash2_output *hash); + +- EFI_STATUS (*hash_init) (struct shim_efi_hash2_protocol *this, +- EFI_GUID *hash_algorithm); ++ EFI_STATUS (*hash_init)(struct shim_efi_hash2_protocol *this, EFI_GUID *hash_algorithm); + +- EFI_STATUS (*hash_update) (struct shim_efi_hash2_protocol *this, +- UINT8 *message, +- UINT64 message_size); ++ EFI_STATUS (*hash_update)(struct shim_efi_hash2_protocol *this, UINT8 *message, UINT64 message_size); + +- EFI_STATUS (*hash_final) (struct shim_efi_hash2_protocol *this, +- shim_efi_hash2_output *hash); ++ EFI_STATUS (*hash_final)(struct shim_efi_hash2_protocol *this, shim_efi_hash2_output *hash); + }; + + typedef struct shim_efi_hash2_protocol shim_efi_hash2_protocol_t; + +-struct shim_efi_ipmi_interface_protocol +-{ +- EFI_STATUS (*excute_ipmi_cmd) (struct shim_efi_ipmi_interface_protocol *this, +- shim_ipmi_cmd_header request, +- void *send_data, +- UINT8 send_length, +- void *recv_data, +- UINT8 *recv_length, +- UINT16 *status_codes); +- shim_ipmi_system_interface_type (*get_ipmi_interface_type) (struct shim_efi_ipmi_interface_protocol *this); +- UINT16 (*get_ipmi_base_address) (struct shim_efi_ipmi_interface_protocol *this); +- shim_ipmi_interface_address_type (*get_ipmi_base_address_type) (struct shim_efi_ipmi_interface_protocol *this); +- UINT8 (*get_ipmi_version) (struct shim_efi_ipmi_interface_protocol *this); ++struct shim_efi_ipmi_interface_protocol { ++ EFI_STATUS (*excute_ipmi_cmd) ++ (struct shim_efi_ipmi_interface_protocol *this, shim_ipmi_cmd_header request, void *send_data, UINT8 send_length, ++ void *recv_data, UINT8 *recv_length, UINT16 *status_codes); ++ shim_ipmi_system_interface_type (*get_ipmi_interface_type)(struct shim_efi_ipmi_interface_protocol *this); ++ UINT16 (*get_ipmi_base_address)(struct shim_efi_ipmi_interface_protocol *this); ++ shim_ipmi_interface_address_type (*get_ipmi_base_address_type)(struct shim_efi_ipmi_interface_protocol *this); ++ UINT8 (*get_ipmi_version)(struct shim_efi_ipmi_interface_protocol *this); + }; + + typedef struct shim_efi_ipmi_interface_protocol shim_efi_ipmi_interface_protocol_t; + +-EFI_STATUS tpcm_ipmi_write (void *context __attribute__ ((unused)), unsigned char *buf, size_t size, EFI_HANDLE image_handle); ++EFI_STATUS tpcm_measure_grub(void *context, unsigned char *buf, size_t size, EFI_HANDLE image_handle); + + #endif +-- +2.23.0 + + diff --git a/shim.spec b/shim.spec index ae75211..dd25a5b 100644 --- a/shim.spec +++ b/shim.spec @@ -22,7 +22,7 @@ Name: shim Version: 15 -Release: 28 +Release: 29 Summary: First-stage UEFI bootloader ExclusiveArch: x86_64 aarch64 License: BSD @@ -57,6 +57,7 @@ Patch22: backport-CVE-2023-0286.patch # Feature Patch9000: Feature-add-tpcm-support-with-ipmi-channel.patch +Patch9001: fix-the-bug-for-fb-and-mok-do-some-clean-code.patch BuildRequires: elfutils-libelf-devel openssl-devel openssl git pesign gnu-efi gnu-efi-devel gcc Requires: dbxtool efi-filesystem mokutil @@ -155,6 +156,9 @@ cd .. /usr/src/debug/%{name}-%{version}-%{release}/* %changelog +* Fri Mar 17 2023 huangzq6 - 15-29 +- fix the bug for fb and mok, do some clean code. + * Wed Mar 8 2023 huangzq6 - 15-28 - support no tpcm scenes temporary -- Gitee