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; + + // Polling for 7 seconds + while (timeout_ms > 0) { + response_length = sizeof(OEM_BMC_GET_RESULT_RESPONSE); + 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); + UINT8 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 2000 + +#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